在COM对象上使用早期绑定

时间:2009-04-22 09:18:15

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

我有一段非常好的代码,并为我提供了用户开始菜单的路径:

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

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

这可能吗?怎么样?

谢谢你的帮助!

4 个答案:

答案 0 :(得分:4)

如果你想解决这个问题,你需要弄清楚,在VB项目中添加哪个COM引用。

打开注册表并导航到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,并添加对此文件的引用(在添加引用对话框的浏览选项卡上)。如果打开项目属性,您实际上会看到添加的COM组件的好名称是 Microsoft Shell控件和自动化

添加引用后,您可以使用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中执行相同的操作。
Dim path As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)

答案 1 :(得分:3)

实际上你可以使用反射:

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来清理这个混乱。

答案 2 :(得分:2)

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

有关详情,请参阅here

答案 3 :(得分:0)

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