How to restart a windows service on failure? - c#

I came across this question, which looked like it would resolve what I'm trying to do, and I'm trying to use similar code where a Process() object is created and the "sc" command is called from code.
static void SetRecoveryOptions(string serviceName)
{
int exitCode;
using (var process = new Process())
{
var startInfo = process.StartInfo;
startInfo.FileName = "sc";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
// tell Windows that the service should restart if it fails
startInfo.Arguments = string.Format("failure \"{0}\" reset= 0 actions= restart/60000", serviceName);
process.Start();
process.WaitForExit();
exitCode = process.ExitCode;
}
if (exitCode != 0)
throw new InvalidOperationException();
}
I've tried calling that code from a few locations (such as the committed event handler for the service installer, OnStart of the service itself, etc) but every time I get an exception as soon as the Process() object is created. The exception is: "operation is not allowed due to the current state of the object".
Any ideas what I'm missing here?

Related

What is the difference between the below processes?

This process is running "independently" from my app. I can use my form meanwhile the script is running, not waiting for exit.
string strCmdText = "some command line script";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
This one though stops the process in my form till command line window is being closed:
Process p = new Process();
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = cmd.exe;
p.Start();
To me both seems to be the same process.start(). So what is the difference?
They are very similar but not equivalent.
Here is how Process.Start method implemented;
public static Process Start(string fileName, string arguments)
{
return Start(new ProcessStartInfo(fileName, arguments));
}
new ProcessStartInfo(fileName, arguments) constructor sets second parameter to arguments string which is ProcessStartInfo.Arguments property not Verb property. And also;
public static Process Start(ProcessStartInfo startInfo)
{
Process process = new Process();
if (startInfo == null) throw new ArgumentNullException("startInfo");
process.StartInfo = startInfo;
if (process.Start()) {
return process;
}
return null;
}
As you can see from it's documentation;
The overload associates the resource with a new Process component. If
the process is already running, no additional process is started.
Instead, the existing process resource is reused and no new Process
component is created. In such a case, instead of returning a new
Process component, Start returns null to the calling procedure.

Running process from hidden window

