ラベル wix の投稿を表示しています。 すべての投稿を表示
ラベル wix の投稿を表示しています。 すべての投稿を表示

2026年4月24日金曜日

WIX で VCRuntime のインストール忘備録2

前回の記事は WIX で VCRuntime のインストール忘備録
アプリケーションを実行していると、以下の行で例外が発生(Access Violation)する環境がある
        std::lock_guard<std::mutex> lock(connection_string_mutex_);
デバッグのログを色々と埋め込んで状況を絞り込んで検証していったところ
AIにより

という状況に辿りついた。
インストーラでRuntimeのチェックをしていたが、どんどん新しいRuntimeが出て、
それでも動作するので、Runtimeのバージョンチェックをするのは得策でないという結論になり、
インストーラでのチェックを諦めたのだが、これは何とかしたい

そこで、古いバージョンで動かないRuntimeがインストールされている時だけエラーにする処理を模索した
        <!-- x86 版 -->
        <!-- Minor バージョン番号を整数で取得 -->
        <Property Id="VC_REDIST_MINOR_X86" Secure="yes">
          <RegistrySearch Id="VCRedistMinorX86"
            Root="HKLM"
            Key="SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86"
            Name="Minor"
            Type="raw"
            Win64="no" />
        </Property>

        <Condition Message="Visual C++ 2022 Redistributable (x86) 14.37 以降が必要です。&#10;vc_redist.x86.exe をインストールしてください。">
          NOT (VC_REDIST_MINOR_X86 AND VC_REDIST_MINOR_X86 &lt; "#37")
        </Condition>


        <!-- x64 版 -->
        <!-- Minor バージョン番号を整数で取得 -->
        <Property Id="VC_REDIST_MINOR_X64" Secure="yes">
          <RegistrySearch Id="VCRedistMinorX64"
            Root="HKLM"
            Key="SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64"
            Name="Minor"
            Type="raw" />
        </Property>

        <!-- Minor が存在して 37 未満の場合のみエラー -->
        <Condition Message="Visual C++ 2022 Redistributable (x64) 14.37 以降が必要です。&#10;vc_redist.x64.exe をインストールしてください。">
          NOT (VC_REDIST_MINOR_X64 AND VC_REDIST_MINOR_X64 &lt; "#37")
        </Condition>
いやはや、AIの進化は凄まじい。AIの助けなしだと1週間は時間を取られていたかもしれない。

2022年5月18日水曜日

WIX で VCRuntime のインストール忘備録

そろそろ VCのRUNTIMEをVisual Studio 2019に移行しとかないと、コンパイルできないライブラリが増えてきたかな?と思いまして、2015 から 2019 に引き上げました。
WIXを使ったインストーラで、2019用のVC runtime のマージモジュールを探したが見つかりません。
ほぇ?と思って検索したらマージモジュールを使用したコンポーネントの再配布に書いてありました。

Visual Studio 2019 以降、Visual C++ 再頒布可能ファイルのマージ モジュールは非推奨です
Visual Studio 2019 以降、Visual C++ 再頒布可能ファイルのマージ モジュールは非推奨です
Visual Studio 2019 以降、Visual C++ 再頒布可能ファイルのマージ モジュールは非推奨です
ふぁ???
という事で、VC Runtime がインストールされているかどうかチェックが必要になりました
Wix per user installer to detect the Visual C++ 2015 Redistributableにチェック方法がありました。StackOverflowさまさまです
How to check if the Microsoft Visual C++ Runtime is installedにも詳細が記述されてましたが、こちらだとサービスパックが追加される毎に対応が必要そうで、ちょっと重たい。

という事で、
<Product ...>
  ...
vc runtime 2015 x86 のインストール状況プロパティ
  <!-- C++ 2015 -->
  <Property Id="CPPRUNTIME2015X86" Secure="yes">
    <RegistrySearch Id="mfc140x86_23026" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{74d0e5db-b326-4dae-a6b2-445b9de1836e}" Type="raw" />
    <RegistrySearch Id="mfc140x86_24215" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{e2803110-78b3-4664-a479-3611a381656a}" Type="raw" />
  </Property>
vc runtime 2017 x86 のインストール状況プロパティ
  <!-- C++ 2017 -->
  <Property Id="CPPRUNTIME2017X86" Secure="yes">
    <RegistrySearch Id="mfc1416x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.16,bundle" Type="raw" />
  </Property>
