Console exe is not exiting some times? - c#

I have a very simple console exe application. This application will be executed by Windows Server R2 Task Scheduler after every 15 minutes. This was working fine for a long period of time but since last 2 days the application is not exiting some times. The problem is that Task Scheduler will never run the application again unless the previous started application exit. Here is my application code,
static void Main(string[] args)
{
MyService.Process();
}
internal static void Process()
{
try
{
Logger.Log("Starting Service");
// Synchronous Work
Logger.Log("Ending Service");
}
catch (Exception ex)
{
Logger.Log("Unknown error occured: " + ex.Message);
}
}
When I check the log file I am seeing these lines at the end of file,
Starting Service
--------------------------
Ending Service
The Task Scheduler in Windows Server 2008 R2 showing me memory = 480), CPU = 0 and Threads = 1. What can be the possible cause that forbid the exe to exit. Also, note that it only happens some times. My application creates, moves, delete some files/directories using File and Directory class and send some data to server using WebClient.UploadValues

Related

Application does not exit when an error happening on systemd

So I developed an application using .net-core, I run this software on a linux machine as a daemon service using systemd. Now the problem is that when an error happen in the app, it enters in a "limbo", infact each activity of the application is logged using Console.WriteLine and I can see this log typing that command on linux machine: journalctl -fu app.service.
When the error happen the log doesn't write anything, but at the same time the application keep running and this is really strange because I setup the service with the following configuration:
[Unit]
Description = Daemon service
[Service]
ExecStart = /usr/bin/dotnet /home/my username/Desktop/publish/SimpleApp.dll
WorkingDirectory= /home/foo/Desktop/publish
Restart = always
RestartSec = 3
[Install]
WantedBy = multi-user.target
as you can see the Restart = always should restart the app when an error is raised. When an exception is raised the method Error() write the error inside a file and then kill the software in the following way:
public void Error(Exception ex)
{
File.WriteAllText("error.txt", ex.ToString());
Environment.Exit(1);
}
Must be some problem on Environment.Exit with the Linux environment, or I did something wrong calling Environment.Exit. There are other ways to close an application like this which run as system service?
Thanks
Try the following:
public void Error(Exception ex)
{
File.WriteAllText("error.txt", ex.ToString());
throw new Exception ("This is a test to see if restart is working");
}

Windows service unexpected termination logging

I want my Windows Service to log (log4net) error if the service terminates unexpectedly, i.e crashes due to any reason. I terminated the service from Windows Task Manager, checked Event Viewer i.e.
Windows logs -> System
and found error was 7034.
Update:
Here is what I tried, I used EventLog class for writing entry in Application log, which was successful. Although I want an entry to be written in case windows service crashes or terminates unexpectedly.
static int Main(string[] args)
{
try
{
// Do something here
}
catch (Exception ex)
{
if (!EventLog.SourceExists("ApplicationName"))
EventLog.CreateEventSource("ApplicationName", "WindowsService");
EventLog.WriteEntry("ApplicationName", ex.Message);
}
return -1;
}
But it didn't log anything upon crash, where should I write entry in EventLog so that it can log upon crash?

How to start an exe from a .NET Windows Service for updating the service