I have faced a strange problem when trying to run a process from hidden window - the process I run runs in hidden like my process, Am I doing something wrong? I want to run that child process not hidden.
Process.Start(Path.GetTempPath() + "cleanup.exe", Path.GetDirectoryName(Application.StartupPath);
you can try with creating an object of Process class as below :
Process objProcess = new Process();
objProcess.StartInfo.UseShellExecute = false;
objProcess.StartInfo.RedirectStandardOutput = true;
objProcess.StartInfo.CreateNoWindow = true;
objProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
// Passing the batch file/exe name
objProcess.StartInfo.FileName = string.Format(strBatchFileName);
// Passing the argument
objProcess.StartInfo.Arguments = string.Format(strArgument);
try
{
objProcess.Start();
}
catch
{
throw new Exception("Batch file is not found for processing");
}

How to resync time using w32tm in C# code?

Please give me a working code for achieving the time synchronization using w32tm.exe in C#.net. I already tried. Code shown below.
System.Diagnostics.Process p;
string output;
p = new System.Diagnostics.Process();
p.StartInfo = procStartInfo;
p.StartInfo.FileName = "w32tm";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Arguments = " /resync /computer:xxxxx977";
p.Start();
p.WaitForExit();
output = p.StandardOutput.ReadLine().ToString();
MessageBox.Show(output);
But i am getting the following error
The specified module could not be found. (0x8007007E).
and my requirement also wants to redirect the standardoutput for the success message.
you can try following C# code to enable date time sync from NTP server.
by the way i guess which is /resync command number so that i wouldn't have to launch that dirty external process
/// <summary>Synchronizes the date time to ntp server using w32time service</summary>
/// <returns><c>true</c> if [command succeed]; otherwise, <c>false</c>.</returns>
public static bool SyncDateTime()
{
try
{
ServiceController serviceController = new ServiceController("w32time");
if (serviceController.Status != ServiceControllerStatus.Running)
{
serviceController.Start();
}
Logger.TraceInformation("w32time service is running");
Process processTime = new Process();
processTime.StartInfo.FileName = "w32tm";
processTime.StartInfo.Arguments = "/resync";
processTime.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
processTime.Start();
processTime.WaitForExit();
Logger.TraceInformation("w32time service has sync local dateTime from NTP server");
return true;
}
catch (Exception exception)
{
Logger.LogError("unable to sync date time from NTP server", exception);
return false;
}
}
detailled explanation :
windows have a service, called w32time, which can sync time on your computer, first i check that the service is running, using ServiceController class, then, because i don't know which is the resync command number so that i can use ServiceController launch command method, i use a ProcessStart to launch a dos command on that services : w32tm /resync
The error is occurring when the .Net runtime JITs the method you're about to step into, because it couldn't find one of the types used by the method.
What exactly does the method that you can't step into do, and what types / methods does it use?
Refer this Link
So check whether any item you tried to load is in the folder or not.

Getting the friendly name for a Process after starting it

I'm coding a watchdog service for an embedded system that monitors some proprietary processes and restarts them if necessary. (Nothing to do with malware, before you ask. It's just a business requirement)
I need to retrieve the friendly name from a process I have just created, so that later I can retrieve that process using that name in order to monitor its health.
My problem is as follows:
If I try to read Process.ProcessName right after Process.Start(), I get an InvalidOperationException because it the process has not been fully created yet.
The same happens if I use Process.WaitForInputIdle(), but since this requires a message pump and many executables could be UI-less launchers for the actual application, this might not be an option.
I need to get the friendly name right after creating the process, before doing anything else.
Here's a code snippet:
var startInfo = new ProcessStartInfo { FileName = "notepad.exe" };
var process = new Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForInputIdle();
var friendlyName = process.ProcessName;
This will throw an InvalidOperationException on the last line if the process being started is Firefox, for example.
So how would I do this? Is there a safer method?
EDIT: Added a code snippet for clarification.
EDIT2: Rephrased the whole question for clarification, left irrelevant stuff out.
Ok, so after a lot of research I had to resort to a somewhat hacky solution.
According to the Process.GetProcessesByName() documentation, "The process name is a friendly name for the process, such as Outlook, that does not include the .exe extension or the path.".
Considering this, I worked around the problem using this code:
var startInfo = new ProcessStartInfo { FileName = "notepad.exe" };
var process = new Process();
process.StartInfo = startInfo;
process.Start();
var friendlyName = Path.GetFileNameWithoutExtension(startInfo.FileName);
As I said, it still feels kinda hacky, but at least it got the job done and allowed me to move on.
Thanks for all your comments anyway!
You are missing some key things in your code and try something like this using NotePad.exe and you will see what I am talking about
var startInfo = new ProcessStartInfo { FileName = "notepad.exe" };
var process = new Process();
process.StartInfo = startInfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;
process.Start();
process.WaitForInputIdle();
// this line below will always be false because `process.ProcessName will be
//notepad and process.StartInfo.FileName = notepade.exe
if (process.ProcessName.Equals(process.StartInfo.FileName) == false)
{
var theConfiguredProcessName = process.ProcessName;
}
Another option you could do either of the next 2 things below
Process[] processName = Process.GetProcessesByName("blah.exe");
or check all processes running and check for your running process
Process[] processlist = Process.GetProcesses();
foreach(Process process in processlist)
{
Console.WriteLine("Process: {0} ID: {1}", process.ProcessName, process.Id);
}

Proccess info gives an error but a bat file does not

I try to start ilasm from C# using class ProcessInfo
string arguments = string.Format("\"{0}\" /exe /output:\"{1}\" /debug=IMPL", ilFullFileName, exeFileFullName);
ProcessStartInfo processStartInfo = new ProcessStartInfo(CILCompiler, arguments);
processStartInfo.UseShellExecute = false;
processStartInfo.CreateNoWindow = false;
processStartInfo.WorkingDirectory = #"c:\Windows\Microsoft.NET\Framework\v4.0.30319\";
using (Process process = Process.Start(processStartInfo))
{
process.WaitForExit();
}
the arguments are:
"path_to_il.il" /exe /output:"path_to_exe.exe" /debug=IMPL
and then it gives me the error:
The application was unable to start correctly (0xc0000007b). Click Ok to close the application.
The odd part of that is, when I do exactly the same actions manually using bat file
"c:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" "path_to_il.il" /exe /output:"path_to_exe.exe" /debug=IMPL
pause
it does work.
What did I miss?
I think you need to set the file name as well:
processStartInfo.FileName = "ilasm.exe";

Categories

Resources