2011-09-18 110 views
9

我們正在開發一個引用一些COM庫(例如AutoIT)的C#應用​​程序。在構建服務器上註冊COM引用的DLL

我在第三方「Libs」文件夾中包含源代碼管理下的所有引用的組件。

問題是,COM DLL在.csproj文件中沒有HintPath屬性,我假設這些必須使用regsvr32(或使用某種腳本)手動註冊。

我目前正在研究創建一個MSBuild腳本,該腳本將在每次構建之前運行,但是我無法弄清楚應該手動調用regsvr32.exe還是使用一些預定義的MSBuild任務?

目前,這是我所attmpted作爲測試:

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> 
    <ItemGroup> 
    <MyAssemblies Include="D:\*.dll" /> 
    </ItemGroup> 
    <Target Name="Build"> 
    <RegisterAssembly 
     Assemblies="@(MyAssemblies)" > 
    </RegisterAssembly> 
    </Target> 
</Project> 

這會產生錯誤,我已經放置在指定文件夾中的DLL文件是無效的DLL。

什麼是解決這個問題的好方法?

編輯:引用內COM DLL必須在.csproj的文件與此類似

項目:

<COMReference Include="AutoItX3Lib"> 
     <Guid>{F8937E53-D444-4E71-9275-35B64210CC3B}</Guid> 
     <VersionMajor>1</VersionMajor> 
     <VersionMinor>0</VersionMinor> 
     <Lcid>0</Lcid> 
     <WrapperTool>tlbimp</WrapperTool> 
     <Isolated>False</Isolated> 
    </COMReference> 

這不包括任何暗示路徑等管理組件,因此生成服務器上,沒有找到引用的COM DLL。

使用REGSVR32註冊構建服務器上的COM DLL時,構建成功。

回答

10

您不在註冊服務器上註冊COM服務器。這隻有當你真的想要運行編譯的代碼時才需要。你需要的是COM服務器的類型庫,這樣你就可以獲得互操作程序集。你用Tlbimp.exe創建的。

無論您是要在構建服務器上運行Tlbimp還是在開發機器上預先運行,都取決於您如何部署這些COM服務器。保留COM可執行文件和.tlb文件的副本非常接近互操作庫是個不錯的主意。換句話說,檢查他們。安裝程序現在可以檢索COM服務器的已知良好版本。

+0

我有兩個類型庫和互操作程序集簽入我的源代碼管理(Git)。儘管參考interop是不夠的。 Tlbimp的輸出是什麼?我寧願將它作爲構建過程的一部分,而不是先行,因爲在升級構建環境時,我可以複製所有腳本並擴展到更多的服務器,並將所有邏輯存儲在那裏,而無需任何先決步驟 –

+0

Tlbimp的輸出是互操作程序集。我不能用「不夠」來做任何事情,你必須描述你變得更好的構建錯誤。 –

+0

我已更新我的原始問題。 Interop dll存在於「依賴關係」文件夾中,但是.csproj和此文件之間沒有鏈接,因此構建不會選擇該文件。在我的開發環境中,這可以正常工作,因爲我已經安裝了原始軟件包(例如AutoIt),但是在構建服務器上沒有安裝,因此在編譯前沒有做一些額外的步驟就會失敗。 –

0

1)嘗試引用COM庫到你的csproj作爲參考 - 如果你還沒有這樣做。

2)嘗試添加到您的csproj文件:

<Project ... > 
    ... 
    <Target Name="BeforeBuild"> 
     <Exec Command="regsvr32.exe yourComponent.dll" /> 
    </Target> 
</Project> 

PS:如果你正在使用某種形式的構建服務器軟件,你不應該修改的csproj,但在服務器上使用的構建腳本。

+0

感謝您的回答。我更喜歡不改變.csproj文件,而是使用一個「prep」腳本來完成這項工作。我想在所有程序集上運行regsvr32.exe(也許將所有COM引用放在一個文件夾下並在其上運行)。儘管如此,我如何在MSBuild中逐個遍歷它們。 –

+0

我相信我找到了解決方案 - 使用%(MyAssemblies.Identity)符號時,每使用* .dll,每個擴展文件都會運行一次該命令。這是正確和常見的用法嗎? –

+0

因爲您試圖使用COM dll,所以我不太瞭解您使用%(MyAssemblies.Identity)的解決方案。但是爲了遍歷列表文件,您可以在命令行中使用'for',如果您想要:瞭解如何使用它 - 只需鍵入'for /? > yourTargetPath \ help_for_for.txt'並讀取創建的txt文件。 –

0

如果在MSBuild中有任何任務調用regsvr32,但我不確定,但是REgisterAssembly調用regasm.exe - 也就是 - 爲COM互操作註冊.NET組件。

我相信,只需手動調用regsvr32將是實現所需結果的最快方法。

另一件事是 - 如果COM DLL已經被以前的版本註冊並且你會再次運行你的構建腳本會發生什麼? (我真的不知道regsvr32會如何反應,只是想到這裏)

+0

再次調用regsvr32是無害的(AFAIK),除了浪費了X毫秒的時間。 –

11

對於我原來的回答類似的問題,請參閱:TFS Build server and COM references - does this work?

爲構建服務器更好的選擇可能是在您的項目文件,而不是COMReference使用COMFileReference項目。一個例子如下所示:

<ItemGroup> 
    <COMFileReference Include="MyComLibrary.dll"> 
    <EmbedInteropTypes>True</EmbedInteropTypes> 
    </COMFileReference> 
</ItemGroup> 

COM dll不需要在計算機上註冊以使其工作。

每個COMFileReference項目也可以有一個WrapperTool屬性,但默認似乎工作正常。 EmbedInteropTypes屬性沒有記錄爲適用於COMFileReference,但它似乎按預期工作。

請參閱http://msdn.microsoft.com/en-us/library/bb629388.aspx瞭解更多細節。這個MSBuild項目自.NET 3.5起可用。

+0

順便說一下,看起來HintPath也適用於COMReference任務,即使它沒有記錄。 – jpierson

+0

HintPath在COMReference中對我無效,但我可以在COMFileReference的Include屬性中使用路徑。 – kristianp

相關問題