将WinForms WebBrowser控件作为NETWORK_SERVICE运行

时间:2009-11-26 15:50:38

标签: c# asp.net webbrowser-control

我需要在ASP.NET应用程序中使用WinForms WebBrowser控件才能截取网页截图。

我宁愿在控制台应用程序中运行它,并通过ASP.NET应用程序与应用程序通信,但这不是我的电话,我被告知它必须作为网站的一部分运行。

除了每次使用新会话开始新的调用之外,这一切都非常有效,就像cookie没有被持久化一样。作为一个实验,我改变了我的IIS应用程序池以像我一样运行而不是NETWORK_SERVICE,它一切正常。所以它作为网络服务运行有点奇怪。

我猜测网络服务帐户没有跟踪ASP.NET_SessionId cookie和auth cookie的权限,但这些都是非持久性cookie,所以我不知道为什么会这样是

这是一些简化的代码,因此您可以了解我正在做的事情。我删除了大量的日志记录和存储图像,因此它不是完整的代码。基本上开发人员/测试人员/管理员可以运行此代码一次(任务通过网页启动),它将生成系统中每个页面的位图,他们可以发布新版本的网站,然后再次运行它,它会告诉你差异(新页面,删除的页面,页面已更改)。

public void Run()
{
    var t = new Thread(RunThread);
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
}

private void RunThread()
{
    try
    {
        using (var browser = new WebBrowser())
        {
            browser.DocumentCompleted += BrowserDocumentCompleted;

            if (!VisitPage(browser, "special page that sets some session flags for testing - makes content predictable")))
                throw new TestRunException("Unable to disable randomness");

            foreach (var page in pages)
            {
                VisitPage(browser, page);
            }
        }
    }
    // An unhandled exception in a background thread in ASP.NET causes the app to be recycled, so catch everything here
    catch (Exception)
    {
        Status = TestStatus.Aborted;
    }
}

private bool VisitPage(WebBrowser browser, string page)
{
    finishedEvent.Reset();

    var timeout = false;
    stopwatch = new Stopwatch();

    browser.Navigate(page);

    stopwatch.Start();

    while (!timeout && !finishedEvent.WaitOne(0))
    {
        Application.DoEvents();
        if (stopwatch.ElapsedMilliseconds > 10000)
            timeout = true;
    }
    Application.DoEvents();

    if (timeout)
    {
        if (resource != null)
            ShopData.Shop.LogPageCrawlTestLine(testRunID, resource, sequence++, (int)stopwatch.ElapsedMilliseconds, null);
    }

    browser.Stop();

    return !timeout;
}

private void BrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    try
    {
        var browser = (WebBrowser)sender;

        var width = browser.Document.Body.ScrollRectangle.Width;
        var height = browser.Document.Body.ScrollRectangle.Height;
        var timeTaken = (int)stopwatch.ElapsedMilliseconds;

        if ((width == 0) || (height == 0))
        {
            return;
        }

        browser.Width = width;
        browser.Height = height;

        byte[] buffer;

        using (var bitmap = new Bitmap(width, height))
        using (var memoryStream = new MemoryStream())
        {
            browser.DrawToBitmap(bitmap, new Rectangle(0, 0, width, height));
            bitmap.Save(memoryStream, ImageFormat.Bmp);
            buffer = memoryStream.ToArray();
        }
        // stores image

    }
    finally
    {
        finishedEvent.Set();
    }
}

总结如下:

  • 以上代码由ASP.NET页面启动,并在背景中运行
  • 如果我在一个IIS应用程序池中运行它以便作为一个合适的用户运行
  • ,它可以正常工作
  • 如果我在IIS应用程序池中将其作为NETWORK_SERVICE运行,则每次导航都会有一个新会话,而不是在WebBrowser的生命周期内持久保存会话。
  • 我可以在ASP.NET之外使它工作正常,但这对我来说不是一个选项,它必须在这个ASP.NET应用程序中运行。

//更新

根据我的同事的建议,我在后台线程中使用模拟,我正在创建WebBrowser,以本地用户身份运行。这很好用,我很满意这个解决方案。他是一个stackoverflow用户,所以我会让他发布答案并获得信用:)

3 个答案:

答案 0 :(得分:2)

在后台线程中使用模拟将允许WebBrowser作为具有运行IE的权限的用户运行,从而存储cookie,而不是作为应用程序池用户(NETWORK_SERVICE)运行。

您可以在web.configprogramatically中设置模拟,以将其限制为特定主题。

答案 1 :(得分:2)

由于使用了WinInet,因此不受官方支持。有关服务中WinInet的限制,请参阅http://support.microsoft.com/kb/238425

答案 2 :(得分:0)

您是否在来自WebBrowser控件的请求中看到了会话cookie?我找不到任何关于这个控件应该如何处理cookie的东西 - 如果忽略它们你会得到你描述的行为