InvokeMember可能获取特定属性值的值

时间:2017-04-10 07:32:21

标签: c# .net windows com windows-explorer

我引用this thread刷新Windows资源管理器,我只想刷新一些窗口,这意味着我想根据标题或路径过滤打开的窗口。让我复制该线程中的代码以获得更多说明:

Guid CLSID_ShellApplication = new Guid("13709620-C279-11CE-A49E-444553540000");
Type shellApplicationType = Type.GetTypeFromCLSID(CLSID_ShellApplication, true);

object shellApplication = Activator.CreateInstance(shellApplicationType);
object windows = shellApplicationType.InvokeMember("Windows", System.Reflection.BindingFlags.InvokeMethod, null, shellApplication, new object[] { });

Type windowsType = windows.GetType();
object count = windowsType.InvokeMember("Count", System.Reflection.BindingFlags.GetProperty, null, windows, null);
for (int i = 0; i < (int)count; i++)
{
    object item = windowsType.InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, windows, new object[] { i });
    Type itemType = item.GetType();

    string itemName = (string)itemType.InvokeMember("Name", System.Reflection.BindingFlags.GetProperty, null, item, null);
    if (itemName == "Windows Explorer")
    {
        // Here I want to check whether this window need to be refreshed
        // based on the opened path in that window
        // or with the title of that window
        // How do I check that here
        itemType.InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, item, null);
    }
}

我从上面的代码中理解的是:通过使用这一行windowsType.InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, windows, new object[] { i });,我们将得到当前的窗口对象,然后我们使用.InvokeMember("Name"..来获取该对象的名称,就像明智的一样我应该传递给InvokeMember方法来获取该对象的路径或该窗口的标题吗?或者任何人都可以在上述声明中告诉我"Name"可能的替代值?

我期待的是一些如下代码:

 string itemPath = (string)itemType.InvokeMember("Something here", System.Reflection.BindingFlags.GetProperty, null, item, null);

OR

 string itemTitle = (string)itemType.InvokeMember("Something here", System.Reflection.BindingFlags.GetProperty, null, item, null);

如果您需要,我可以为您提供更多信息,希望专家提出解决此问题的建议,

提前致谢

1 个答案:

答案 0 :(得分:2)

这是您在Bad Old Days中编写后期绑定COM客户端代码的方法。为了实现它,相当大的痛苦和痛苦,片段中的内容还没有结束。我首先提出了一种非常不同的方法来实现这一点,因为这些COM对象在任何Windows版本上都可用,并且永远不会再改变,因此没有任何意义可以做到这一点。 &#34;嵌入互操作类型&#34;自VS2010以来支持的功能消除了任何避免它的理由。

项目&gt;添加参考&gt; COM选项卡。勾选&#34; Microsoft Internet Controls&#34;和#34; Microsoft Shell控件和自动化&#34;。现在,您可以使用IntelliSense的所有优点,尽早编写它,并且可以帮助您找到正确的成员并避免拼写错误:

var shl = new Shell32.Shell();
foreach (SHDocVw.InternetExplorer win in shl.Windows()) {
    var path = win.LocationURL;
    if (!path.StartsWith("file:///")) continue;
    path = System.IO.Path.GetFullPath(path.Substring(8));
    if (path.StartsWith("C")) win.Refresh();
}

一个稍微愚蠢的例子,它会刷新任何资源管理器窗口,其中显示的路径位于C盘上。请注意Path属性如何用于发现显示的内容,需要LocationURL。您可能必须找到Internet Explorer和Windows资源管理器窗口之间的区别(又名&#34;文件资源管理器&#34;),虽然IE也可以显示目录内容,所以我认为这是最正确的版本。

如果你真的想要这么做,那么请使用dynamic关键字来减少痛苦。在这种情况下几乎相同:

dynamic shl = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
foreach (var win in shl.Windows()) {
    string path = win.LocationURL;
    if (!path.StartsWith("file:///")) continue;
    path = System.IO.Path.GetFullPath(path.Substring(8));
    if (path.StartsWith("C")) win.Refresh();
}

明确回答您的问题,使用&#34; LocationURL&#34;。