c++ - 使用Wix Msi安裝程序在安裝後將CPP dll註冊到COM中




windows-installer wix3.10 (2)

我想在Msi安裝期間將CPP庫註冊到COM中。

我已經搜索了很多並在這裡找到了很多解決方案,但我的代碼中沒有任何工作。 我不知道有沒有直接的方法。 我嘗試使用自定義操作直接使用ExeCommand和批處理腳本。

這是帶有批處理腳本的代碼。

<SetProperty Id="Register" Value="&quot;[INSTALLDIR]Scripts\Register.bat&quot;" After="CostFinalize"/>
<CustomAction Id="Register" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/> 

<SetProperty Id="Unregister" Value="&quot;[INSTALLDIR]Scripts\UnRegister.bat&quot;" After="CostFinalize"/>
<CustomAction Id="Unregister" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>

使用此代碼,安裝不會顯示任何錯誤,但dll未註冊。 安裝後,如果我單獨運行批處理腳本,那麼它將被註冊。

的Register.bat

cd“C:\ Windows \ System32”

regsvr32“C:\ Program Files(x86)\ ABC \ Abc.dll”

ping -n 15 127.0.0.1> nul:

Unregister.bat

cd“C:\ Windows \ System32”

regsvr32 / u“C:\ Program Files(x86)\ ABC \ Abc.dll”

ping -n 15 127.0.0.1> nul:

使用帶有ExeCommand的自定義操作,它會顯示錯誤,例如某些dll依賴項缺失。 ExeCommand代碼如下。

<CustomAction Id="Register" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"
              ExeCommand="[WindowsFolder]System32\regsvr32 &quot;[INSTALLDIR]Abc.dll&quot;" Return="check" />
<CustomAction Id="Unregister" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"
             ExeCommand="[WindowsFolder]System32\regsvr32 /u &quot;[INSTALLDIR]Abc.dll&quot;" Return="check" />

下面給出了兩種情況的InstallSequence。

 <InstallExecuteSequence> 
    <Custom Action="Register" Before="InstallFinalize" >NOT Installed</Custom>
    <Custom Action="Unregister" Before="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
 </InstallExecuteSequence>

在這兩種情況下,我認為它是以提升的權限運行。

這是我大部分時間都會遇到的錯誤。

編輯

dll的依賴性walker視圖如下所示。

我還添加了我使用的加熱命令。 我已將此添加到prebuild事件以生成組件。 之後,在產品文件中添加了此組件。

調用“$(WIX)bin \ heat.exe”文件“dllPath \ Abc.dll”-dr“INSTALLDIR”-srd -gg -sfrag -suid -out“$(SolutionDir)Installer \ ComRegisterComponent.wxs”

生成的文件看起來像這樣。

 <Fragment>
    <DirectoryRef Id="INSTALLDIR">
        <Component Id="Abc.dll" Guid="*">
            <File Id="Abc.dll" KeyPath="yes" Source="SourceDir\Abc.dll" />
        </Component>
    </DirectoryRef>
</Fragment>

這裡的SourceDir路徑讓我感到困惑。我已經在heat命令中添加了確切的路徑,即使它生成了這個SourceDir。


簡短,總結答案

您需要 停止使用批處理文件和自定義操作 進行COM註冊(不可靠),而是使用WiX工具包中的 heat.exe 工具提取COM註冊信息, 以便 在編譯時將COM註冊添加到MSI數據庫。

64位二進製文件有一些複雜情況,請參閱下面的詳細信息。 幸運的是,您似乎正在處理基於上面顯示的安裝目錄的32位組件。

在這種特殊情況下,它有助於在部署後在COM文件上運行heat.exe,此時所有依賴項都“就位”,以便正確加載COM文件。 在這些答案中有很多“調試溝通” - 我將把這一切留在未來,但首先嘗試這個簡單的解決方案。 也許嘗試下面描述的新依賴工具“Dependencies.exe”。

詳盡的答案

在我嘗試回答這個問題之前(這似乎是圍繞 缺少的依賴關係 或者 在批處理文件中做了一些奇怪的事情 ),我想為COM註冊的最佳實踐清理一些事情。

注意 :屏幕截圖似乎表明您的批處理文件中出現了一些奇怪的內容,但缺少依賴項仍然是一個問題。

