5

如果我的术语不对,请原谅我,因为这对我来说有点未知。

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

我尝试从 COM 选项卡中添加对Shell32.dllFolderShortcut的引用,但该对象没有出现在 Intellisense 中(也许它不在 typelib 中?)。我也想过做一个DLLImport,但是,当然,这只能让我访问函数,而不是对象。

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

4

4 回答 4

12

如果您不想在编译时导入类,正如Simon Mourier所描述的,也可以使用Activator.

如果你有ProgID你的对象,获取类型使用

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

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

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

使用这种类型,您现在可以使用以下方法创建 coclass 的实例Activator.CreateInstance

var instance = Activator.CreateInstance(comType);

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

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

您可以在此处继续阅读。

于 2013-03-15T09:40:43.743 回答
6

这是一段代码,可让您创建文件夹快捷方式。CoCreateInstance 可以(通常)通过声明一个简单的类来替换,该类用具有所需 CLSID的Guid属性和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);
}
于 2013-03-15T09:06:56.840 回答
1

您是否尝试添加新参考:

  1. 打开解决方案资源管理器
  2. 展开 C# 项目
  3. 右键单击引用节点并添加一个新的 COM 引用
于 2013-03-14T19:06:40.950 回答
0

听起来您已经尝试使用“添加新的 COM 引用”添加您的 COM。这些是我会尝试的事情:

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

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

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

于 2013-03-14T19:11:35.873 回答