Windows のインストーラーで、 .NET Framework をインストールさせたかったので調べました。
InstallShield はウィザードから選択するだけで、 .NET Framework がなければインストールさせることができたのですが、 Inno Setup は実装する必要があるようです。
環境
- Windows 10 Pro
- Inno Setup 5.5.9
.NET Framework がインストールされていることをチェックする
簡単にコマンドで結果が得られるかな?と思っていましたが、レジストリーをチェックする必要があるみたいでした。
.NET Framework 1~4.0 の場合
.NET Framework 1~4.0 までは、次のレジストリーを調べれば良いみたいです。
To find .NET Framework versions by viewing the registry (.NET Framework 1-4)
…略…
In the Registry Editor, open the following subkey:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP
The installed versions are listed under the NDP subkey. The version number is stored in the Version entry. For the .NET Framework 4 the Version entry is under the Client or Full subkey (under NDP), or under both subkeys.
Note
The “NET Framework Setup” folder in the registry does not begin with a period.
How to: Determine which .NET Framework versions are installed | Microsoft Docs
NDP
の下の Version
エントリーを確認すれば良いみたいです。
.NET Framework 4.0 については、 NDP
の下に次のサブキーが登録されているようです。
- Clinet Profile:
NDP\Client
- 完全な .NET Framework:
NDP\Full
Client Profile?
Client Profile は次のようなもののようです。
.NET Framework 4 Client Profile は、クライアント アプリケーション用に最適化された .NET Framework 4 のサブセットです。 WPF (Windows Presentation Foundation)、Windows フォーム、WCF (Windows Communication Foundation)、および ClickOnce の機能を含むほとんどのクライアント アプリケーション向けの機能が用意されています。 これにより、.NET Framework 4 Client Profile を対象とするアプリケーションの配置が速くなり、インストール パッケージが小さくなります。
…略…
.NET Framework 4 Client Profile に含まれていない機能
.NET Framework 4 Client Profile には、次の機能は含まれていません。 アプリケーションでこれらの機能を使用するには、.NET Framework 4 をインストールする必要があります。
- ASP.NET
- Windows Communication Foundation (WCF) の高度な機能
- .NET Framework Oracle 用データ プロバイダー
- コンパイルに使用する MSBuild
これを .NET Framework がインストールされていると判断するか、しないか、あると思いまして。 インストーラーを作成するような、クライアント向けに作成したアプリケーションであれば、 .NET Framework がインストールされていると判断しても良さそうです。
そのアプリケーションが、なぜか、クライアント向けであるにもかかわらず、 ASP.NET で実装されたウェブアプリケーションだったりすると、話はまた別だと思いますけど。 このあたりは、 “含まれていない機能” を参考に判断すれば良さそうです。
.NET Framework 4.5 and later の場合
.NET Framework 4.5 以降は、次のレジストリーを調べれば良いみたいです。
To find .NET Framework versions by viewing the registry (.NET Framework 4.5 and later)
In the Registry Editor, open the following subkey:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
Note
that the path to the Full subkey includes the subkey Net Framework rather than .NET Framework.
Check for a DWORD value named Release. The existence of the Release DWORD indicates that the .NET Framework 4.5 or newer has been installed on that computer.
How to: Determine which .NET Framework versions are installed | Microsoft Docs
NDP\v4\Full
の Release
をチェックすれば良いみたいです。
リンク先に Release
の値とバージョンの対応の表があるので、それに従って制御する必要がありそうです。
Inno Setup での実装
このチェックを Inno Setup のスクリプトで実装してくれている方がいるようでした。
InitializeSetup
関数の中に記述されているバージョンとサービスパックの指定を要件に合うように変えてあげれば良さそうです。
必要であればメッセージボックスの制御も変えます。
チェックのタイミングは、 [Files]
セクションの Source
の行に Check: function
とつけて、ファイルをコピーする前のタイミングでチェックしているようです。
チェックが False であれば、ファイルをコピーしないし、 .NET Framework もインストールしないイメージかな。
.NET Framework をインストールさせる
まず、 .NET Framework のインストーラーを探しました。
.NET Framework 4.7.1 (Offline Installer)
次のリンクからオフラインインストーラーをダウンロードしました。
Web Installer でも良いと思いますが、 setup.exe のインストーラーで完結する形にしたかったので、オフラインインストーラーをダウンロードしました。
.NET Framework の配置ガイドです。
- .NET Framework deployment guide for developers | Microsoft Docs
- .NET Framework Deployment Guide for Administrators | Microsoft Docs
Chaining by using the default .NET Framework UI
To silently chain the .NET Framework installation process and let the .NET Framework installer provide the UI, add the following command to your setup program:
<.NET Framework redistributable> /q /norestart /ChainingPackage <PackageName>
…略…
/norestart
Prevents the setup program from rebooting automatically. If you use this option, the chaining app has to capture the return code and handle rebooting (see Getting Progress Information from an Installation Package in the MSDN Library).
/q
Sets quiet mode.
.NET Framework deployment guide for developers | Microsoft Docs
インストーラーに含めて、その中で実行する場合は、 /norestart と /q オプションをつけるようです。
/norestart は、自動的に再起動させないためのオプションのようです。 これをつける場合は、呼び出す側でリターンコードを受け取って、後で再起動をさせる(自動でも手動でも)ようにする必要があるようです。
/q は、 .NET Framework 自体のインストーラーのプログレスウィンドウを表示しないためのオプションのようです。
Inno Setup での実装
次のリンクに同様の QA がありました。
.NET Framework のインストーラーを起動するには、 Exec
を使えば良さそうです。
リターンコードは Exec
の 6 つ目の引数で受け取れるようです。
それから、 [File]
セクションの Source
の行に、 AfterInstall: procedure
をつけることで、コピーした後にスクリプトを実行することができるようです。
Inno Setup のコード
調べたことをまとめて、次のようなコードになりました。
[Files]
Source: "testsetup\NDP471-KB4033342-x86-x64-AllOS-ENU.exe"; DestDir: {tmp}; Flags: deleteafterinstall; AfterInstall: InstallFramework; Check: not InitializeSetup
[Code]
// [Inno Setup: Verify that .NET 4.0 is installed - Stack Overflow](https://stackoverflow.com/questions/4104011/inno-setup-verify-that-net-4-0-is-installed)
// [www.kynosarges.de/DotNetVersion.html](www.kynosarges.de/DotNetVersion.html)
function IsDotNetDetected(version: string; service: cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
// 'v1.1' .NET Framework 1.1
// 'v2.0' .NET Framework 2.0
// 'v3.0' .NET Framework 3.0
// 'v3.5' .NET Framework 3.5
// 'v4\Client' .NET Framework 4.0 Client Profile
// 'v4\Full' .NET Framework 4.0 Full Installation
// 'v4.5' .NET Framework 4.5
// 'v4.5.1' .NET Framework 4.5.1
// 'v4.5.2' .NET Framework 4.5.2
// 'v4.6' .NET Framework 4.6
// 'v4.6.1' .NET Framework 4.6.1
// 'v4.6.2' .NET Framework 4.6.2
// 'v4.7' .NET Framework 4.7
// 'v4.7.1' .NET Framework 4.7.1
//
// service -- Specify any non-negative integer for the required service pack level:
// 0 No service packs required
// 1, 2, etc. Service pack 1, 2, etc. required
var
key, versionKey: string;
install, release, serviceCount, versionRelease: cardinal;
success: boolean;
begin
versionKey := version;
versionRelease := 0;
// .NET 1.1 and 2.0 embed release number in version key
if version = 'v1.1' then begin
versionKey := 'v1.1.4322';
end else if version = 'v2.0' then begin
versionKey := 'v2.0.50727';
end
// .NET 4.5 and newer install as update to .NET 4.0 Full
else if Pos('v4.', version) = 1 then begin
versionKey := 'v4\Full';
case version of
'v4.5': versionRelease := 378389;
'v4.5.1': versionRelease := 378675; // 378758 on Windows 8 and older
'v4.5.2': versionRelease := 379893;
'v4.6': versionRelease := 393295; // 393297 on Windows 8.1 and older
'v4.6.1': versionRelease := 394254; // 394271 before Win10 November Update
'v4.6.2': versionRelease := 394802; // 394806 before Win10 Anniversary Update
'v4.7': versionRelease := 460798; // 460805 before Win10 Creators Update
'v4.7.1': versionRelease := 461308; // 461310 before Win10 Fall Creators Update
end;
end;
// installation key group for all .NET versions
key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + versionKey;
// .NET 3.0 uses value InstallSuccess in subkey Setup
if Pos('v3.0', version) = 1 then begin
success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
end else begin
success := RegQueryDWordValue(HKLM, key, 'Install', install);
end;
// .NET 4.0 and newer use value Servicing instead of SP
if Pos('v4', version) = 1 then begin
success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
end else begin
success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
end;
// .NET 4.5 and newer use additional value Release
if versionRelease > 0 then begin
success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
success := success and (release >= versionRelease);
end;
result := success and (install = 1) and (serviceCount >= service);
end;
function InitializeSetup(): Boolean;
begin
if not IsDotNetDetected('v4.7.1', 0) then begin
// comment out
//MsgBox('MyApp requires Microsoft .NET Framework 4.7.1.'#13#13
// 'Please use Windows Update to install this version,'#13
// 'and then re-run the MyApp setup program.', mbInformation, MB_OK);
result := false;
end else
result := true;
end;
// [inno setup - How can I install .NET framework as a prerequisite using InnoSetup? - Stack Overflow](https://stackoverflow.com/questions/20752882/how-can-i-install-net-framework-as-a-prerequisite-using-innosetup#20753218)
procedure InstallFramework;
var
ResultCode: Integer;
begin
if not Exec(ExpandConstant('{tmp}\NDP471-KB4033342-x86-x64-AllOS-ENU.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
// { you can interact with the user that the installation failed }
MsgBox('.NET installation failed with code: ' + IntToStr(ResultCode) + '.', mbError, MB_OK);
end;
end;
終わり
インストーラーはテストでインストール、アンインストールを繰り返すのが面倒でした。