I have a windows service that I would like to be automatically and silently updated. I started using wyBuild to implement this, but have had some issues with it, and decided to try to build my own. I've written a standalone exe that can be called to do the update procedure: checks for a new zip file with the update, downloads it, unzips, stop the windows service, copy files from the zip, then restart the service. This exe works fine when I run it from the commandline and wasn't really difficult to write.
However, now I would like the service (the same one being updated) to shell out to the updater exe to update itself. I first tried Process.Start:
var proc = Process.Start(pathToUpdaterExe);
proc.WaitForExit(60000);
This called the updater, but when the updater stops the service, the process is killed and the update stops. I did some searching and it sounds like the solution is to use a separate AppDomain. This is what I have now:
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence objEvidence = new System.Security.Policy.Evidence(baseEvidence);
AppDomainSetup setup = new AppDomainSetup();
var updateDomain = AppDomain.CreateDomain("updateDomain", objEvidence, setup);
updateDomain.ExecuteAssembly(updater);
AppDomain.Unload(updateDomain);
However, now I get the error System.IO.IOException: "The process cannot access the file 'C:\Program Files (x86)\Company\Service\Service.dll' because it is being used by another process" when attempting to copy over the new Service.dll
Again, I've stopped the service at this point. I've confirmed this with logging. I can't imagine what would have Service.dll still locked, so I added code to check to see what is locking it:
public static IEnumerable<Process> GetProcessesLocking(string filePath)
{
var result = new List<Process>();
result.Clear();
var processes = Process.GetProcesses();
foreach (Process proc in processes)
{
try
{
if (proc.HasExited) continue;
foreach (ProcessModule module in proc.Modules)
{
if ((module.FileName.ToLower().CompareTo(filePath.ToLower()) == 0))
{
result.Add(proc);
break;
}
}
}
catch (Exception ex)
{
Log(ex.ToString());
Log("There was an error checking " + proc.ProcessName );
}
}
return result;
}
However this code indicates that nothing has a lock on the dll (result is empty and nothing is logged indicating an error).
I suspect I'm running afoul of some UAC issue that is the real cause of the IOException. The windows service runs as LocalSystem. All that to ask: How should I be running the update exe from the windows service such that it has rights to copy files in c:\Program Files?
Update
As the comments and answer suggest, Process.Start can work, but there is some nuance. You have to start cmd.exe and use it to start the updater. I also found I could not use a full path for the updater exe and that I needed to set UseShellExecute=false. This is my final working code that launches the updater from the .NET service:
var cmd = "/c start updater.exe";
var startInfo = new ProcessStartInfo("cmd.exe");
startInfo.Arguments = cmd;
startInfo.WorkingDirectory = AssemblyDirectory;
startInfo.UseShellExecute = false;
var proc = Process.Start(startInfo);
I did this exact thing - using a simpler (some might say kludgy) approach. The service:
Produces a batch command,
Downloads the new executables to a staging location,
Starts a process: cmd.exe which, in turn, runs the batch script w/o waiting for it to complete, and then
Immediately terminates itself.
The batch command:
Pings 127.0.0.1 five times,
Copies the executables to the final location and,
Restarts the service.
Works like clockwork. The ping is a reliable 5 second delay - lets the service shutdown before copying the files.
Edit:
Just for completeness - I realized that by batch cmd is pinging 127.0.0.1 not 128.0.0.1 and so I edited this answer to reflect that. I suppose either works - but 128.0.0.1 pings timeout, where 127.0.0.1 resolves to "me". Since I'm only using it as a poor-man's delay, it serves the purpose either way.

Launching a stored-procedure with Task.Factory.StartNew

I am trying to develop a web service which calls a stored procedure. This stored procedure is quite long (around 1h30), and it does numerous "count" and "insert" in a database.
To launch this procedure I used a C# Class task ; here is the example :
[HttpPost]
[Route("updateData/{date:datetime?}")]
public JsonResult UpdateData(DateTime? date) {
try {
Task.Factory.StartNew(() => Data.UpdateData(date), TaskCreationOptions.LongRunning);
return Json("UpdateData successfully started !");
}
catch (Exception e) {
return Json("Error UpdateData: " + e);
}
}
When I test in local environment it works ; but when I work on Azure the process stops after roughly 30 minutes.
For launching the web service I use the Microsoft Azure scheduler.
The problem does not seem to be the stored procedure, but it seems to be in the use of the task (because without the task it works).
Is there something special to do ?
What you're experiencing is an IIS timeout. Once IIS detects inactivity, it will terminate the app pool:
Otherwise, when you have 20 minutes without any traffic then the app pool will terminate so that it can start up again on the next visit.
This happens because Task.Factory.StartNew doesn't register work with IIS, hence it doesn't know that you currently have active work going on.
To avoid this, If you're using .NET 4.5.2, you can use HostingEnvironment.QueueBackgroundWorkItem to register and queue work on a ASP.NET Threadpool thread.
If you're on previous versions, you can use BackgroundTaskManager by Stephan Cleary.
For more, read this post by the .NET Web Development team

C# Service calls Console Application that doesn't close

What I have is a windows Service calling a console application that i'm running. However, when the service run it again, the console app doesn't close. is it best to have the app close itself when it's done running or have the service close it? In either cause can you give an example on how to close it?
while (true)
{
try
{
string ectory = #"C:\Program Files\Checker.exe";
EventLog.WriteEntry("PriceGrab", "Calling executeable");
var p = Process.Start(ectory);
if (!p.WaitForExit(30000))
{
p.Kill();
}
System.Threading.Thread.Sleep(600000); // wait 10 minutes
}
catch (Exception ex)
{
EventLog.WriteEntry("PriceGrabCall", ex.Message, EventLogEntryType.Warning);
}
This is what I have inside of my Service executable. This will not close the app. The app is designed to run once every 10 minutes. N/M works now...
It depends on the nature of the console app. If it's like a server app and it won't quit (has an infinite loop...), then you just start it once and only kill it when you don't need it anymore (or just leave it running...). If it's supposed to exit, you can give it some time to close itself, and then kill it if it didn't finish:
var p = Process.Start( ... );
// ...
if (!p.WaitForExit(5000)) { // wait 5 seconds
p.Kill();
}
But be careful when killing processes like this. You might lose the work that they were doing.
Just a suggestion that may be more robust: I've done something similar in the past and have used a solution where the console app is scheduled via Windows Task Scheduler every 5 mins or so and the service checks for new files created by the console app using a file system watcher.

Categories