我正在开发一个新的 WMI 实例提供程序,但遇到了一些麻烦。我能够使用regsvr32.exe. 该regsvr32应用程序调用我的实现DllRegisterServer并创建以下注册表项和值:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F} : (default) = "WMI Provider"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : (default) = "C:\MyWmiProvider.dll"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : ThreadingModel = Neutral
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\Version : (default) = 1.0.0
Run Code Online (Sandbox Code Playgroud)
(哪里{00000001-0000-0000-0000-00000000000F}只是一个测试类 ID(CLSID))
我也能够成功地添加在我的定义我的WMI类定义中号anaged Ø bject ˚F使用ORMAT(MOF)文件mofcomp.exe。我可以通过运行以下命令来验证我的定义是否存在于 WMI 存储库中:
Get-CimClass -Namespace "root/MyNamespace" | Where-Object CimClassName -like "MyClass_*"
Run Code Online (Sandbox Code Playgroud)
这是我的 MOF 文件的示例:
#pragma namespace("\\\\.\\root\\MyNamespace")
#pragma autorecover
instance of __Win32Provider as $P
{
Name = "MyWmiProvider";
ClsId = "{00000001-0000-0000-0000-00000000000F}";
};
instance of __InstanceProviderRegistration
{
Provider = …Run Code Online (Sandbox Code Playgroud) 如何使用.NET检查COM组件(EXE/DLL文件)是否已注册?
我已经有一个项目使用了很多COM和HRESULTS.我想知道是否有可能定义你自己的HRESULT,并且能够将FormatMessage()用于我们自己的HRESULT?
我四处乱窜,无法找到任何东西.有任何想法吗?
编辑
基本上我想定义一组我自己的HRESULT,而不是只返回E_FAIL.或者其他通用的.像E_FAIL一样好.但是,我想说,我想指出,例如地理处理子系统崩溃或文件是无效的光栅图像.该应用程序已经通过它使用com.
我在.NET(C#)中使用了广泛的现有COM API(可能是Outlook,但它不是).我通过在Visual Studio中添加"COM引用"来完成此操作,因此所有"魔法"都是在幕后完成的(即,我不必手动运行tlbimp).
虽然现在可以从.NET"轻松"使用COM API,但它不是非常友好的.NET.例如,没有泛型,事件很奇怪,奇怪,如IPicture等.所以,我想创建一个使用现有COM API实现的本机.NET API.
一个简单的第一次传球可能是
namespace Company.Product {
class ComObject {
public readonly global::Product.ComObject Handle; // the "native" COM object
public ComObject(global::Product.ComObject handle) {
if (handle == null) throw new ArgumentNullException("handle");
Handle = handle;
}
// EDIT: suggestions from nobugz
public override int GetHashCode() {
return Handle.GetHashCode();
}
public override bool Equals(object obj) {
return Handle.Equals(obj);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法的一个直接问题是,您可以轻松地为同一个底层"本机COM"对象结束多个ComObject实例.例如,在进行枚举时:
IEnumerable<Company.Product.Item> Items {
get {
foreach (global::Item item in Handle.Items)
yield …Run Code Online (Sandbox Code Playgroud) 我正在尝试将VC6 COM DLL添加到我们的VS2010RC C#解决方案中.使用VC6工具编译DLL以创建x86版本,并使用VC7跨平台工具编译以生成VC7 DLL.
只要消耗C#项目的平台设置为x86,组件的x86版本就可以正常工作.DLL的x64或x86版本是否实际注册无关紧要.它适用于两者.如果平台设置为"任何CPU",我会收到一个BadImageFormatException负载Interop.<name>.dll.
至于x64版本,我甚至无法构建项目.我收到tlbimp错误:
TlbImp:错误TI0000:必须指定与输入类型库兼容的单个有效机器类型.
有没有人见过这个问题?
编辑:
我已经做了很多深入研究这个问题,并认为这可能是一个Visual Studio错误.我有一个干净的解决方案.我引入了我的COM程序集,选择了与语言无关的"任何CPU".生成的Interop DLL的过程体系结构是x86而不是MSIL.
可能必须手工制作Interop才能使其工作.
如果有人有其他建议,请告诉我.
我有一个第三方组件,让我们说FIPreviewHandler来处理预览,它实现了IPreviewHandler.FIPreviewHandler实现为托管组件,并通过互操作使用IPreviewHandler接口和相关接口.FIPreviewHandler使用regasm.exe作为COM注册.
我有一个客户端应用程序也管理.我想在我的应用程序中创建一个FIPreviewHandler实例作为COM组件.
我有一个interop程序集,定义IPreviewHandler和相关的接口.
当我使用Activator.CreateInstance()创建一个FIPreviewHandler实例时,GetTypeByCLSID()返回的类型使用FIPreviewHandler的正确CLSID,它返回一个托管实例,因为它有实际的程序集可用,并跳过COM .当我尝试QI /将此实例转换为任何接口,例如IPreviewHandler时,它返回null,因为它作为托管对象加载,尽管FIPreviewHandler实现的IPreviewHandler接口与我在interop中的接口相同,但它在一个不同的命名空间/程序集中,因此为null.如果要返回一个COM实例/ RCW(System .__ ComObject),它将不会占用命名空间,并且可以正常转换,并返回一个有效的实例.
FIPreviewHandler是一个32位组件,在64位Win7机器上,如果我将我的客户端应用程序编译为"任何CPU",Activator.CreateInstance()将返回一个COM实例/ RCW(System .__ ComObject),因为它会查找64位实现FIPreviewHandler,因此返回一个代理.在这种情况下,我的应用程序工作正常.但是当我为x86编译它时,它获得32位实现,并返回实际托管类的托管实例,而不是COM实例,因此失败.
我不能使用FIPreviewHandler程序集中定义的接口,因为我必须为IPreviewHandler编写通用客户端,我的应用程序将与任何实现IPreviewHandler的组件一起使用,这对于基于C++的客户端访问FIPreviewHandler作为COM对象非常有用,但是失败了对于托管客户端.
我希望我有意义,我真的很感激任何帮助.
我正在尝试编写从用户的Windows Media Player库中读取每个项目的代码.此代码适用于大多数用户,但对于某些用户,getAll()当他们的Windows Media Player库中明显包含数百或数千个项目时,将返回空列表.
var player = new WindowsMediaPlayer();
var collection = player.mediaCollection;
var list = collection.getAll();
int total = list.count;
Run Code Online (Sandbox Code Playgroud)
我WMPLib通过添加对wmp.dll的COM引用来引用命名空间.我的应用程序随附Interop.WMPLib.dll.如何配置某些用户的计算机,使其在其库中运行带有许多歌曲的Windows Media Player,但WMPLib无法正常运行?此外,在所有情况下可靠地读取用户的Windows Media Player库有哪些变通方法?
有时当我结束应用程序并尝试释放一些COM对象时,我会在调试器中收到警告:
RaceOnRCWCleanUp被发现了
如果我编写一个使用COM对象的类,我是否需要实现IDisposable并调用Marshal.FinalReleaseComObject它们IDisposable.Dispose才能正确释放它们?
如果Dispose没有手动调用,我还需要在终结器中释放它们还是GC会自动释放它们?现在我打电话Dispose(false)给终结者,但我想知道这是否正确.
我使用的COM对象也有一个类侦听的事件处理程序.显然,事件是在另一个线程上引发的,所以如果在处理类时触发它,如何正确处理呢?
希望这个问题不会太模糊.通过COM规范和Don Box的Essential COM书阅读,有很多关于"COM解决的问题"的讨论 - 而且它们听起来都很重要,相关且最新.
那么COM地址在其他系统(linux,unix,OSX,android)上处理的问题怎么样呢?我想的是:
我基本上只是想了解为什么例如Linux上的CORBA不是像COM这样的东西在Windows上(如果这是有道理的).Linux上的软件开发是否可以订阅与COM提出的基于组件的模型不同的理念?
最后,COM是C/C++的东西吗?有几次我遇到过人们的评论,他们说COM被.NET淘汰了,但没有真正解释他们的意思.
TL; DR是否所有生成的注册表项都regsvr32需要出现在SxS reg-free-COM清单中,反之亦然?
我正在尝试获得免注册的COM用于第三方组件.
读 了 关于主题,我发现有提到的几个要素,即可以放入一个清单:
从文档中,我们可以将以下标记添加到清单中以描述COM组件:
assemblyIdentity- 据我所知,这真的只是描述了"抽象集会 "comClass - 描述COM类(IID接口).看来,这总是需要的.typelib - 什么时候?comInterfaceExternalProxyStub - 什么时候?comInterfaceProxyStub - 什么时候?从其他文档HKEY_LOCAL_MACHINE\SOFTWARE\Classes我们可以看到COM注册表项有几个类别:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{CLSID} 我假设大致相当于comClassHKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{IID}将对应于任何一个 comInterface[External]ProxyStub,但我真的不知道何时使用哪个(或两者)typelib清单条目?使用regsvr42来提取我试图注册的dll会产生一个只包含comClass条目,没有typelib或ProxyStub条目的清单.(我交叉检查写的密钥,有问题的DLL pdm.dll,MS的Process Debug Manager只写那些密钥,也就是说,注册表中没有明显的类型库或代理存根信息.)
如果注册表只包含与此相关的信息,comClass则表示此信息在SxS清单中是足够的,或者清单中是否需要其他信息?
另外,我注意到注册表包含a VersionIndependentProgId和a ProgId,其末尾附加了版本号.清单只有一个ProgId条目,文档说明:
progid:与COM组件关联的与版本相关的编程标识符.ProgID的格式是
<vendor>.<component>.<version>.
但文档也说明了这一点
该comClass元素可以有
<progid>...</progid>子元素,其中列出的版本有关的ProgID.
并且他们说 progid属性应该是版本独立的属性.
那么,放在这里的是什么?当客户端没有请求特定版本时,它是否重要?
com ×10
c# ×5
.net ×4
c++ ×3
interop ×3
com-interop ×1
hresult ×1
manifest ×1
marshalling ×1
powershell ×1
proxy ×1
regfreecom ×1
side-by-side ×1
visual-c++ ×1
visual-c++-6 ×1
windows ×1
wmi ×1
wmp ×1