2011-09-18 103 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

相关问题