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

时间:2013-03-14 19:03:00

标签: c# com pinvoke shell32

如果我的术语已经关闭,请原谅我,因为这对我来说是一个未知的领域。

我有一个需要创建FolderShortcut的程序。 Microsoft has documentation关于如何在C ++中创建它,我正在尝试将方向转换为C#。说明指出需要使用CoCreateInstance作为参数调用CLSID_FolderShortcut函数,我推断这意味着它正在实例化COM对象。此对象的CLSID为{0AFACED1-E828-11D1-9187-B532F1E9575D}

我已尝试在COM标签中添加对 Shell32.dll 的引用,但FolderShortcut对象未显示在Intellisense中(可能它不在typelib中?)。我还想过做DLLImport,但是,当然,这只能让我访问函数,而不是对象。

在.Net中访问此对象需要做什么?

4 个答案:

答案 0 :(得分:7)

如果你不想在编译期间导入类,正如 Simon Mourier 描述的那样,也可以使用Activator对COM对象做一些后期绑定。

如果您已获得对象的ProgID,请使用

获取类型
Type comType = Type.GetTypeFromProgID("MyProg.ProgId");

否则你可以通过它CLSID获取类型:

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

使用此类型,您现在可以使用Activator.CreateInstance创建coclass的实例:

var instance = Activator.CreateInstance(comType);

基本上,您现在可以使用Type.InvokeMember调用方法。这仅在对象实现IDispatch接口时才有效。

但是对于您的具体示例,您应该能够将实例强制转换为System.Runtime.InteropServices.ComTypes.IPersistFile,这会导致对COM对象调用QueryInterface。使用此界面,您可以轻松访问IPersistFile的成员。

您可以继续阅读here

答案 1 :(得分:5)

这是一段允许您创建文件夹快捷方式的代码。 CoCreateInstance可以(通常)通过声明一个用Guid属性修饰的简单类来替换,该类具有所需的CLSID和ComImport属性。 new调用将自动执行COM魔术。使用此代码,您甚至不需要Shell32引用(或者如果您愿意,可以从那里重用IShellLink声明。)

用法:

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

代码:

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);
}

答案 2 :(得分:1)

您是否尝试添加新参考:

  1. 打开解决方案资源管理器
  2. 展开C#项目
  3. 右键单击引用节点并添加新的COM引用

答案 3 :(得分:0)

听起来您尝试使用“添加新的COM引用”添加COM。 这些是我试过的东西:

  1. 我首先要做的是确保您的COM DLL已在您的计算机中注册。如果没有,则注册它,然后尝试使用COM选项卡再次添加它。

  2. 你在64位机器上运行吗?尝试确保将项目属性设置为AnyCPU,以便能够读取32位COM。

  3. 确保您具有您尝试访问的DLL的互操作等效项。它通常命名为“Interop.YourDLLName.dll”。添加对该DLL的引用,这应该有用。