标签: com

使用WiX安装程序复制Visual Studio COM注册

曾几何时,一位年轻,天真的工程师认为将他的应用程序的一些功能分成一个用C#编写的COM组件是个好主意.Visual Studio拥有所有这些工具,对吧?.NET实际上是为此做的,对吗?哈!他说,这很容易.我将对组件进行适当的分离,使业务逻辑远离前端,而使用COM,我将能够在任何地方使用它!他愉快地检查了register for COM interop项目属性中的复选框,暴露了他想要的分类,然后继续前进.

哦,试验这样的选择.这位年轻的工程师现在更有经验,现在不希望任何人这样做.但是,肩负重担,负担仍然沉重.他希望减轻负担.

随之而来的是WiX,一种用于从XML生成Windows Installer文件的工具.这引起了他的兴趣 - 它可以简单地从一些配置文件复制一个正确的Windows安装程序文件所需的大部分代码.他的目光正在抬头.

使用WiX 2.0,他可以很容易地生成注册C#COM对象所需的文件.这涉及使用工具牛油.他会做以下事情:

tallow -c -nologo MyComExposedLibrary.dll > MyComExposedLibrary.wxs
Run Code Online (Sandbox Code Playgroud)

然后将其修复(首先这是手动完成的,但最终我将步骤记录到一个小工具集中,最终目录引用ID,组件ID,文件ID,GUID和代码库).

然后,随后的安装程序将安装,如果应用程序工作,将有欢乐的庆祝活动.

它没有.

几天来,年轻的工程师倾注了他的开发PC和测试安装PC的差异."所有的注册表键都是一样的!" 他会惊呼."对于MyComExposedLibrary的所有内容都已注册,我发誓!"

除此之外,事实并非如此.

在第三天的黎明之后,经过许多山露,他意识到Visual Studio正在注册的另一个对象是他的安装程序不是:MyComExposedLibrary.tlb文件.

显然,Visual Studio一直在注册此文件,在HKLM\Software\Classes\Interface注册表项中创建其他子项,并在其中注册typelib HKLM\SOFTWARE\Classes\TypeLib.

Tallow没有给出任何帮助,抱怨说.tlb不是一个文件.也不是WiX 3.0测试版 - 这似乎有更多的问题让事情发挥作用.

我也尝试了热火.这生成了注册表元素和类元素.我清理了热量的输出,然后去编译它,但得到了一个不同的错误:error LGHT0130 : The primary key <uuid here> is duplicated in table 'Registry'.问题是,据我所知,uuid实际上并不存在于我的任何wxs源文件中.如果我在我的feature元素中改变组件引用顺序,则另一个dll组件会给出该错误.由于我没有成功完成项目的WiX 3.0版本的编译,我无法确认热量是否能提供正确的输出.

我从安装程序中删除了所有内容,除了导致出现此错误的程序集之一并再次尝试编译.我得到了同样的错误.Arrugh!

所以,我的好伙伴,Windows爱好者和WiX用户都有两个问题:

  • WiX可以本地注册的类型库吗?如果是这样,怎么样?
  • 如果没有,使用Windows安装程序注册typelib的正确方法是什么?

此外,我想作为另一部分,Visual Studio如何确定如何注册typelib?(编辑:看起来关于typelib注册MSDN库文章有所需的密钥的名称,但我仍然需要弄清楚如何获取uuid的.(这是关于typelib的博客文章和Larry Osterman的COM注册.))再读一点,手动注册这些位可能会让我失望,但我希望不是......

我评估了输出regasm /regfile:MyDll.dll MyDll.dll.看起来这些是wix为dll生成的密钥.Regasm的另一种模式,regasm /tlb:<filename>生成并注册程序集的类型库,但是,

/ regfile [:FileName]生成具有指定名称的reg文件,而不是注册类型.此选项不能与/ u或/ tlb选项一起使用 …

.net windows com wix typelib

36
推荐指数
2
解决办法
1万
查看次数

*.tlb文件是否曾在运行时使用过?

我正在研究一种通过COM互操作公开一些.NET API的产品.作为构建的一部分,我们为所有这些程序集生成*.tlb文件,并将它们作为单独SDK包的一部分提供.我们的客户可以在我们的产品上安装SDK,并创建使用我们的COM API的应用程序.

我们是否需要使用产品本身发送和注册这些*.tlb文件?是否存在运行时需要*.tlb,执行针对它们编码的第三方库的情况?

如果您回答"是",请解释它是如何工作的.我在互联网上看到很多评论说我必须提供并注册它们,但我没有找到一个清楚解释为什么要这样做的评论.这让我怀疑这是真的.

.net com

36
推荐指数
1
解决办法
1万
查看次数

在VB6 IDE中工作时卸载COM控件

我日常工作的一部分是维护和扩展传统的VB6应用程序.公共引擎是用C/C++编写的,VB6使用这些函数来提高性能.

在异步编程方面,C接口是不够的,我们依靠COM控件将事件激发到VB6.

我的问题是,当我在VB6中注册控件时,VB将此控件加载到内存中,并且在我退出VB6 IDE之前不会卸载它.由于控件是一直加载的,我无法在VC6中重新编译它,因为DLL文件已被锁定.

我找到的解决方案是不在VB中启用控件,而是使用CreateObject()我的控件的全名.问题是我必须将我的控件声明为Object,因为VB6对我正在使用的接口一无所知,而且我无法访问IntelliSense,这很痛苦.

知道如何在退出应用程序后或直接在IDE中告诉VB6卸载控件吗?

vb6 com

35
推荐指数
1
解决办法
2543
查看次数

如何在WiX 3中注册Win32 COM DLL文件?

我找到了一个关于注册DLL的示例,使用Windows Installer XML工具集在MSI文件中注册COM Interop的程序集.,和WiX抱怨"AssemblyRegisterComInterop"属性.

我删除了它并将"Assembly"属性更改为win32,它说我需要指定AssemblyManifest属性,但是我应该放在那里?

com dll wix wix3

35
推荐指数
3
解决办法
3万
查看次数

在*nix系统上是否有相当于COM的东西?如果没有,那么*nix的可重用性方法是什么?

我对windows COM及其背后的想法有所了解.我试图了解*nix系统是否具有等价物或为什么不具有等价物?

unix architecture linux com

35
推荐指数
2
解决办法
8726
查看次数

如何诊断COM可调用包装器对象创建失败?

我使用以下命令创建一个COM对象(来自本机代码)CoCreateInstance:

const 
   CLASS_GP2010: TGUID = "{DC55D96D-2D44-4697-9165-25D790DD8593}";

hr = CoCreateInstance(CLASS_GP2010, nil, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IUnknown, out unk);
Run Code Online (Sandbox Code Playgroud)

实际上,我在Delphi中,这意味着我调用了辅助函数:

CreateComObject(CLASS_GP2010);
Run Code Online (Sandbox Code Playgroud)

大部分时间这个功能都成功了.但有时,在同一个可执行文件中,在同一进程中,调用CoCreateInstance失败的原因是:

Unspecified error (0x80004005 = E_FAIL)
Run Code Online (Sandbox Code Playgroud)

再次调用该函数可能会成功,或者可能会失败.没有(明显的)押韵或理由.

这不是我的COM dll

如果这是一个正常的 COM DLL,我写,我就开始把OutputDebugStringDLL_ATTACH,当有人试图打电话DllGetClassObject,我会确认COM是正确加载我的DLL,并且它被正确要求被实例化的类.

不幸的是,它不是COM dll; 它是一个.NET程序集dll.COM子系统并不是简单地 "加载"我的dll.相反,COM被指示加载mscoree.dll:

HKEY_CLASSES_ROOT
   CLSID
      {DC55D96D-2D44-4697-9165-25D790DD8593}
         InprocServer32
            @default = mscoree.dll
Run Code Online (Sandbox Code Playgroud)

mscoree.dll导出所需的GetClassObject功能.那mscoree.dll个人回来了E_FAIL,不是我.故障永远不会发生在我的开发机器上,但始终在客户机器上间歇性地失败.

如何启用.NET日志记录?

问题是,因为mscoree.dll返回的是E_FAIL(而不是任何有用的):我如何告诉我问题是什么?

例如,似乎唯一遇到故障的客户(除了是唯一大量使用COM对象的客户)恰好在Windows XP上.也许他们遇到了.NET框架中的已知错误(版本4之前),您无法在同一进程中加载​​不同版本的.NET运行时 …

.net delphi com ccw com-callable-wrapper

35
推荐指数
1
解决办法
835
查看次数

.NET"所有COM都在下面"吗?

多年来,我一直是Juval Lowy在.NET开发方面的教学和指导的崇拜者.他还写了我最喜欢的书之一:Programming .NET Components.

然而,在最近的DotNet Rocks播客(2010年1月)讨论WCF/COM和.NET时,他发表了一些令我惊讶的评论:

JuvalLöwy: ..... 在.NET中,看,这里的每个类都是COM对象.我们知道.事实上,它远远超过COM,因为我们有git编译,我们有垃圾收集,我们有安全堆....

