2016-04-05 14 views
1

Visual Studio 2015を使用しています。アンインストール時にExcelアドインを「登録解除」するインストーラカスタムアクションを作成しようとしています。基本的には、HKCU\Software\Microsoft\Officeのキーを調べ、バージョン番号(16.0など)のサブキーを見つけて、Excel\Optionsサブキー(存在する場合)を調べて、OPENのいずれかのアドイン名をチェックする必要がありますExcelは、OPENOPEN1OPEN2などを使用して、レジストリ内のアドインを列挙します。インストーラのカスタムアクションですべてのレジストリ値を読み取ることができません

カスタムアクションをデバッグすると、すべてのレジストリ値を表示できないように見えます。例として、実際に10のサブキーがある場合、HKCU\Software\Microsoft\Officeの下に8つのサブキーがあると報告します。のいずれかを使用してRegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32)

のx64:RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)

x86の私は以下のように特定のレジストリビューを開くには、アプリケーションを強制しようとしてきたので、私は、これは、仮想化をレジストリに起因することを推測していますこれらの呼び出しは全く同じ制限付きレジストリビューになります(私はまだ8つのキーを10回以上見ています)。だから、インストーラのカスタムアクションは何らかの理由で特定のレジストリビューを強制することができないようです。

これを回避するための追加テストを行うためのコンソールアプリケーションを作成しました。コンソールアプリケーションは、x64またはx86プラットフォームをターゲットにしてコンパイルされているかどうかにかかわらず、フル10キーを見ることができます。

私はここで紛失しています。これはVS2015セットアッププロジェクトの既知の問題ですか?彼らはレジストリの特定の部分を見る能力に限界がありますか?それとも、自分のコードエラーですか?

ここでは、アドインの登録を解除するために使用しようとしているコードを示します。私はアンインストールプロセスで致命的なエラーを引き起こしていた途中で、大量のエラーチェックを追加しました。今やアンインストールは(クラッシュを引き起こさない限り)機能しますが、実際にアドインを登録解除するわけではありません。

If Registry.CurrentUser.OpenSubKey("Software\Microsoft\Office", True) IsNot Nothing Then 
    Dim regCUOffice As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Office", True) 
    If regCUOffice.GetSubKeyNames.Count > 0 Then 
     For Each strKeyName As String In regCUOffice.GetSubKeyNames 
      If regCUOffice.OpenSubKey(strKeyName & "\Excel\Options", True) IsNot Nothing Then 
       Dim regExcelOptionsKey As RegistryKey = regCUOffice.OpenSubKey(strKeyName, True).OpenSubKey("Excel\Options", True) 
       For Each strValueName As String In regExcelOptionsKey.GetValueNames 
        If strValueName IsNot Nothing Then 
         If (strValueName.Equals("OPEN") Or strValueName.StartsWith("OPEN")) Then 
          If regExcelOptionsKey.GetValue(strValueName) IsNot Nothing Then 
           If regExcelOptionsKey.GetValue(strValueName).Equals("MyAddIn.xll") Then 
            regExcelOptionsKey.DeleteValue(strValueName) 
           End If 
          End If 
         End If 
        End If 
       Next 
       regExcelOptionsKey.Close() 
      End If 
     Next 
    End If 
    regCUOffice.Close() 
End If 

答えて

1

これについて数多くの研究と作業を行った結果、私はこの問題を理解したと考えています。

明らかに、Visual Studioのセットアッププロジェクトでビルドされたカスタムアクションは、汎用のSYSTEMアカウントとして実行されます。したがって、HKCUレジストリハイブはSYSTEMアカウントのハイブであり、ではなく、現在ログインしているユーザーはです。しかし、この動作を回避することは可能です。

私が遭遇した最も実行可能な解決策は、MSIが作成された後に偽装フラグを反転させることです。これにより、カスタムのアクションをインストールして、現在ログインしているユーザーを偽装することができます。残念ながら、このフラグを反転させることは特に直感的ではありません。 (あなたのSetupProjectName.vdprojファイルが配置されている、すなわち)あなたのセットアッププロジェクトのためのプロジェクトフォルダにCustomAction_Impersonate.jsよう

// CustomAction_Impersonate.js <msi-file> 
// Performs a post-build fixup of an msi to change all deferred custom actions to Impersonate 
// Constant values from Windows Installer 
var msiOpenDatabaseModeTransact = 1; 

var msiViewModifyInsert   = 1 
var msiViewModifyUpdate   = 2 
var msiViewModifyAssign   = 3 
var msiViewModifyReplace  = 4 
var msiViewModifyDelete   = 6 

var msidbCustomActionTypeInScript  = 0x00000400; 
var msidbCustomActionTypeNoImpersonate = 0x00000800 

if (WScript.Arguments.Length != 1) 
{ 
     WScript.StdErr.WriteLine(WScript.ScriptName + " file"); 
     WScript.Quit(1); 
} 

var filespec = WScript.Arguments(0); 
var installer = WScript.CreateObject("WindowsInstaller.Installer"); 
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact); 

var sql 
var view 
var record 

try 
{ 
     sql = "SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`"; 
     view = database.OpenView(sql); 
     view.Execute(); 
     record = view.Fetch(); 
    //Loop through all the Custom Actions 
     while (record) 
     { 
      if (record.IntegerData(2) & msidbCustomActionTypeInScript) 
      { 
       //We must flip the msidbCustomActionTypeNoImpersonate bit only for deferred custom actions 
       record.IntegerData(2) = record.IntegerData(2) & ~msidbCustomActionTypeNoImpersonate; 
       view.Modify(msiViewModifyReplace, record); 
      } 
     record = view.Fetch(); 
     } 

     view.Close(); 
     database.Commit(); 
} 
catch(e) 
{ 
     WScript.StdErr.WriteLine(e); 
     WScript.Quit(1); 
} 

保存このスクリプトを:私は最終的にあなたのためのすべての取材を行い、このスクリプトに出くわしました。 Visual Studioで、セットアッププロジェクトを選択し、プロパティウィンドウを開きます。 PostBuildEventプロパティに、cscript.exe "$(ProjectDir)CustomAction_Impersonate.js" "$(BuiltOuputPath)"を追加します。

基本的に、この行はVisual Studioにプロジェクトをビルドするように指示し、正常にビルドされたら保存したスクリプトを実行します。このスクリプトは偽装フラグを反転させて、インストーラのカスタムアクションをログインユーザーとして実行できるようにします。

私の予備テストでは、これはトリックを行うようです。この解決策が何らかの理由で実行できないことがわかったら、ここで更新します。他の誰かがこの問題を抱えている場合に備えて、答えを共有したかっただけです。

関連する問題