1

我目前正在尝试构建一个应该监视的简单组件,如果用户打开具有特定 URL 的窗口(仅限 IE)。所以我编写了这个组件,一切正常,所以我将它与需要它的应用程序集成在一起。问题是,在这个应用程序中使用了 PerformanceCounters,这些似乎扰乱了 InternetExplorer 自动化对象的行为。

所以我写了这个小示例来演示这个问题:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using SHDocVw;

namespace IEHookTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(PerfCounter);
            t.Start();

            URLInterceptor.Instance.StartListening();
            Console.ReadLine();
        }

        private static void PerfCounter()
        {
            PerformanceCounter cpuPc = 
                new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
            do
            {
                float x = cpuPc.NextValue();
                System.Diagnostics.Debug.WriteLine(x);
                Thread.Sleep(50);
            } while (true);
        }
    }

    class URLInterceptor
    {
        private const string DEMANDED_URL = "test";
        private ShellWindows _shellWindows = new ShellWindows();

        public static readonly URLInterceptor Instance = new URLInterceptor();
        private static int _count = 0;
        private URLInterceptor()
        {
        }

        public void StartListening()
        {
            _count++;
            _shellWindows.WindowRegistered -= ShellWindows_WindowRegistered;
            _shellWindows.WindowRegistered += new DShellWindowsEvents_WindowRegisteredEventHandler(ShellWindows_WindowRegistered);
            FindIEs();
        }

        private void FindIEs()
        {
            int count = 0;
            foreach (InternetExplorer browser in _shellWindows)
            {
                browser.NewWindow3 -= browser_NewWindow3;
                browser.NewWindow3 += new DWebBrowserEvents2_NewWindow3EventHandler(browser_NewWindow3);
                count++;
            }
        }

        private void ShellWindows_WindowRegistered(int lCookie)
        {
            FindIEs();
        }

        private void browser_NewWindow3(ref object ppDisp,
                                        ref bool Cancel,
                                        uint dwFlags,
                                        string bstrUrlContext,
                                        string bstrUrl)
        {
            if (!string.IsNullOrEmpty(bstrUrl) && bstrUrl.ToLower().Contains(DEMANDED_URL))
            {
                Cancel = true;
                Console.WriteLine("catched URL: " + bstrUrl);
            }
        }
    }
}

此示例需要对“Microsoft Internet 控件”(SHDocVw) 的引用。要测试示例,只需打开谷歌并搜索“测试”。获取第一个链接并在新选项卡或窗口中打开它。您会看到,有时会引发“NewWindow3”事件,有时不会。但是,如果您注释掉第 15 行(线程开始),对象将按预期工作,并为每个新窗口引发事件。

所以我的问题是,为什么性能计数器会干扰 InternetExplorer 对象,我该如何同时使用它们。我尝试在新的 AppDomain 中运行监视器组件,但这并没有解决问题。仅创建一个新流程是一种解决方案,但出于多种原因,这是我不想做的。

我正在使用 IE 7 在 Win2k3 服务器上进行测试。

4

1 回答 1

0

To keep the references in an Arraylist solves the problem. Seems that the ShellWindows Collection doesn't hold the references.

于 2008-11-06T14:40:50.490 回答