【问题标题】:Using early binding on a COM object在 COM 对象上使用早期绑定
【发布时间】:2010-10-21 01:14:56
【问题描述】:

我的这段代码运行良好,并为我提供了用户开始菜单的路径:

    Dim oShell As Object = CreateObject("Shell.Application")
    MsgBox(oShell.NameSpace(11).Self.Path)

这显然使用了后期绑定。现在说我想在 C# 或 VB.NET 严格模式下执行此操作,它们都不支持这种带有后期绑定的语法。

这可能吗?怎么样?

感谢您的帮助!

【问题讨论】:

    标签: vb.net com late-binding option-strict


    【解决方案1】:

    如果你想用 COM 方式解决这个问题,你必须弄清楚在你的 VB 项目中添加哪个 COM 引用。

    打开 regedit 并导航到HKEY_CLASSES_ROOT\<class id>\CLSID,即

    HKEY_CLASSES_ROOT\Shell.Application\CLSID
    

    您将找到唯一标识 COM 组件的类 ID。

    HKEY_CLASSES_ROOT\CLSID 下,您现在可以查看 COM 组件后面的文件:

    HKEY_CLASSES_ROOT\CLSID\{13709620-C279-11CE-A49E-444553540000}\InProcServer32
    

    显示以下值:

    %SystemRoot%\system32\SHELL32.dll
    

    现在转到 Visual Studio,并添加对此文件的引用(在 Add References 对话框的 Browse 选项卡上)。如果您打开项目属性,您实际上会看到添加的 COM 组件的好听的名称是 Microsoft Shell Controls and Automation

    添加引用后,您可以使用Shell.Application 对象,如下所示:

    Option Strict On
    
    Module PrintStartMenuLocation
    
        Sub Main()
            Dim shell As New Shell32.Shell
            Dim folder As Shell32.Folder
            Dim folderItem As Shell32.FolderItem
            Dim startMenuPath As String
    
            folder = shell.NameSpace(Shell32.ShellSpecialFolderConstants.ssfSTARTMENU)
            folderItem = CType(folder.Items(0), Shell32.FolderItem)
            startMenuPath = folderItem.Path
    
            Console.WriteLine(startMenuPath)
        End Sub
    
    End Module
    

    C# 版本如下所示:

    class Program
    {
        static void Main(string[] args)
        {
            Shell32.Shell shell = new Shell32.Shell();
            Shell32.Folder folder = shell.NameSpace(Shell32.ShellSpecialFolderConstants.ssfSTARTMENU);
            Shell32.FolderItem folderItem = folder.Items().Item(0) as Shell32.FolderItem;
            string startMenuPath = folderItem.Path;
    
            Console.WriteLine(startMenuPath);
        }
    }
    

    但是,如果您只需要检索开始菜单文件夹的位置,您可以使用 .NET 直接在 .NET 中执行相同操作

    Dim path As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
    

    【讨论】:

      【解决方案2】:

      其实你可以使用反射:

      Type shellType = Type.GetTypeFromProgID("Shell.Application", true);
      object shell = Activator.CreateInstance(shellType);
      object folder = shellType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shell, new object[] { 11 });
      object self = folder.GetType().InvokeMember("Self", BindingFlags.GetProperty, null, folder, new object[] { });
      object path = self.GetType().InvokeMember("Path", BindingFlags.GetProperty, null, self, new object[] { });
      Console.WriteLine(path);
      

      不是我喜欢的那种代码,但在 C# 4.0 中,你可以使用 dynamic type 来清理这个烂摊子。

      【讨论】:

      • 据我了解,OP 想要使用 early 绑定的问题。
      【解决方案3】:
      Dim DirPath As String = _
          System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
      

      请参阅here 了解更多信息。

      【讨论】:

        【解决方案4】:

        如果我没记错的话,您所要做的就是将对象引用转换为适当的接口。如果您在 .NET 中使用 COM 对象,您通常会导入类型库,然后让接口随时可用。

        【讨论】:

        • 但我不知道那个接口会是什么,实际上我什至不确定它是否一定总是返回的同一个接口......
        • 如果您不确定界面,那么早期绑定不适合您。这就是早期绑定的重点——编译器必须知道它是什么接口,并且可以检查参数的有效性并生成调用。否则你必须使用后期绑定。
        • 我明白,但假设我用 C# 编码,我不能使用后期绑定。是在 C# 中找出接口名称的唯一方法吗?
        • 您应该重述这个问题或请其他人明确询问如何在 C# 中执行此操作,以便 C# 专家看到并回答您的问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-25
        • 1970-01-01
        • 2016-12-15
        • 1970-01-01
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        相关资源
        最近更新 更多