卡尔富兰克林:嗯,你应该澄清一下.我的意思是,每个对象都不是COM对象.每个对象都具有COM对象的功能,但.NET Framework不是COM库.

JuvalLöwy: 不,不.首先,.NET实际上是建立在COM之上的.这都是COM下面的.

然后,在卡尔富兰克林要求澄清这一评论之后:

卡尔富兰克林:是的,我明白了.我的问题是基于COM构建的.NET?

JuvalLöwy:当然,所有COM都在下面.

Carl Franklin:不,我知道它是交织在一起的,而且是必需的,但是当你新建一个.NET对象时,你并没有创建一个COM对象.

JuvalLöwy:你正在创建一个.NET对象,但我所说的只是.NET构建在底层.这都是C++和COM.

Carl Franklin:它是C++,但你没有通过COM接口注册COM对象.除非你专门做到这一点,否则不是全部.

JuvalLöwy:但有些东西在下面使用COM,但这不是重点.忘记它是如何制作的.

你怎么看这些评论?

虽然我理解(并且已经确认)某些系统程序集是用非托管C++编写的,但是它们是"所有COM下面"也是有效的吗?

我是在假设完全可以编写与COM/ATL/ActiveX完全无关的.NET CLI兼容的C++程序集?

以下是相关播客的PDF文字记录.见第7页.

.net c++ com

34
推荐指数
5
解决办法
1791
查看次数

从C#访问COM对象的最佳方法

我打算使用作为COM对象公开的各种对象.为了使它们更容易使用,我想将它们包装为C#对象.对此最好的方法是什么?

.net c# com pinvoke

33
推荐指数
3
解决办法
5万
查看次数

为什么使用FinalReleaseComObject而不是ReleaseComObject?

我知道基本的区别,因为ReleaseComObject只减少一些计数器并将其FinalReleaseComObject减少到零.

所以我通常听到的是,调用FinalReleaseComObject因为那时你确定COM对象真的被释放了.

但这让我想知道,这个反击有一点对吗?如果你总是打电话,你不打破这种机制吗FinalReleaseComObject?如果在您打电话之前该计数器不是一个,那么ReleaseComObject可能没有理由吗?

什么可能导致它高于一个不应该?

提前致谢.

PS:我的COM体验只包括使用Excel Interop.不确定这个问题是否属于该域的本地问题(即在Office Interop之外,FinalReleaseComObject不经常使用).

更新1

文章丹提及使用会谈ReleaseComObject时,即可大功告成.据我从文章中了解,这是正常的方式.我认为,如果你这样做,它应该工作正常.在对文章的评论中,作者建议有人ReleaseComObject在循环中调用直到它真正发布(该文章来自2006年,所以这与调用类似FinalReleaseComObject).但他也表示这可能是危险的.

如果你真的想让RCW在代码中的某个特定点调用Release(),你可以在循环中调用ReleaseComObject()直到返回值达到零.这应该确保RCW将调用Release().但是,如果您这样做,请注意,当其他托管引用尝试使用该RCW时,它将导致异常."

这让我相信总是打电话确实不是一个好主意FinalReleaseComObject,因为你可以在其他地方引起例外.正如我现在所看到的那样,如果你绝对确定可以,你应该只打电话给你.

不过,我对此事的经验不多.我不知道怎么可以肯定.如果计数器在不应该增加的情况下增加,那么解决这个问题是不是更好?如果是这样,那么我会说FinalReleaseComObject更多的是黑客而不是最佳实践.

.net com interop

33
推荐指数
1
解决办法
2万
查看次数

初始化VCProjectEngineObject时出现错误80040154(类未注册的异常)(Microsoft.VisualStudio.VCProjectEngine.dll)

我正在尝试运行工具,以便将Visual C++项目转换为makefile.我正在尝试转换项目的项目是用VS2008编写的,所以我在版本9中使用了对Microsoft.VisualStudio.VCProjectEngine.dll的引用.

它失败了:

VCProjectEngine vcprojEngine = new VCProjectEngineObject();
Run Code Online (Sandbox Code Playgroud)

有以下例外:

检索具有CLSID {D19A00C4-A7F9-4E14-A5E1-D060B7EB57F3}的组件的COM类工厂由于以下错误而失败:80040154未注册类(HRESULT异常:0x80040154(REGDB_E_CLASSNOTREG)).

当试图用regsvr32注册VCProjectEngine.dll时,我收到一个错误,即找不到入口点DllRegisterServer.

任何的想法??

提前致谢.

c# com exception dllregistration

33
推荐指数
1
解决办法
10万
查看次数