Winforms Webbrowser 컨트롤을 Network_Service로 실행합니다
-
05-07-2019 - |
문제
웹 페이지의 스크린 샷을 찍으려면 ASP.NET 응용 프로그램에서 WinForms Webbrowser 컨트롤을 사용해야합니다.
콘솔 앱에서 많이 실행하고 ASP.NET 응용 프로그램을 통해 앱에 통신하지만 내 전화가 아니며 웹 사이트의 일부로 실행해야한다고 들었습니다.
탐색을위한 모든 호출과는 별도로 새로운 세션으로 새로 시작하는 것과는 거의 작동합니다. 쿠키가 지속되지 않는 것과 같습니다. 실험으로, 나는 IIS 응용 프로그램 풀을 Network_Service 대신 나처럼 실행하도록 변경했으며 모두 잘 작동합니다. 따라서 네트워크 서비스로 실행하는 것은 이상한 일입니다.
네트워크 서비스 계정에 ASP.NET_SESSITEID 쿠키와 인증 쿠키를 추적 할 권한이 없다고 생각합니다. 그러나 두 가지 모두 비가 유능한 쿠키이므로 왜 그런지 모르겠습니다.
다음은 단순화 된 코드가 있으므로 내가하고있는 일의 요점을 얻을 수 있습니다. 잘라낸 이미지의 로깅 및 저장이 있으므로 완전한 코드가 아닙니다. 기본적으로 개발자/테스터/관리자는 한 번이 코드를 실행할 수 있습니다 (웹 페이지를 통해 작업이 시작됨) 시스템의 모든 페이지의 비트 맵을 생성하고 웹 사이트의 새 버전을 출시 한 다음 다시 실행할 수 있습니다. 차이점 (새 페이지, 제거 된 페이지, 페이지 변경).
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 애플리케이션 풀에서 실행하면 잘 작동합니다.
- IIS 애플리케이션 풀에서 네트워크로 실행하면 모든 탐색에는 웹 브라우저의 수명을위한 세션을 지속하지 않고 새 세션이 있습니다.
- ASP.NET 외부에서 잘 작동 할 수 있지만 현재는 옵션이 아니므 로이 ASP.NET 응용 프로그램에서 실행해야합니다.
//업데이트
내 동료의 조언에 따라 나는 웹 브라우저를 만들고 로컬 사용자로 실행하는 백그라운드 스레드에서 가장합니다. 이것은 잘 작동 하며이 솔루션에 매우 만족합니다. 그는 stackoverflow 사용자이므로 답을 게시하고 크레딧을 받도록하겠습니다 :)
해결책
백그라운드 스레드에서 가장하는 데있어서 Webbrowser는 Application Pool 사용자 (Network_Service)로 실행되는 대신 IE를 실행하는 권한을 가진 사용자로 실행할 수 있습니다.
당신은에 가장을 설정할 수 있습니다 web.config 또는 프로그램 적으로 특정 스레드로 제한합니다.
다른 팁
Wininet 사용으로 인해 비교적으로 지원되지 않습니다. 보다 http://support.microsoft.com/kb/238425 서비스에서 Wininet의 한계.
웹 브라우저 컨트롤에서 오는 요청에서 세션 쿠키가 보이나요? 이 컨트롤이 쿠키를 처리하는 방법에 대해 아무것도 찾을 수 없습니다. 쿠키를 무시하면 설명하는 동작을 얻을 수 있습니다.