自我註冊被認為是有害的

不應使用自行註冊來註冊COM文件 。 以下是對此案例的描述: MSI註冊dll - 自我註冊被認為是有害的 。 有一個好消息,但是,一旦你正確設置它,通過內置的MSI機製做的事情將更容易和更可靠。

有一種方法可以在安裝過程中自行註冊文件,而無需使用您嘗試執行的自定義操作( SelfReg表 )。 自定義操作很難正常工作,但您不應使用內置機制來運行自註冊(如上面鏈接的答案中詳細解釋的那樣)

應該在編譯時從COM文件中提取COM註冊信息 ,而不是使用自定義操作或SelfReg表 - 換句話說,當您從WiX源文件編譯MSI文件時。 提取的註冊表數據應該用於填充MSI數據表系列,這些數據表旨在分別在安裝和卸載過程中可靠地註冊和註銷COM文件。

WiX:“heat.exe”命令行工具

無需了解此過程的複雜細節 - 您需要知道的是使用哪些工具。 WiX為此提供了“ heat.exe ”工具。 它本質上是一個“ 收集器 ”工具,能夠為多種目的生成有效的WiX XML源文件 - 其中一個是COM提取。 它還支持遍歷目錄 - 生成WiX源文件,可以安裝遍歷期間遇到的文件。 一旦您知道如何使用MSI包,它本質上是一種非常快速的方法。

依賴沃克

所以我們已經確定你應該花時間學習如何使用heat.exe來生成正確註冊COM文件所需的WiX源。 然而, 還有一個問題 缺少依賴性

要使COM文件能夠自行註冊 - 或者您能夠使用heat.exe成功提取COM註冊表數據 - COM文件必須能夠正確加載。 為此,所有dll依賴項必須在可訪問位置的相關係統上可用。

獲取 Dependency Walker 的副本,並使用它來掃描COM文件以查找它所依賴的文件。 以下是無法加載的COM文件示例,因為它無法找到 MMUtilities.dll

從安裝程序的安裝位置運行時,您很可能會發現類似於您的dll(或任何文件類型,例如OCX)的類似錯誤。 regsvr32.exe無法找到所需的依賴項文件,並且註冊過程失敗。

有一些報告遺漏的依賴關係並不重要 - 我想這與Dependency Walker工具的年齡有關 - 據我所知,它最近沒有更新過。 查找您認為是自己的依賴文件或核心系統文件的文件,而不是您從未聽說過的非常長的dll文件名。 請記住,某些dll具有加載所需的依賴語言dll。 例如,MMUtilities.dll需要MmUtilitiesEnglish.dll或同一文件夾中存在的其他語言dll才能正確加載。

以上文件的一些 示例誤報依賴 API-MS-WIN-CORE-RTLSUPPORT-L1-1-0.DLLAPI-MS-WIN-CORE-PROCESSTHREADS-L1-1-0.DLLAPI-MS-WIN-CORE-REGISTRY-L1-1-0.DLL 等......有很多。 我相信,但我不確定,這些誤報的根本原因在於安裝到WinSxS文件夾的並排組件的問題,但這是另一個討論 - 只是提到它。

更新 :我剛剛再次檢查了這一點,上面看到的大多數誤報依賴項顯然都是 API-sets - 在創建Dependency Walker之後很久就引入了一個Windows功能,因此該工具無法正確處理。

由於鏈接的答案表明(請閱讀,鏈接上面),現在還在 C#中重寫了Dependency Walker, 稱為“ Dependencies ”,可在此處獲取: https://github.com/lucasg/Dependencieshttps://github.com/lucasg/Dependencies (我未經測試)寫作,將很快測試)。

另外快速提一下:如果你有一個可執行文件要檢查(而不是dll,ocx等...),你可以通過 Profile => Start Profiling... 菜單項啟動它,然後你也會看到“ 隱藏運行時依賴項 “未在二進制導入表中指定(其中指定了依賴項/導入)。 您需要使用所有對話框中的所有功能來真正運用應用程序,以確保獲得所有此類依賴項。

依賴性walker Web頁面調用這些隱藏的依賴項 顯式依賴項 (動態或運行時依賴項)和 系統掛鉤依賴項 (注入依賴項)。 有關詳細信息,請參閱上面的鏈接。

Heat.exe提取

