简体   繁体   English

如何通过CLSID在C#中实例化COM对象?

[英]How do I go about instantiating a COM Object in C# by CLSID?

Forgive me if my terminology is off, as this is somewhat uncharted territory for me. 如果我的术语已经关闭,请原谅我,因为这对我来说是一个有点未知的领域。

I have a program which needs to create a FolderShortcut . 我有一个程序需要创建FolderShortcut Microsoft has documentation on how to create it in C++, and I'm trying to translate the directions to C#. Microsoft有关于如何使用C ++创建它的文档 ,我正在尝试将方向转换为C#。 The instructions state that the CoCreateInstance function needs to be called with CLSID_FolderShortcut as a parameter, which I infer to mean that it's instantiating a COM object. 指令声明需要使用CLSID_FolderShortcut作为参数调用CoCreateInstance函数,我推断这意味着它实例化了一个COM对象。 The CLSID for this object is {0AFACED1-E828-11D1-9187-B532F1E9575D} . 该对象的CLSID是{0AFACED1-E828-11D1-9187-B532F1E9575D}

I've tried adding a reference to Shell32.dll from the COM tab, but the FolderShortcut object does not show up in Intellisense (maybe it's not in the typelib?). 我尝试从COM选项卡添加对Shell32.dll的引用,但是FolderShortcut对象没有出现在Intellisense中(也许它不在typelib中?)。 I also thought about doing a DLLImport , but, of course, that only gives me access to functions, not objects. 我还想过做一个DLLImport ,但是,当然,这只能让我访问函数,而不是对象。

What do I need to do to get access to this object in .Net? 要在.Net中访问此对象,我需要做什么?

If you do not want to import the classes during compile time, as Simon Mourier describes it is also possible to do some late binding to the COM objects, using Activator . 如果您不想在编译期间导入类,正如Simon Mourier描述的那样,使用Activator也可以对COM对象进行一些后期绑定。

If you've got the ProgID of your object, get the type using 如果你有对象的ProgID ,请使用类型

Type comType = Type.GetTypeFromProgID("MyProg.ProgId");

otherwise you can get the type by it's CLSID : 否则你可以通过它的CLSID得到类型:

Type comType = 
    Type.GetTypeFromCLSID(new Guid("0AFACED1-E828-11D1-9187-B532F1E9575D"));

Using this type, you are now able to create an instance of the coclass, using Activator.CreateInstance : 使用此类型,您现在可以使用Activator.CreateInstance创建coclass的实例:

var instance = Activator.CreateInstance(comType);

Basicly you can now invoke methods using Type.InvokeMember . 基本上,您现在可以使用Type.InvokeMember调用方法。 This only works if the object implements the IDispatch interface. 这仅在对象实现IDispatch接口时有效。

However for your specific example you should be able to cast the instance to System.Runtime.InteropServices.ComTypes.IPersistFile , which results in an call to QueryInterface for COM objects. 但是,对于您的特定示例,您应该能够将实例System.Runtime.InteropServices.ComTypes.IPersistFileSystem.Runtime.InteropServices.ComTypes.IPersistFile ,这会导致对COM对象的QueryInterface的调用。 Using this interface you can easily access the members of IPersistFile . 使用此界面,您可以轻松访问IPersistFile的成员。

You may continue here with further reading. 您可以继续在这里进一步阅读。

Here is a piece of code that allows you to create a folder shortcut. 这是一段代码,允许您创建文件夹快捷方式。 The CoCreateInstance can (in general) be replaced by declaring a simple class decorated with the Guid attribute with the required CLSID, and the ComImport attribute. CoCreateInstance可以(通常)通过声明一个用Guid属性修饰的简单类来替换,该类具有所需的CLSID和ComImport属性。 The new call will do the COM magic automatically. new调用将自动执行COM魔术。 With this code, you don't even need a Shell32 reference (or you can reuse the IShellLink declaration from there if you prefer). 使用此代码,您甚至不需要Shell32引用(或者如果您愿意,可以从那里重用IShellLink声明)。

Usage: 用法:

static void Main(string[] args)
{
    CreateFolderShortcut(@"c:\temp", Path.GetFullPath("Shortcut to Temp"));
}

Code: 码:

public static void CreateFolderShortcut(string path, string shortcutPath)
{
    CreateFolderShortcut(path, shortcutPath, null);
}

public static void CreateFolderShortcut(string path, string shortcutPath, string comment)
{
    if (path == null)
        throw new ArgumentNullException("path");

    IShellLink link = (IShellLink)new ShellLinkFolder();

    if (comment != null)
    {
        link.SetDescription(comment);
    }
    link.SetPath(path);

    IPersistFile file = (IPersistFile)link;
    file.Save(shortcutPath, false);
}

[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
private class ShellLink
{
}

[ComImport]
[Guid("0AFACED1-E828-11D1-9187-B532F1E9575D")]
private class ShellLinkFolder
{
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
private interface IShellLink
{
    void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
    void GetIDList(out IntPtr ppidl);
    void SetIDList(IntPtr pidl);
    void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
    void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
    void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
    void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
    void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
    void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
    void GetHotkey(out short pwHotkey);
    void SetHotkey(short wHotkey);
    void GetShowCmd(out int piShowCmd);
    void SetShowCmd(int iShowCmd);
    void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
    void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
    void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
    void Resolve(IntPtr hwnd, int fFlags);
    void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}

Did you try to add a new reference: 您是否尝试添加新参考:

  1. Open Solution Explorer Open Solution Explorer
  2. Expand the C# project 展开C#项目
  3. Right click on the references node and add a new COM reference 右键单击引用节点并添加新的COM引用

It sounds like that you have tried adding your COM using the "Add a new COM reference". 听起来你已尝试使用“添加新的COM引用”添加COM。 These are the things that I'd try: 这些是我尝试的东西:

  1. What I'd do first is to make sure that your COM DLL is registered in your computer. 我首先要做的是确保您的COM DLL已在您的计算机中注册。 If not then register it then try to add it again using the COM tab. 如果没有,则注册它然后尝试使用COM选项卡再次添加它。

  2. Are you running on a 64bit machine? 你在64位机器上运行吗? Try to also make sure that your project properties is set to AnyCPU for it to be able to read the 32bit COM. 尝试确保将项目属性设置为AnyCPU,以便能够读取32位COM。

  3. Make sure that you have the interop equivalent of the DLL that you are trying to access. 确保您具有要尝试访问的DLL的互操作等效项。 It is usually named like "Interop.YourDLLName.dll". 它通常命名为“Interop.YourDLLName.dll”。 Add a reference to that DLL and that should work. 添加对该DLL的引用,这应该有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM