我正在嘗試做幫助Windows服務/計劃任務必須使用一個網絡瀏覽器和文件對話框
我試圖創建任何類型的解決方案,將在夜間運行Windows服務器,對網站進行身份驗證,在網站上檢查網頁上的新鏈接,以指示新版本的zip文件,使用新鏈接(如果存在)下載壓縮文件,將下載的文件解壓縮到服務器,使用解壓後的內容(sql腳本等)構建數據庫實例,並記錄發生在文本文件中的所有內容。
窗體應用程序:那八九不離十工程
我創建一個Windows的部分形成,它使用一對夫婦的WebBrowser控件,一對夫婦線程,和幾個定時器做一切,除了夜間運行的應用程序。當我登錄並運行它時,它非常適合作爲表單使用,但我需要將它(或類似的東西)作爲一個服務或計劃任務運行。
我的服務嘗試
所以,我創建了一個Windows服務蜱每一個小時,如果System.DateTime.Now.Hour> = 22,嘗試啓動Windows窗體應用做的事情。當服務嘗試啓動窗體時,會發生此錯誤:
無法實例化ActiveX控件'8856f961-340a-11d0-a96b-00c04fd705a2',因爲當前線程不在單線程單元中。
,我研究並試圖通過放置該[STAThread]屬性上服務的程序類的主要方法還是使用像這樣的代碼在一些地方,包括窗體構造函數來解決:
webBrowseThread = new Thread(new ThreadStart(InitializeComponent));
webBrowseThread.SetApartmentState(ApartmentState.STA);
webBrowseThread.Start();
我無法得到任何一種工作方法。在後一種方法中,表單上的控件(將在IntializeComponent中初始化)不會被初始化,而是我得到空引用異常。
我的任務計劃嘗試
所以,我試圖用我自己的憑據到我的開發機器上本地運行的形式創造一個夜間計劃任務(只是測試)。它比服務得到的更遠,但掛在文件下載對話框中。
相關注意事項:要發送鍵序列通過文件下載來獲取和文件另存爲對話框,我的表實際運行一對夫婦使用WScript.Shell.SendKeys的VBScript文件。好吧,這是尷尬承認,但我嘗試了一些不同的東西,包括Win32 API中的SendMessage和引用IWshRuntimeLibrary在我的C#代碼中使用SendKeys。當我研究如何通過對話框時,Win32 API似乎是推薦的方法,但我無法弄清楚。 vbscript文件是我能工作的唯一東西,但我現在擔心這可能是計劃任務無法工作的原因。
關於我的WebBrowser控件的選擇
我已閱讀有關System.WebClient類來替代WebBrowser控件,而且一目瞭然,它看起來並不像它有什麼,我需要完成這件事。例如,我需要(或者我認爲我需要)WebBrowser的DocumentCompleted和FileDownload事件來處理頁面加載,文件下載等方面的延遲。WebClient還有更多我沒有看到的事情嗎?除了WebBrowser以外,是否還有另外一個更友好的服務並且可以做到這一點?
總結
吉茲,這是長。抱歉!這將有助於甚至有一個更好的方式來做我想做的事情的高層次的建議,因爲我嘗試過的東西都沒有奏效。
更新09年10月22日
嗯,我想我更近,但我再次卡住。我最終會得到一個體面大小的zip文件,其中包含幾個文件,但由我的代碼生成的zip文件是空的。這是我的代碼:
// build post request
string targetHref = "http://wwwcf.nlm.nih.gov/umlslicense/kss/login.cfm";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetHref);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// encoding to use
Encoding enc = Encoding.GetEncoding(1252);
// build post string containing authentication information and add to post request
string poststring = "returnUrl=" + fixCharacters(targetDownloadFileUrl);
poststring += getUsernameAndPasswordString();
poststring += "&login2.x=0&login2.y=0";
// convert to required byte array
byte[] postBytes = enc.GetBytes(poststring);
request.ContentLength = postBytes.Length;
// write post to request
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Close();
// get response as stream
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
// writes stream to zip file
FileStream writeStream = new FileStream(fullZipFileName, FileMode.Create, FileAccess.Write);
ReadWriteStream(responseStream, writeStream);
response.Close();
responseStream.Close();
ReadWriteStream的代碼如下所示。
private void ReadWriteStream(Stream readStream, Stream writeStream)
{
// taken verbatum from http://www.developerfusion.com/code/4669/save-a-stream-to-a-file/
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
後字符串的建設是從我以前的形式的應用程序,採取的工作。我比較了兩組代碼(我的工作表單應用程序和這一個)的poststring中的結果值,它們是相同的。
我甚至不確定如何排除故障。任何人都可以看到明顯的原因,爲什麼這不起作用?
結論09年10月23日
我終於有了這個工作。我必須克服一些重要的障礙。我在線上的ReadWriteStream方法代碼遇到了一些問題。我不知道爲什麼,但它不適合我。在克勞迪奧Lassala的Virtual Brown Bag meeting叫JB一個傢伙幫我想出這個代碼,我的目的,工作要好得多:
private void WriteResponseStreamToFile(Stream responseStreamToRead, string zipFileFullName)
{
// responseStreamToRead will contain a zip file, write it to a file in
// the target location at zipFileFullName
FileStream fileStreamToWrite = new FileStream(zipFileFullName, FileMode.Create);
int readByte = responseStreamToRead.ReadByte();
while (readByte != -1)
{
fileStreamToWrite.WriteByte((byte)readByte);
readByte = responseStreamToRead.ReadByte();
}
fileStreamToWrite.Flush();
fileStreamToWrite.Close();
}
將在下面的建議,我確實有與認證的麻煩。下面的代碼是解決這個問題的方法。插入的幾條意見解決了我遇到的關鍵問題。
string targetHref = "http://wwwcf.nlm.nih.gov/umlslicense/kss/login.cfm";
HttpWebRequest firstRequest = (HttpWebRequest)WebRequest.Create(targetHref);
firstRequest.AllowAutoRedirect = false; // this is critical, without this, NLM redirects and the whole thing breaks
// firstRequest.Proxy = new WebProxy("127.0.0.1", 8888); // not needed for production, but this helped in order to debug the http traffic using Fiddler
firstRequest.Method = "POST";
firstRequest.ContentType = "application/x-www-form-urlencoded";
// build post string containing authentication information and add to post request
StringBuilder poststring = new StringBuilder("returnUrl=" + fixCharacters(targetDownloadFileUrl));
poststring.Append(getUsernameAndPasswordString());
poststring.Append("&login2.x=0&login2.y=0");
// convert to required byte array
byte[] postBytes = Encoding.UTF8.GetBytes(poststring.ToString());
firstRequest.ContentLength = postBytes.Length;
// write post to request
Stream postStream = firstRequest.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length); // Fiddler shows that post and response happen on this line
postStream.Close();
// get response as stream
HttpWebResponse firstResponse = (HttpWebResponse)firstRequest.GetResponse();
// create new request for new location and cookies
HttpWebRequest secondRequest = (HttpWebRequest)WebRequest.Create(firstResponse.GetResponseHeader("location"));
secondRequest.AllowAutoRedirect = false;
secondRequest.Headers.Add(HttpRequestHeader.Cookie, firstResponse.GetResponseHeader("Set-Cookie"));
// get response to second request
HttpWebResponse secondResponse = (HttpWebResponse)secondRequest.GetResponse();
// write stream to zip file
Stream responseStreamToRead = secondResponse.GetResponseStream();
WriteResponseStreamToFile(responseStreamToRead, fullZipFileName);
responseStreamToRead.Close();
sl.logScriptActivity("Downloading update.");
firstResponse.Close();
我想強調的是,AllowAutoRedirect設置爲false,第一個HttpWebRequest的實例是整個事情的關鍵工作。當沒有設置時,提琴手顯示了兩個額外的請求,並且破壞了腳本的其餘部分。
代碼看起來不錯。我會抓住一小撮Fiddler http://www.fiddlertool.com/並觀看您的要求。如果這不起作用,我會創建一個小型的網絡應用程序並與之對抗,以便我可以看到兩端發生了什麼。 – Will 2009-10-22 17:48:41
另一個想法 - 您的請求可能會遇到登錄和退出問題。同樣,通過查看請求可以讓您比較從瀏覽器和代碼中進行此操作。我懷疑您需要登錄,獲取您的身份驗證cookie,並在嘗試下載zip文件時將該cookie發回。從小提琴手開始,比較你的要求。 – Will 2009-10-22 17:51:48
太棒了。感謝您更新您的問題,並提供有關這些內容的詳細信息。我可能會回來偷你的一些代碼... – Will 2009-10-23 20:35:10