vc runtime 2019 x86 のインストール状況プロパティ
  <!-- C++ 2019 -->
  <Property Id="CPPRUNTIME2019X86" Secure="yes">
    <?foreach CPPRUNTIMEVERSIONPREFIX in 21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40?>
      <RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
    <?endforeach ?>
  </Property>
vc runtime 2019 x86 がインストールされていないと、インストールを中止する条件の追加
  <!-- インストール時にC++ 2019 Runtime(x86) がインストールされているかチェック -->
  <Condition Message="Microsoft Visual C++ 2019 (x86) Redistributable missing">
    <![CDATA[Installed Or CPPRUNTIME2019X86]]>
  </Condition>
vc runtime 2015 x64 のインストール状況プロパティ
  <!-- C++ 2015 -->
  <Property Id="CPPRUNTIME2015X64" Secure="yes">
    <RegistrySearch Id="mfc140x64_23026" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{e46eca4f-393b-40df-9f49-076faf788d83}" Type="raw" />
    <RegistrySearch Id="mfc140x64_24215" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{d992c12e-cab2-426f-bde3-fb8c53950b0d}" Type="raw" />
  </Property>
vc runtime 2017 x64 のインストール状況プロパティ
  <!-- C++ 2017 -->
  <Property Id="CPPRUNTIME2017X64" Secure="yes">
    <RegistrySearch Id="mfc1416x64" Root="HKCR" Key="Installer\Dependencies\VC,redist.x64,amd64,14.16,bundle" Type="raw" />
  </Property>
vc runtime 2019 x64 のインストール状況プロパティ
  <!-- C++ 2019 -->
  <Property Id="CPPRUNTIME2019X64" Secure="yes">
    <?foreach CPPRUNTIMEVERSIONPREFIX in 21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40?>
      <RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x64" Root="HKCR" Key="Installer\Dependencies\VC,redist.x64,amd64,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
    <?endforeach ?>
  </Property>
vc runtime 2019 x64 がインストールされていないと、インストールを中止する条件の追加
  <!-- インストール時にC++ 2019 Runtime(x64) がインストールされているかチェック -->
  <Condition Message="Microsoft Visual C++ 2019 (x64) Redistributable missing">
    <![CDATA[Installed Or CPPRUNTIME2019X64]]>
  </Condition>
vc runtime 2010 x64 のマージモジュールを追加
  <Directory Id="System64Folder">
   <!-- VC100 ATL Runtime -->
   <Merge Id="Microsoft_VC100_ATL_x64.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_ATL_x64.msm" />
   <Merge Id="Microsoft_VC100_CRT_x64.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_CRT_x64.msm" />
   <Merge Id="Microsoft_VC100_MFCLOC_x64.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_MFCLOC_x64.msm" />
   <Merge Id="Microsoft_VC100_MFC_x64.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_MFC_x64.msm" />
   <Merge Id="Microsoft_VC100_OpenMP_x64.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_OpenMP_x64.msm" />
  </Directory>
vc runtime 2010 x86 のマージモジュールを追加
  <Directory Id="SystemFolder">
      <!-- VC100 ATL Runtime -->
      <Merge Id="Microsoft_VC100_ATL_x86.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_ATL_x86.msm" />
      <Merge Id="Microsoft_VC100_CRT_x86.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_CRT_x86.msm" />
      <Merge Id="Microsoft_VC100_MFCLOC_x86.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_MFCLOC_x86.msm" />
      <Merge Id="Microsoft_VC100_MFC_x86.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_MFC_x86.msm" />
      <Merge Id="Microsoft_VC100_OpenMP_x86.msm" Language="0" DiskId="1" SourceFile="C:/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC100_OpenMP_x86.msm" />
  </Directory>
vc runtime 2010 x64 と x86 のマージモジュールを参照
  <Feature ...>
      <!-- VC10 runtime -->
      <MergeRef Id="Microsoft_VC100_ATL_x64.msm" />
      <MergeRef Id="Microsoft_VC100_CRT_x64.msm" />
      <MergeRef Id="Microsoft_VC100_MFCLOC_x64.msm" />
      <MergeRef Id="Microsoft_VC100_MFC_x64.msm" />
      <MergeRef Id="Microsoft_VC100_OpenMP_x64.msm" />
      <!-- VC10 runtime -->
      <MergeRef Id="Microsoft_VC100_ATL_x86.msm" />
      <MergeRef Id="Microsoft_VC100_CRT_x86.msm" />
      <MergeRef Id="Microsoft_VC100_MFCLOC_x86.msm" />
      <MergeRef Id="Microsoft_VC100_MFC_x86.msm" />
      <MergeRef Id="Microsoft_VC100_OpenMP_x86.msm" />
  </Feature>
  ...
