NSISでインストーラ&アンインストーラを作っていて、インストール時に一緒にインストールしたAdobe AIRアプリケーションを、アンインストール時に同時にアンインストールしたいという要件。
Adobe AIRアプリケーションのアンインストールは、手動ならWindowsのコントロールパネルからできるので、ここの情報をレジストリから引っ張り出して実行すればOK。この辺は良くある手段。
で、レジストリからアンインストールに必要なプログラムの実行パス情報を持ってこようとしたら、Adobe AIRでは、Uninstall以下のサブキーの名前が毎回変わるので、検索する必要があることが発覚。
NSISにはレジストリの特定のキーを読む機能はあっても、キーを検索する機能はないので、DLLで拡張を作成。さっくり適当にC#でレジストリを検索して文字列を返すDLLを作成してみた。
ちなみにアンインストール情報はHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall以下にあります。
ということで、必要な動作はUninstall以下のサブキーを全部開いてDisplayNameが目的の名前と一致するサブキーを探すこと。ソースは以下。
SearchUninstall.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace SearchUninstall
{
public class SearchUninstall
{
public static string Find(string name)
{
string keyPath = "";
// レジストリからの読み取り
Microsoft.Win32.RegistryKey regkey =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false);
// キーが存在しないときは null が返される
if (regkey == null) return null;
// 文字列を読み込む
// 読み込む値が存在しないときは null が返される
string stringValue = (string)regkey.GetValue("string");
// sub以下のすべてのキー名を取得
string[] keyNames = regkey.GetSubKeyNames();
foreach (string k in keyNames)
{
string tmp_keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + k;
Microsoft.Win32.RegistryKey regkey2 =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(tmp_keyPath, false);
try
{
string displayName = (string)regkey2.GetValue("DisplayName");
if (displayName == name)
{
keyPath = tmp_keyPath;
break;
}
}
catch (Exception e)
{
;
}
finally
{
regkey2.Close();
}
}
//閉じる
regkey.Close();
return keyPath;
}
}
}
で、出来上がったDLLをNSISに読み込ませようとしても、どうにも動かない。
Dependency walkerで他のDLLと見比べてみると、C#で作られたDLLはエントリポイントが見えない。
そう言えばそんな話もあったような。
参考:WINAMP.COM | Forums – How can I use a C# DLL in NSIS
NSISからでは.NETのDLLが読めないらしい。ということで、見つけたのが以下。.NETのDLLを使えるようにするプラグイン。
Call .NET DLL methods plug-in – NSIS
CLR.zipをダウンロードしてきて、NSISをインストールしたフォルダのPluginsフォルダに入れておけばOK。
先に作ったSearchUninstall.dllはnsiファイルと同じ場所に入れておく。
で、nsiファイルは以下の感じ。Uninstall部分の必要部分を抜粋。
; アンインストーラ
Section "Uninstall"
; アンインストールで使用するプラグインの準備
InitPluginsDir
SetOutPath $PLUGINSDIR
File "SearchUninstall.dll"
; AIRアプリケーションのアンインストーラを探す
CLR::Call /NOUNLOAD "SearchUninstall.dll" "SearchUninstall.SearchUninstall" "Find" 1 "HogeHogeAir"
pop $0
CLR::Destroy
ReadRegStr $4 HKLM $0 "UninstallString"
; AIRアプリケーションのアンインストーラをPassiveモード(自動処理)で実行する
ExecWait "$4 /passive"
; 後片付け
Delete "$PLUGINSDIR\SearchUninstall.dll"
SectionEnd
これで、アンインストール時にAdobe AIRアプリケーションのアンインストーラも勝手に起動して削除できる。
CLR超便利。プラグインを作るのが相当楽に。