2012-12-18 124 views
0

我已經與HttpListenter東西鬼混發現在:HttpLisenter啓動方法在Windows服務啓動失敗

http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

它在標準控制檯應用程序的偉大工程,但我試圖得到它作爲Windows服務工作。應用程序日誌顯示服務啓動時,它在HttpListener.Start()方法上失敗。我非常難以理解爲什麼會發生這種情況。

這裏的概念質量在這裏:)

public class Server 
{ 
    public Server() 
    { 
     var thread = new Thread((Start)); 
     thread.Start(); 
    } 

    public static void Start() 
    { 
     while(Listen()) 
     { 
     } 
    } 

    private static bool Listen() 
    { 
     var prefixes = new[] {"http://192.168.0.7/"}; 

     if (!HttpListener.IsSupported) 
     { 
      Console.WriteLine ("Windows XP SP2 or Server 2003 is required to use the HttpListener class."); 
      return false; 
     } 
     // URI prefixes are required, 
     // for example "http://contoso.com:8080/index/". 
     if (prefixes == null || prefixes.Length == 0) 
      throw new ArgumentException("prefixes"); 

     // Create a listener. 
     HttpListener listener = new HttpListener(); 

     // Add the prefixes. 
     foreach (string s in prefixes) 
     { 
      listener.Prefixes.Add(s); 
     } 

     listener.Start(); //THIS FAILS IN WINDOWS SERVICE AS LOCAL SYSTEM 

     //Console.WriteLine("Listening..."); 
     //// Note: The GetContext method blocks while waiting for a request. 
     //HttpListenerContext context = listener.GetContext(); 
     //HttpListenerRequest request = context.Request; 
     //// Obtain a response object. 
     //HttpListenerResponse response = context.Response; 
     //// Construct a response. 
     //string responseString = "<HTML><BODY> " + DateTime.Now + "</BODY></HTML>"; 
     //byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); 
     //// Get a response stream and write the response to it. 
     //response.ContentLength64 = buffer.Length; 
     //System.IO.Stream output = response.OutputStream; 
     //output.Write(buffer,0,buffer.Length); 
     //// You must close the output stream. 
     //output.Close(); 
     //listener.Stop(); 

     return true; 
    } 

} 

Relavent日誌的類(證明: 錯誤:

Application: Stout.Workers.Service.exe 
Framework Version: v4.0.30319 
Description: The process was terminated due to an unhandled exception. 
Exception Info: System.Net.HttpListenerException 
Stack: 
    at System.Net.HttpListener.Start() 
    at Stout.Workers.Service.Server.Listen() 
    at Stout.Workers.Service.Server.Start() 
    at System.Threading.ThreadHelper.ThreadStart_Context(System.Object) 
    at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
    at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
    at System.Threading.ThreadHelper.ThreadStart() 

錯誤:

Faulting application name: Stout.Workers.Service.exe, version: 0.0.0.0, time stamp: 0x50d0cd99 
Faulting module name: KERNELBASE.dll, version: 6.2.9200.16451, time stamp: 0x50988950 
Exception code: 0xe0434352 
Fault offset: 0x00014b32 
Faulting process id: 0x1e70 
Faulting application start time: 0x01cddd5bb3e8500b 
Faulting application path:  C:\Users\Chad\Dropbox\Personal\Projects\Stout\Stout\Workers\Service\bin\Debug\Stout.Workers.Service.exe 
Faulting module path: C:\Windows\SYSTEM32\KERNELBASE.dll 
Report Id: f1aa9986-494e-11e2-be9b-685d43b0551c 
Faulting package full name: 
Faulting package-relative application ID: 

信息:

Fault bucket , type 0 
Event Name: CLR20r3 
Response: Not available 
Cab Id: 0 

Problem signature: 
P1: stout.workers.service.exe 
P2: 0.0.0.0 
P3: 50d0cd99 
P4: System 
P5: 4.0.30319.18016 
P6: 505702c9 
P7: 206c 
P8: 5c 
P9: System.Net.HttpListenerException 
P10: 
+0

你可以嘗試添加一個try/catch並記錄你得到的完整錯誤(message + stacktrace)嗎?您可以在應用程序的開始處將事件處理程序添加到AppDomain.CurrentDomain.UnhandledException事件中,以便在退出應用程序之前嘗試捕獲並記錄錯誤。 這個問題可能是一個權限問題,因爲Windows服務似乎不像通過命令行執行的相同的useraccount下運行,但沒有確切的錯誤,我只是猜測 –

+0

你*記錄*是CLR終止你的服務,因爲未處理的異常。您如何使這些代碼在控制檯應用程序中工作是很難猜測的。不要忘記添加控制檯。Main方法中的ReadLine()方法使線程有足夠的時間以相同的方式崩潰你的應用程序。 –

+0

@BernhardKircher我猜這是一個權限問題,雖然我無法得到它的工作(或吐出更多有用的錯誤/堆棧跟蹤)。由於這只是我的一個小型個人項目,我已經放棄了通過窗口服務來做到這一點,並且正在使用一個很好的舊winform應用程序;) – chad

回答

1

我想你正試圖接受你的聽衆多個請求。 如果仔細閱讀代碼,您會發現您正在實例化無限數量的偵聽器,而不是創建單個偵聽器來處理多個調用。

您實際得到的異常是StackOverflowException(唯一的例外,無法通過try-catch塊獲得)無論您做什麼,應用程序都會中斷。

刪除您的while循環(只需調用Listen一次)並嘗試在Listen方法中使用以下方法。

HttpListener listener = new HttpListener(); 
//add your prefixes here 
listener.Start(); 
AsyncCallback processRequest = delegate(IAsyncResult result) 
{ 
    //set the listener to listen for next request 
    listener.BeginGetContext(processRequest, listener); 
    HttpListenerContext context = listener.EndGetContext(result); 
    //Your code to handle the request here 
} 

listener.BeginGetContext(processRequest, listener); 

這就造成你與單個HttpListener

希望這有助於

UPDATE尋找循環:如果取消對請求處理的代碼,你會注意到異常不會發生因爲在調用listener.GetContext()時會阻塞該線程,並且偵聽器會掛起,直到它收到請求並且Listen方法未返回。通過調用listener.Start(),它會立即返回,然後返回true,您將以非常快的速度循環創建許多聽衆。

您的代碼可能以這種方式工作,但效率不高,因爲您必須爲每個請求創建一個偵聽器。最好讓一個監聽器異步處理所有的請求,因爲如果你的一個請求需要10秒鐘來執行你的循環,那麼你將不會創建另一個監聽器,直到你響應請求的客戶端。