我正在开发一个具有'finder'工具的应用程序的一部分,该工具允许用户将finder拖放到应用程序或Internet Explorer Web浏览器上,以便我们的程序可以找到它并执行它需要的操作去做。这部分应用程序在过去几年没有进行任何积极的开发(上次我认为IE 7是最新的浏览器),但它适用于IE 9及更低版本。从IE 10开始我们遇到问题,我特意使用的是IE 11。
以下代码查找不同的Internet Explorer窗口(包括选项卡)和文件资源管理器窗口。我们制作了一个快速的VB脚本以进行额外的测试 -
dim objShell
dim objShellWindows
set objShell = CreateObject("shell.application")
set objShellWindows = objShell.Windows
if (not objShellWindows is nothing) then
WScript.Echo objShellWindows.Count
for each win in objShellWindows
wscript.Echo TypeName(win)
WScript.Echo win.LocationUrl
WScript.Echo win.LocationName
WScript.Echo win.HWND
next
end if
set objShellWindows = nothing
set objShell = nothing
上面的代码会毫无错误地执行,它会给出我们打开的所有标签的URL和标题栏名称。
以下是我们的C#代码。它试图获取主IE窗口(而不是选项卡)。 this.Handle
是查找器工具在用户放下它时获取的主IE窗口的句柄。我们试图遍历打开的窗口并找到用户选择的Internet Explorer窗口。此特定代码段与我们的原始实现稍有不同,但最终结果是相同的。只要它点击test = window.Item(i)
,它就会抛出UnauthorizedAccessException
。
ShellWindows windows = null;
IWebBrowser2 shellWindow = null;
IHTMLDocument2 actualDoc = null;
Type shellApplicationType = Type.GetTypeFromProgID("Shell.Application");
Shell32.Shell shellInterface = (Shell32.Shell)Activator.CreateInstance(shellApplicationType);
windows = (ShellWindows)shellInterface.Windows();
bool found = false;
for (int i = 0; i < windows.Count; i++)
{
try
{
object test;
try
{
test = windows.Item(i); //Exception here
shellWindow = (IWebBrowser2)test;
}
catch
{
}
if (shellWindow != null && (IntPtr)shellWindow.HWND == this.Handle)
{
//the rest of the code gets the correct tab from the main IE window
这是我们第一次重新访问该部分程序时未经编辑的原始代码。
ShellWindows windows = null;
IWebBrowser2 shellWindow =null;
IHTMLDocument2 actualDoc = null;
windows = new SHDocVw.ShellWindowsClass();
bool found = false;
for (int i = 0; i < windows.Count; i++)
{
try{
shellWindow = windows.Item(i) as SHDocVw.IWebBrowser2; //Exception here
if (shellWindow != null && (IntPtr)shellWindow.HWND == this.Handle)
{
我还要注意,我已经尝试了遵循此语法的for
循环,而不是foreach
循环
foreach(IWebBrowser2 browser in windows)
和
foreach(InternetExplorer browser in windows)
在这些情况下,循环会跳过IE窗口。
我查看了IE的安全设置。我已禁用增强保护模式并允许跨域。似乎没有关于这个问题的大量信息,我们尝试的每一种方法似乎总是以UnauthorizedAccessException
结束。
编辑:为了回应Hans的回答,我没有在这台机器上运行任何反恶意软件。它是一个具有Windows 7的虚拟机,具有最新的SP和更新(没有微软安全要领)。我尝试在具有类似设置的32位机器上运行应用程序,但也失败了。在IE 11上测试之后,我卸载了IE 11,重新启动,尝试了IE 10(它失败了,同样的错误),卸载了IE 10,重新启动,尝试了IE 9,并且它在没有对系统进行任何其他更改的情况下工作。
以下是汉斯要求的SSCCE。此代码实际上适用于我的目标计算机。我将在第二天或第二天回到这篇文章,同时处理需要我注意的其他任务。
我将其构建为32位控制台应用程序,并在64位计算机上运行。
using System;
using SHDocVw;
using mshtml;
namespace GetBrowserSSCCE
{
class Program
{
static void Main(string[] args)
{
ShellWindows windows = null;
IWebBrowser2 shellWindow = null;
windows = new SHDocVw.ShellWindowsClass();
for (int i = 0; i < windows.Count; i++)
{
try
{
shellWindow = windows.Item(i) as SHDocVw.IWebBrowser2;
Console.WriteLine(string.Format("Window Found. HWND: {0}\nName: {1}", shellWindow.HWND, shellWindow.Name));
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("UnauthorizedAccessException caught. Exception Text: " +ex.Message);
}
}
Console.ReadLine();
}
}
}
答案 0 :(得分:4)
这在您的C#程序中失败,但是当您从VBScript解释器强烈将其运行到环境问题时,它就失败了。两者都使用完全相同的shell接口。之前已经在interwebs上报告了特定异常(基础错误代码为0x8007005)但从未诊断过。
当您遇到环境问题(尤其是与访问权限相关的类型)时,您应该首先关注的是计算机上安装的反恶意软件。禁用它然后重试。
您应该关注的第二个问题是与ShellWindows相关的怪癖,它不仅枚举Internet Explorer窗口,还会枚举Windows资源管理器窗口。你一直在寻找足够的IE访问权限,但这还不够,如果你碰巧打开了一个资源管理器窗口并且explorer.exe进程存在访问问题,这段代码也会失败。请注意,您的Activator.CreateInstance()方法调用不等同于VBScript代码,Activator.GetObject()是。因此,如果这是潜在问题,那么您的更改实际上会使问题变得更糟。
值得检查的第三个细节是过程的重要性。默认情况下,VBScript代码将在引导64位版本Windows的计算机上的64位脚本解释器中运行。但是C#项目的默认设置是以32位模式运行。右键单击EXE项目,“属性”,“构建”选项卡,然后使用“平台目标”设置进行修补,如果看到,则选中“首选32位”复选框。这不是对错误代码的解释,但它可能会影响反恶意软件侵入的有效性。