HttpWebRequest timeout in Windows service - c#

I am getting a timeout error while starting my Windows service. I am tring to download an XML file from a remote system which causes a timeout during the service OnStart.
This is the method I am calling from OnStart:
public static StreamReader GetResponseStream()
{
try
{
EventLog.WriteEntry("Epo-Service_Retriver", "Trying ...",
EventLogEntryType.Information);
CookieContainer CC = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
Utils.GetWeeklyPublishedURL());
request.Proxy = null;
request.UseDefaultCredentials = true;
request.KeepAlive = true; //THIS DOES THE TRICK
request.ProtocolVersion = HttpVersion.Version10; // THIS DOES THE TRICK
request.CookieContainer = CC;
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
EventLog.WriteEntry("Epo-Service_Retriver", "Connected to Internet...",
EventLogEntryType.SuccessAudit);
return reader;
}
}
Is there any possibility to avoid this timeout?

You'll want to start a thread to do that work.
This is how I recall doing it in 1.1 (this is little more than pseudo code), something like this;
protected override void OnStart(string[] args)
{
Foo f = new Foo(args);
f.MethodThatNeverExits();
}
private void MethodThatNeverExits()
{
LongRunningInitialization();
while (true)
{
Thread.Sleep(pollingInterval);
DoSomeWork();
}
}
Would become;
private AutoResetEvent shutDownEvent;
private Thread thread;
protected override void OnStart(string[] args)
{
shutDownEvent = new AutoResetEvent(false);
Foo f = new Foo(args);
thread = new Thread(new ThreadStart(f.MethodThatNeverExits()));
thread.Start();
}
private void MethodThatNeverExits()
{
LongRunningInitialization();
while (!shutDownEvent.WaitOne(pollingInterval, false))
{
DoSomeWork();
}
}
protected override void OnStop()
{
shutDownEvent.Set();
thread.Join(timeToWait);
}

Related

WebClient DownloadFileAsync() does not work

WebClient DownloadFileAsync() does not work with the same URl and Credentials...
Any clue?
static void Main(string[] args)
{
try
{
var urlAddress = "http://mywebsite.com/msexceldoc.xlsx";
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("UserName", "Password");
// It works fine.
client.DownloadFile(urlAddress, #"D:\1.xlsx");
}
/*using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("UserName", "Password");
// It y creats file with 0 bytes. Dunow why is it.
client.DownloadFileAsync(new Uri(urlAddress), #"D:\1.xlsx");
//client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
}*/
}
catch (Exception ex)
{
}
}
You need to keep the program running while the async download completes, as it runs in another thread.
Try something like this, and wait for it to say completed before you hit enter to end the program:
static void Main(string[] args)
{
try
{
var urlAddress = "http://mywebsite.com/msexceldoc.xlsx";
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("UserName", "Password");
client.DownloadFileAsync(new Uri(urlAddress), #"D:\1.xlsx");
client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
}
catch (Exception ex)
{
}
Console.ReadLine();
}
public static void Completed(object o, AsyncCompletedEventArgs args)
{
Console.WriteLine("Completed");
}
Depending what kind of app you're using this in, the main thread needs to keep running while the background thread downloads the file.
By declaring Main function as async, you can also use DownloadFileTaskAsync with await.
public static async void Main(string[] args)
{
var urlAddress = "http://mywebsite.com/msexceldoc.xlsx";
var fileName = #"D:\1.xlsx";
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(new Uri(urlAddress), fileName);
}
}

Reading and saving post data

I have been assigned to take over someones position, however I do not really know C#. There is a server (192.268. something ect) that will post data to a site (unknown site, lets say bleh.com)
This is what the posting code snippet looks like:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
"https://server-ip-here/postlistener?filename=filename.zlib");
req.UseNagleAlgorithm = true;
req.AllowWriteStreamBuffering = true;
req.Method = "POST";
req.Accept = "application/xml";
req.ServicePoint.Expect100Continue = false;
System.Net.ServicePointManager.CheckCertificateRevocationList = false;
req.Proxy = new WebProxy();
filename = "filename.dat";
byte[] postData = File.ReadAllBytes(filename);
Stream stream = req.GetRequestStream();
stream.Write(postData, 0, postData.Length);
stream.Flush();
stream.Close();
req.BeginGetResponse(new AsyncCallback(responseHandler), this);
Which I beleive I get the post request in this form
www.blah.com/upload?filename=file_1234_12389126495129847980.zlib
I am unsure how to listen for post requests and then get the data from them and save them as a file.
Currently I have tried this:
private void Form1_Load(object sender, EventArgs e)
{
listener = new HttpListener();
// listener.Prefixes.Add("http://localhost:8000/");
listener.Prefixes.Add("http://127.0.0.1:8000/");
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Start();
listenThread1 = new Thread(new ParameterizedThreadStart(startlistener));
listenThread1.Start();
}
private void startlistener(object s)
{
while (true)
{
// blocks until a client has connected to the server
ProcessRequest();
}
}
private void ProcessRequest()
{
var result = listener.BeginGetContext(ListenerCallback, listener);
result.AsyncWaitHandle.WaitOne();
}
private void ListenerCallback(IAsyncResult result)
{
var context = listener.EndGetContext(result);
Thread.Sleep(1000);
var data_text = new StreamReader(
context.Request.InputStream,
context.Request.ContentEncoding).ReadToEnd();
var cleaned_data = System.Web.HttpUtility.UrlDecode(data_text);
context.Response.StatusCode = 200;
context.Response.StatusDescription = "OK";
MessageBox.Show(cleaned_data);
context.Response.Close();
}
Which listens on the local host (Would sub local host for the website once we establish what it will be).
Not sure how to grab the post though, right now I can only listen for it. Ideally I would only like to accept posts from a specific IP address also.
Any ideas how I can go about grabbing the post data (which will be binary) and saving it as a file?