一旦確定了使WiX heat.exe提取工作丟失的文件,您可以將文件置於“COM dll”旁邊,以便在加載過程中找到它們。 您可以使用regsvr32.exe測試運行,以查看註冊是否正確完成。 這樣手動運行註冊時應該沒有錯誤消息。 請記住從提升的命令提示符運行註冊

其他幾個答案解釋瞭如何使用heat.exe - 我很久沒有使用它了: 如何運行heat.exe並在wix中註冊一個dll 。 這是來自WiX傢伙本身的 heat.exe的官方文檔 。 它可能是一個有點令人生畏的工具 - 它有很多功能。

在最簡單的形式(對於路徑或本地文件夾中可用的所有依賴項的普通32位COM文件),您可以運行此heat.exe命令行以生成一個名為 YourFileName.wxs 的輸出WiX源文件, YourFileName.wxs 包含所有必需的COM註冊表數據。

heat.exe file YourFileName.ocx -o YourFileName.wxs

幾年前我寫了一個答案,展示如何將導出的WiX註冊表數據合併到主WiX源: 如何在Wix(命令行)中引用熱輸出(wxs) 。 我相信這是對程序的準確描述,但由於某種原因,有人下了決定答案。 請試一試,看看它是否適合您。

重要! :heat.exe尚未正確處理64位COM二進製文件(2017年12月)。

我被告知WiX擴展包( 非免費 )處理64位二進製文件並提供其他一些功能。 我想我可以鏈接到它(我不隸屬於FireGiant): https://www.firegiant.com/wix/wep-documentation/harvesting/https://www.firegiant.com/wix/wep-documentation/harvesting/ 。 不知何故,人們需要知道這些事情,但我不確定鏈接的禮儀。

你的二進製文件是64位嗎? (它從您的安裝文件夾看起來不是這樣,但我將其添加到可能找到它的其他人)。 對於64位組件,我想我們已經完全循環,並且建議您使用上面的擴展包功能,或者只是嘗試 將文件設置為自我註冊,如此處所述 。 我討厭這種自我註冊的“解決方案”,但我現在想不出任何其他快速解決方法(無論如何我都不會推薦)。 我會再檢查一下。 在進行“自行註冊修復”之前,請務必檢查最新的WiX版本以查看是否已修復64位問題 。 它至少比嘗試使用自定義操作和批處理文件(永遠不應該嘗試註冊)更好 - 有很多與MSI複雜的自定義動作排序,模擬/提升,調節,安裝模式以及靜音和交互相關的潛在問題,而不是提到安全軟件的潛在干擾,並且列表繼續)。

一些鏈接:


只需添加另一個答案,其中包含有關如何使用 regsvr32.exe 在自行註冊期間以有效方式 調試缺少的依賴項的 procmon.exe 信息。

基本上你應該為你要監視和記錄的事件 設置一個包含過濾器 ,否則你會得到列出的無關事件的全能列表,很難在無用信息的海洋中找到你需要的東西:

  1. 要將捕獲的流程信息限制為您需要的信息,只需轉到 Filter => Filter...
  2. 將左下拉菜單設置為 Process Name ,然後將第二列設置為 is ,最後在右側框中鍵入 regsvr32.exe ,如上圖所示。
  3. 至關重要的是將最右邊的框設置為 Include 。 然後按OK。
  4. 現在應該禁止所有不必要的事件,並且只顯示 regsvr32.exe 事件(當您運行它時)。
  5. 以正常方式運行 regsvr32.exe 並在列表中查找“ NAME NOT FOUND ”條目(或類似名稱)。
  6. 在下圖中 MMUtilities.dll 。 換句話說,它是一個缺失的依賴。

請注意,您可以通過單擊下面所示的按鈕打開和關閉來包含/排除某種類型的事件。 Registry events file system events network activity process and tread activity profiling events 。 這可以大大減少您在列表中處理的“噪音”。

在自行註冊期間調試缺失依賴項的另一種方法是使用 Dependency Walker, 如我在“線程”或問題中的其他答案或其他任何調用它所示。 通常我發現 Dependency Walker 是更快的選擇,但是 procmon.exe 總體上可能更好 - 除非你正在調試EXE文件,否則Dependency Walker具有優越的 Profile 功能( Profile => Start Profiling... )。





wix3.10