2009-11-26 69 views
2

我需要在ASP.NET應用程序中使用WinForms WebBrowser控件才能截取網頁截圖。將WinForms WebBrowser控件作爲NETWORK_SERVICE運行

我寧願在控制檯應用程序中運行它,並通過ASP.NET應用程序與應用程序通信,但它不是我的電話,我被告知它必須作爲網站的一部分運行。

除了每次調用導航都會從新會話開始新鮮開始,它就像餅乾沒有被持久保存一樣。作爲一個實驗,我將我的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頁面啓動,並在backgound運行
  • ,如果我在一個IIS應用程序池集運行它,它工作正常以適當的用戶身份運行
  • 如果我將其作爲NETWORK_SERVICE在IIS應用程序池中運行,則每個導航都會有一個新的會話,而不是在WebBrowser的生命週期中保留一個會話。
  • 我可以在ASP.NET以外的地方正常工作,但目前這不是我的選擇,它必須在此ASP.NET應用程序中運行。

//更新

在我的同事,我使用模擬在後臺線程在那裏我創建的web瀏覽器,運行的本地用戶的意見。這工作正常,我很滿意這個解決方案。他是一個計算器用戶,所以我會讓他發佈答案並獲得信用:)

+0

你能準確地分享你開始和停止冒充的地方嗎?我有它的工作(環境。UserName會返回所期望的),但瀏覽器仍然不會保留cookie。相反,如果我將App Pool設置爲以相同用戶身份運行,那麼它工作正常...... – Roman 2014-05-21 05:37:24

回答

2

在後臺線程中使用模擬將允許WebBrowser以具有運行IE的權限運行的用戶從而存儲Cookie,而不是以應用程序池用戶(NETWORK_SERVICE)運行。

您可以在web.configprogramatically中設置模擬,將其限制爲特定線程。

+0

我的世界現在是一個更好的地方。 – 2009-11-27 10:45:38

0

您是否在來自WebBrowser控件的請求中看到會話cookie?我找不到這個控件應該如何處理cookie - 如果它忽略它們,你會得到你所描述的行爲

+0

在任何WebBrowser屬性中,在它工作的情況下,以及不在其中的情況下。我認爲控制基本上運行IE瀏覽器,所以這是有道理的,這是一些權限問題停止工作的cookie。根據我的同事的建議,我會嘗試在線程中扮演角色,讓其以本地用戶身份運行。 – 2009-11-27 09:15:37

2

由於使用WinInet而不是正式支持。有關WinInet在服務中的限制,請參閱http://support.microsoft.com/kb/238425

+0

感謝您的鏈接,這解釋得非常好。 – 2009-11-30 08:25:13