</Product>
というように対応できそうです。

2025/05/20 追記: CPPRUNTIMEVERSIONPREFIX が想定した番号を超えていた。Microsoft Visual C++ 2019 (x64) Redistributable missing というメッセージが出てインストーラが動作しない。という事で、インストーラを下記のように番号を増やしたのだが、この番号、どこまで互換性があるのか…というより、チェックするのも面倒くさくなってきた。readme.md かなんかに、vc runtime が必須ですと書いて、チェックいらないんじゃね?と思った。
  <!-- C++ 2019 -->
  <Property Id="CPPRUNTIME2019X86" Secure="yes">
    <?foreach CPPRUNTIMEVERSIONPREFIX in 21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50?>
      <RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
    <?endforeach ?>
  </Property>
2025/12/08 追記:
Visual Studio 2026 が出て、プラットフォームツールセット: v145 になりました。
こいつ、下位互換性は有りますが、上位互換性は有りません。下位バージョンのruntimeだと、static メンバーの初期化がうまく動作しません。
よって、バージョンを切り分ける必要がありそうです。
  <!-- C++ 2026 -->
  <Property Id="CPPRUNTIME2026X86" Secure="yes">
    <?foreach CPPRUNTIMEVERSIONPREFIX in 50;51;52;53;54;55;56;57;58;59;60?>
      <RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
    <?endforeach ?>
  </Property>

2021年12月6日月曜日

WixFirewallExtension 忘備録

Windows Install Wix で Firewall を追加しようとした時に、いろいろ躓いたので忘備録

コマンドラインからでも、以下のようにすればFirewallを制御できるので
netsh advfirewall firewall add rule name="test" dir="in" action="allow" program="c:\Proguram Files\Foo\x.exe" description="test description" enable="yes" profile="any"
カスタム・アクションを定義してやれば、要件はクリアしそうである。
<CustomAction Id="CA_01_BYPASSFIREWALL" ExeCommand='netsh advfirewall firewall add ...' Directory="Foo" Execute="deferred" Impersonate="no" Return="check" />
<CustomAction Id="CA_02_REMOVEFIREWALL" ExeCommand='netsh advfirewall firewall del ...' Directory="Foo" Execute="deferred" Impersonate="no" Return="check" />
<InstallExecuteSequence>
  <Custom Action="CA_02_REMOVEFIREWALL" Before="InstallFinalize">REMOVE="ALL"</Custom>
  <Custom Action="CA_01_BYPASSFIREWALL" Before="InstallFinalize">not (REMOVE="ALL")</Custom>
</InstallExecuteSequence>
上記は試してません

WixFirewallExtension を使用すると、ファイヤーウォールを制御できます。
プロジェクトのソリューション・エクスプローラのReferencesを右クリックして、「参照の追加」を選択し、Program Files\Wix Toolset v3.11\bin\WixFirewallExtension.dll を追加します。
Product.wxsに FirewallExtension の namespace を追加します。
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:fw="http://schemas.microsoft.com/wix/FirewallExtension">
x64 のコンポーネントだと FirewallExtension が x86 コンポーネントのため、怒られてしまいます。
そのため、x86 のプログラム・フォルダにFirewallのコンポーネントを追加します。
      <Directory Id="ProgramFilesFolder" Name="ProgramFiles86Folder">
        <!-- Firewall -->
        <Component Id="grpcFirewallException" Guid="2B6866D0-0F1F-4579-84A7-87CDE9F57640" KeyPath="yes">
          <fw:FirewallException Id="anyFirewallException" Program="[INSTALLFOLDER]x.exe" Description="BYPASS:x.exe network port" Name="Foo Firewall Exception" Scope="any" />
        </Component>
      </Directory>
      
      
      ...
      <Fragment>
        <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
          ...
          <ComponentRef Id="anyFirewallException"/>
        </ComponentGroup>
      </Fragment>
としてやればOKです。