98% usage of CPU - simple C# service

I wrote a simple application in C#. It downloads a log file via ftp, checked whether firefox is running on the PC, changes the log string, uploads the log back to server.
I am running it every 10 seconds using a Timer.
When the service starts, its memory usage is 10Mb and CPU usage <1%. After about two minutes, its memory usage is ~12Mb, but the CPU usage jumps to over 90%!
This is what my app does every 10 seconds:
1) Download log via ftp and store in string log.
2) Go through a list of processes running on the PC, and if there if a firefox.exe process, appropriately change the log string to indicate firefox running.
3) Save the log string to as a txt file, read the file to send id via ftp back to the server.
I doubt saving/reading a couple of lines of text onto hard-drive requires so much CPU power.
Any guesses on what might be going on? Thanks!!
EDIT: Here is my whole class
class Program : System.ServiceProcess.ServiceBase
{
private static System.Timers.Timer timer;
static string myIP = "";
static void start()
{
string strHostName = Dns.GetHostName();
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEntry.AddressList;
int i = 0;
foreach (IPAddress address in addr)
{
if (("" + addr[i].AddressFamily).Equals("InterNetwork"))
myIP = "" + addr[i];
i++;
}
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(firefoxChecker); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000) * (5);
timer.Enabled = true; // Enable the timer
timer.Start();
}
protected override void OnStart(string[] args)
{
start();
}
public static void Main()
{
System.ServiceProcess.ServiceBase.Run(new Program());
}
static string downloadLog()
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://server/log.txt"));
// Provide the WebPermission Credintials
reqFTP.Credentials = new NetworkCredential("username", "password");
reqFTP.Proxy = null;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string log = reader.ReadToEnd();
reader.Close();
reader.Dispose();
return log;
}
static void sendLogThroughFTP(string log)
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://server/log.txt"));
reqFTP.Credentials = new NetworkCredential("username", "password");
reqFTP.Proxy = null;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
StreamWriter wr = new StreamWriter(#"C:\logs\temp.txt");
wr.Write(log);
wr.Close();
StreamReader sourceStream = new StreamReader(#"C:\logs\temp.txt");
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
reqFTP.ContentLength = fileContents.Length;
Stream requestStream = reqFTP.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
sourceStream.Dispose();
}
static void firefoxChecker(object sender, EventArgs e)
{
string firefoxOwner = "----------";
TerminalServicesManager manager = new TerminalServicesManager();
ITerminalServer server = null;
string log = downloadLog();
bool diceFirefoxRunning = false;
bool monsterFirefoxRunning = false;
bool careerbuilderFirefoxRunning = false;
try
{
server = manager.GetLocalServer();
server.Open();
foreach (ITerminalServicesSession session in server.GetSessions())
{
if (session.ConnectionState == ConnectionState.Active)
{
firefoxOwner = session.UserAccount.ToString();
string ip = session.ClientIPAddress.ToString();
string user = session.UserAccount.ToString();
System.Collections.Generic.IList<Cassia.ITerminalServicesProcess> list = session.GetProcesses();
foreach (ITerminalServicesProcess process in list)
{
if (Equals(process.ProcessName, "firefox.exe"))
{
// change firefoxOwner string appropriately
log = updateLog(log, user, firefoxOwner);
}
}
}
}
server.Close();
sendLogThroughFTP(log);
}
catch
{
// do nothing
}
}
static string updateLog(string log, string username, string ffOwner)
{
// make some changes to log string
return log;
}
}
}
Thanks for all the inputs!
Disable the timer when you start doing your work and re-enable it when you are done.
You are downloading and uploading via FTP which could take more than the 5 seconds you have set fro your timer. If you disable the timer before you start and re-enable it at the end, you will poll 5 seconds after the last upload completed.
You may also want to consider upping your polling time to something a little more reasonable. Do you really need to poll every 5 seconds to make sure firefox is still running?

