Pergunta

Eu preciso usar o controle WinForms WebBrowser em um aplicativo ASP.NET, a fim de tirar screenshots de páginas da web.

Eu prefiro executá-lo em um aplicativo de console, e comunicar ao aplicativo por meio do aplicativo ASP.NET, mas não é o meu apelo, eu tenho dito que tem que ser executado como parte do site.

Tudo muito bonito funciona para além de cada chamada para começa Navegar fresco com uma nova sessão, é como se os cookies não estão sendo persistiu. Como uma experiência, eu mudei de IIS pool de aplicativos para executar como me em vez de NETWORK_SERVICE, e tudo funciona bem. Por isso é algo estranho nisso executado como serviço de rede.

Eu estou supondo que a conta de serviço de rede não tem as permissões para acompanhar o cookie ASP.NET_SessionId eo cookie de autenticação, mas ambos estes são cookies não persistentes, então eu não sei por que ser.

Aqui está um código simplificado para que possa obter a essência do que estou fazendo. Há um monte de registrar e armazenar de imagens que eu cortei, por isso não é de código completo. Basicamente, um desenvolvedor / testador / admin pode executar este código uma vez (tarefa expulso via web), ele irá gerar bitmaps de todas as páginas no sistema, eles podem lançar uma nova versão do site e, em seguida, executá-lo novamente, ele vai dizer as diferenças (novas páginas, páginas removidas, as páginas alteradas).

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();
    }
}

Então, em resumo:

  • O código acima é iniciado por uma página ASP.NET e ele é executado no backgound
  • Ele funciona muito bem se eu executá-lo em um conjunto de pool de aplicativos IIS para ser executado como um usuário adequada
  • Se eu executá-lo em um pool de aplicativos IIS como NETWORK_SERVICE então cada navegar tem uma nova sessão, em vez de persistir uma sessão para a vida do WebBrowser.
  • Eu posso fazê-lo funcionar bem fora do ASP.NET, mas isso não é uma opção para mim no momento, ele tem que correr dentro desta aplicação ASP.NET.

// Atualização

Seguindo o conselho do meu colega eu estou usando a representação no segmento de segundo plano onde eu estou criando o WebBrowser, funcionando como um usuário local. Isso funciona bem e estou muito feliz com esta solução. Ele é um usuário stackoverflow então eu vou deixá-lo postar a resposta e obter o crédito:)

Foi útil?

Solução

Usando a representação no segmento de segundo plano permitiria que o WebBrowser para ser executado como um usuário com permissões para executar IE e, assim, armazenar cookies, ao invés de correr como o usuário pool de aplicativos (NETWORK_SERVICE).

Você pode configurar a representação no web.config ou programaticamente para restringi-la a um tópico específico.

Outras dicas

não offcially apoiada devido ao seu uso de WinInet. consulte http://support.microsoft.com/kb/238425 para limitações de WinInet em um serviço.

Você vê o cookie de sessão nos pedidos vindos do controle WebBrowser? Eu não consigo encontrar nada sobre como este controle é suposto biscoitos punho - se ignora-los você teria o comportamento que você está descrevendo

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top