Help threading HttpWebRquest in c#

Hi guys just wondering if somebody could help me try and correctly thread my application, I am constantly hitting an hurdle after another, I have never been to clued up on threading in applications. I have tryed following this http://www.developerfusion.com/code/4654/asynchronous-httpwebrequest/ tutorial.
basically I'm just trying to stop my request from hanging my application
public class Twitter
{
private const string _username = "****",
_password = "****";
private WebResponse webResp;
public string getTimeLine()
{
Thread thread = new Thread(new ThreadStart(TwitterRequestTimeLine));
thread.IsBackground = true;
thread.Start();
using (Stream responseStream = webResp.GetResponseStream())
{
//
using (StreamReader reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
}
private void TwitterRequestTimeLine()
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(aUrl);
SetRequestParams(request);
request.Credentials = new NetworkCredential(_username, _password);
//WebResponse tempResp = request.GetResponse();
ThreadState state = new ThreadState();
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(???), ???);
}
private static void SetRequestParams( HttpWebRequest request )
{
request.Timeout = 500000;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "AdverTwitment";
}
}
}
anyone help would be greatly appricated
You really don't need to thread HttpWebRequest.
When you use BeginGetResponse() and EndGetResponse() with HttpWebRequest, it already uses a background thread for you in order to work asynchronously. There is no reason to push this into a background thread.
As for usage: The help for HttpWebRequest.BeginGetResponse demonstrates a complete, asynchronous request.
If this is a WinForms app, the easiest way to keep the GUI responsive while executing the WebRequest is to use a BackgroundWorker component. Drop a BackgroundWorker on your form and call its RunWorkAsync() method. Put the code to execute the WebRequest and read the Response in the DoWork event handler.
Try using an AsyncCallback like Rubens suggested but have the callback call into a separate method to load the data to its destination. If the getTimeline method doesn't return immediately it will cause the application to hang, because the UI Thread is what is running the request itself.
If you use a separate AsyncCallback to be called after the request is done and have it load the data then the method will return immediately and your UI thread can do other things while it waits.
What about this:
private string getTimeLine()
{
string responseValue = "";
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
AutoResetEvent syncRequest = new AutoResetEvent(false);
WebRequest request = WebRequest.Create(aUrl);
request.Method = "POST";
request.BeginGetResponse(getResponseResult =>
{
HttpWebResponse response =
(HttpWebResponse)request.EndGetResponse(getResponseResult);
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
syncRequest.Set();
}, null);
syncRequest.WaitOne();
return responseValue;
}
EDIT: Ok, I tried to keep a method returning a string, that's why I used AutoResetEvent; If you use a BackgroundWorker, you'll get notified when your data is available:
BackgroundWorker worker = new BackgroundWorker();
string responseValue = "";
worker.RunWorkerCompleted += (sender, e) =>
{
// update interface using responseValue variable
};
worker.DoWork += (sender, e) =>
{
string aUrl = "http://168.143.162.116/statuses/home_timeline.xml";
WebRequest request = WebRequest.Create(aUrl);
// .. setup
using(StreamReader reader =
new StreamReader(request.GetResponse().GetResponseStream()))
responseValue = reader.ReadToEnd();
};
worker.RunWorkerAsync();

Windows Service restarts on Exception

I'm building a windows service that grabs information from a website periodically
How can I start looking again when a exception is caught? for example when internet goes down and up later.
Code:
public string cadena(string pagina)
{
try
{
String cadena;
WebRequest myWebRequest = WebRequest.Create(pagina);
myWebrequest = 10000;
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("ISO-8859-1");
StreamReader readStream = new StreamReader(ReceiveStream, encode);
cadena = readStream.ReadToEnd();
readStream.Close();
myWebResponse.Close();
return cadena;
}
catch (WebException error)
{
myTimer.Enabled = true;
return "error";
}
}
public void inicia(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
String strSite = cadena("www.something.com");
//Do something with strSite...
myTimer.Enabled = true;
}
protected override void OnStart(string[] args)
{
myTimer = new System.Timers.Timer();
myTimer.Interval = 1500;
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(inicia);
myTimer.Enabled = true;
}
Here is a very crude example to get you started, this will keep your program from continuing until you get a valid response. There are better ways of doing this, but this is the idea you want. Good luck!
myWebResponse = myWebRequest.GetResponse();
while (myWebResponse.ContentLength == -1) {
//sleep
myWebResponse = myWebRequest.GetResponse();
}
//continue execution
You should probably put in a check to see if the remote site is available, and either poll until it is, or interrupt when the service is available. This way you won't have to recover from a thrown exception.
I think using exceptions should be reserved for things a little more catastrophic to your application.

Categories