Process,Kill() Not Working - c#

I'm trying to make a service, that every 1000milliseconds(1 Second) Kills any process with the name Skype. I'm 100% sure I have coded it all correctly, everything is working, logging etc. But killing the process is not.
private System.Timers.Timer _timer;
protected override void OnStart(string[] args)
{
try
{
_timer = new System.Timers.Timer(100);
_timer.Elapsed += _timer_Elapsed;
_timer.Enabled = true;
if (!EventLog.SourceExists("MYTESTSERVICE"))
EventLog.CreateEventSource("MYTESTSERVICE", "MYTESTSERVICE LOG");
//_timer.Start();
Process[] p = Process.GetProcessesByName("Skype");
foreach (Process proc in p)
{
proc.Kill();
proc.WaitForExit();
EventLog.WriteEntry("User Tried To Start Skype! Closed.", EventLogEntryType.Warning);
}
}
catch (Exception ex)
{
EventLog.WriteEntry(String.Format("WcfServiceHostTest \n Exception Message: {0}\nTrace: {1}", ex.Message, ex.StackTrace), EventLogEntryType.Error);
}
}
I am currently not using the timer, but instead testing it upon service startup. If Skype is running, the process is not killed. I even tried notepad, and it did not kill that either. I have done research on this, but have not found an answer.
Any help is appreciated!
- Seb

you can use the taskkill:
Process.Start(new ProcessStartInfo
{
FileName = "taskkill",
Arguments = $"/im skype.exe /f /t",
CreateNoWindow = true,
UseShellExecute = false
}).WaitForExit();

Related

Handling Memory Limit on a Process in C#

I have a main application calling another console application through Process component. I have set a memory limit on the console app using through custom implementation of Job Objects(Class name as 'Job' in the code)
Whenever the memory limit is crossed OutofMemory exception is thrown or KERNELBASE.DLL faulting happens. But I am unable to catch this exception in the main app or in the console app.
What is the way to handle this ?
Handling through Global exception in console app did not work.
Main Application has following code
private void startProcess()
{
try
{
Process proc = new Process();
proc.StartInfo.FileName = #"E:\App\console.exe";
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.ErrorDataReceived += Proc_ErrorDataReceived;
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
Job job = new Job(_maxmemory);//memory limit set for child process
job.AddProcess(proc.Id);//for the above console
proc.WaitForExit();//this is called on a thread.
}
catch (Exception ex)
{
}
}
Console app has following code
static void Main(string[] args)
{
System.AppDomain.CurrentDomain.UnhandledException += CatchUnhandledException;
}
static void CatchUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.Error.WriteLine(e.ExceptionObject.ToString());
}
How to handle this memory limit exception either in main app or console ?
Your main app code clearly will not catch that error. Process.Start() starts the other process asynchonously, so the method will end before the other process really does something. You'll have to call proc.WaitForExit() if you want to wait for the child process to terminate. After that, you can use the ExitCode property to find out whether your child process had an error. The value will be non-zero if your process died due to an exception.
Code such as this one in the child process should actually work:
static void Main(string[] args)
{
try
{
AllocateALotOfMemory();
}
catch (OutOfMemoryException e)
{
// Handle error
}
}

WPF programme not running correctly when run silently

I have written a small programme to perform a quick configuration on a client machine and it needs to be able to run with a GUI and silently from the command line. If I run it with the GUI then it works perfectly, if however I try to run it without then it just hangs.
I have traced the problem to this section of code:
string arg = "/C:\"setup.exe /qn ADD_OPINSIGHTS_WORKSPACE=1 OPINSIGHTS_WORKSPACE_ID=" + workSpaceID + " OPINSIGHTS_WORKSPACE_KEY=" + workSpaceKey + " AcceptEndUserLicenseAgreement=1\"";
log.Info(arg);
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "MMASetup-AMD64.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = arg;
try
{
log.Info("try entered");
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
log.Info("Install started");
exeProcess.WaitForExit(30000);
log.Info("Install exit code: " + (exeProcess.ExitCode).ToString());
return (exeProcess.ExitCode).ToString();
}
}
catch (Exception e)
{
log.Error("MMA install threw an error: ", e);
return e.Message;
}
This method is in a seperate class to the GUI and silent code and is run in exactly the same way yet only reaches "Install started" when run silently. I know that the exe does finish so I have tried using the code in this solution but had the same problem:
ProcessStartInfo hanging on "WaitForExit"? Why?
I had the same Problem.
I made a startup class:
public partial class Startup {
// WPF App
private App _app;
[STAThread]
public static void Main(string[] args) {
try {
//Do what you need
//Check the args
//Start your setup silent
//start the WPF App if need it
this._app = new App();
this._app.InitializeComponent();
this._app.Run();
} catch (Exception ex) {
//Logging ex
}
}
After that you must change your Application Startup Object to the Startup Class.
I was running all of my work asynchronously and because I was not loading the GUI thread Windows was treating the application like a console app. Whereas a GUI thread would call other asynchronous methods and wait for them to finish a console application calls the methods and then closes because it has nothing left to do. The solution was to explicitly make the main thread wait like this:
public static void Main(string[] args)
{
try
{
Install().Wait();
}
catch (Exception ex)
{
}
}
private static async Task Install()
{}

cant get process error output using process.ErrorDataReceived c#

I've built Form App that I use for some time , Now I want to Catch the StandardError of my process as well as its standartOutput
I've looked at answers in SO and MSDN and yet and cant get it right
My code :
public void RunProcess(string FileName, string Arguments,, bool IsPrintOutput = true)
{
process = new Process();
process.ErrorDataReceived += new DataReceivedEventHandler(OnDataReceivedEvent);
if (IsPrintOutput) process.OutputDataReceived += new DataReceivedEventHandler(OnDataReceivedEvent);
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = FileName;
process.StartInfo.Arguments = Arguments;
if (EventWhenExit)
{
process.EnableRaisingEvents = true;
process.Exited += new EventHandler(myprocess_Exited);
}
process.Start();
process.BeginOutputReadLine();
//run polling on stored logs to print them to screen
PollingService();
}
I've check it with Iperf and I see that when I run it with correct argument I get correct output
but when I just send it with out any argumnet I see that with cmd I get
C:\>iperf.exe
Usage: iperf [-s|-c host] [options]
Try `iperf --help' for more information.
And my App I get Nothing !
what am I missing here ?
Thanks
You can stop reading here ! If you want to see the details of inner method continue below :
private void OnDataReceivedEvent(object sender, DataReceivedEventArgs e)
{
string ProcessOutput = e.Data;
ProcessLog.Add(e.Data);
}
private void PollingService()
{
var T = new Thread (()=>
{
while (true /* ProcessRunning*/)
{
if (ProcessLogIndex < ProcessLog.Count)
{
lock (this)
{
var tempList = ProcessLog.GetRange(ProcessLogIndex, ProcessLog.Count - ProcessLogIndex);
ProcessLogIndex = ProcessLog.Count;
foreach (var ToSend in tempList)
{
onDataOutputFromProcess(this, ToSend, sProcessNameID.ToString());
}
}
}
Thread.Sleep(400);
}
});
T.IsBackground = true;
T.Start();
}
I don't see a call to BeginErrorReadLine() anywhere in the code you posted. If you don't call that method, then the Process class won't actually redirect the stderr to your event handler.
I believe the above is the issue, but if you are actually calling that somewhere (and just didn't show it), then it is worth considering that there are some strange console programs out there that don't actually used stderr (or stdout) for error output. Instead, they write directly to the console window or some other non-standard mechanism. In those cases, you won't be able to receive the error output by redirecting stderr.
You can identify those programs by redirecting their output at the command like with e.g. iperf.exe 2> foo.txt. The stderr file handle is 2, and so that syntax redirects that file handle to a file named foo.txt. If the file is empty and you see errors on the screen, then the program is one of those strange programs.
But really, I think you probably just forgot to call BeginErrorReadLine(). :)

Restart an application by itself

I want to build my application with the function to restart itself. I found on codeproject
ProcessStartInfo Info=new ProcessStartInfo();
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+
Application.ExecutablePath;
Info.WindowStyle=ProcessWindowStyle.Hidden;
Info.CreateNoWindow=true;
Info.FileName="cmd.exe";
Process.Start(Info);
Application.Exit();
This does not work at all...
And the other problem is, how to start it again like this?
Maybe there are also arguments to start applications.
Edit:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=31454&av=58703
I use similar code to the code you tried when restarting apps. I send a timed cmd command to restart the app for me like this:
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 2 && \"" + Application.ExecutablePath + "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Application.Exit();
The command is sent to the OS, the ping pauses the script for 2-3 seconds, by which time the application has exited from Application.Exit(), then the next command after the ping starts it again.
Note: The \" puts quotes around the path, incase it has spaces, which cmd can't process without quotes.
Hope this helps!
Why not use
Application.Restart();
??
More on Restart
Why not just the following?
Process.Start(Application.ExecutablePath);
Application.Exit();
If you want to be sure the app does not run twice either use Environment.Exit(-1) which kills the process instantaneously (not really the nice way) or something like starting a second app, which checks for the process of the main app and starts it again as soon as the process is gone.
You have the initial application A, you want to restart.
So, When you want to kill A, a little application B is started, B kill A, then B start A, and kill B.
To start a process:
Process.Start("A.exe");
To kill a process, is something like this
Process[] procs = Process.GetProcessesByName("B");
foreach (Process proc in procs)
proc.Kill();
A lot of people are suggesting to use Application.Restart. In reality, this function rarely performs as expected. I have never had it shut down the application I am calling it from. I have always had to close the application through other methods such as closing the main form.
You have two ways of handling this. You either have an external program that closes the calling process and starts a new one,
or,
you have the start of your new software kill other instances of same application if an argument is passed as restart.
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
if (e.Args.Length > 0)
{
foreach (string arg in e.Args)
{
if (arg == "-restart")
{
// WaitForConnection.exe
foreach (Process p in Process.GetProcesses())
{
// In case we get Access Denied
try
{
if (p.MainModule.FileName.ToLower().EndsWith("yourapp.exe"))
{
p.Kill();
p.WaitForExit();
break;
}
}
catch
{ }
}
}
}
}
}
catch
{
}
}
Winforms has the Application.Restart() method, which does just that. If you're using WPF, you can simply add a reference to System.Windows.Forms and call it.
Another way of doing this which feels a little cleaner than these solutions is to run a batch file which includes a specific delay to wait for the current application to terminate. This has the added benefit of preventing the two application instances from being open at the same time.
Example windows batch file ("restart.bat"):
sleep 5
start "" "C:\Dev\MyApplication.exe"
In the application, add this code:
// Launch the restart batch file
Process.Start(#"C:\Dev\restart.bat");
// Close the current application (for WPF case)
Application.Current.MainWindow.Close();
// Close the current application (for WinForms case)
Application.Exit();
My solution:
private static bool _exiting;
private static readonly object SynchObj = new object();
public static void ApplicationRestart(params string[] commandLine)
{
lock (SynchObj)
{
if (Assembly.GetEntryAssembly() == null)
{
throw new NotSupportedException("RestartNotSupported");
}
if (_exiting)
{
return;
}
_exiting = true;
if (Environment.OSVersion.Version.Major < 6)
{
return;
}
bool cancelExit = true;
try
{
List<Form> openForms = Application.OpenForms.OfType<Form>().ToList();
for (int i = openForms.Count - 1; i >= 0; i--)
{
Form f = openForms[i];
if (f.InvokeRequired)
{
f.Invoke(new MethodInvoker(() =>
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}));
}
else
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}
if (cancelExit) break;
}
if (cancelExit) return;
Process.Start(new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = Application.ExecutablePath,
Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty
});
Application.Exit();
}
finally
{
_exiting = false;
}
}
}
This worked for me:
Process.Start(Process.GetCurrentProcess().MainModule.FileName);
Application.Current.Shutdown();
Some of the other answers have neat things like waiting for a ping to give the initial application time to wind down, but if you just need something simple, this is nice.
For .Net application solution looks like this:
System.Web.HttpRuntime.UnloadAppDomain()
I used this to restart my web application after changing AppSettings in myconfig file.
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
configuration.AppSettings.Settings["SiteMode"].Value = model.SiteMode.ToString();
configuration.Save();

handle exit event of child process

I have a console application and in the Main method. I start a process like the code below, when process exists, the Exist event of the process is fired but it closed my console application too, I just want to start a process and then in exit event of that process start another process.
It is also wired that process output is reflecting in my main console application.
Process newCrawler = new Process();
newCrawler.StartInfo = new ProcessStartInfo();
newCrawler.StartInfo.FileName = configSection.CrawlerPath;
newCrawler.EnableRaisingEvents = true;
newCrawler.Exited += new EventHandler(newCrawler_Exited);
newCrawler.StartInfo.Arguments = "someArg";
newCrawler.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
newCrawler.StartInfo.UseShellExecute = false;
newCrawler.Start();
You have to call newCrawler.WaitForExit() in order to stay until the child process finish. Then you can use newCrawler.ExitCode to have the exit value.
Seems like the Process exit handling could have caused the application error. So the application could have terminated. Can you put a proper try..catch block and debugg to see what is going wrong. Or comment the
line
newCrawler.Exited += new EventHandler(newCrawler_Exited);
and see what happens.
Please try following code (This is from MSDN) , also don't forget to pass one argument (FileName)
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading;
using Microsoft.VisualBasic;
class PrintProcessClass
{
private Process myProcess = new Process();
private int elapsedTime;
private bool eventHandled;
// Print a file with any known extension.
public void PrintDoc(string fileName)
{
elapsedTime = 0;
eventHandled = false;
try
{
// Start a process to print a file and raise an event when done.
myProcess.StartInfo.FileName = fileName;
myProcess.StartInfo.Verb = "Print";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(myProcess_Exited);
myProcess.Start();
}
catch (Exception ex)
{
Console.WriteLine("An error occurred trying to print \"{0}\":" + "\n" + ex.Message, fileName);
return;
}
// Wait for Exited event, but not more than 30 seconds.
const int SLEEP_AMOUNT = 100;
while (!eventHandled)
{
elapsedTime += SLEEP_AMOUNT;
if (elapsedTime > 30000)
{
break;
}
Thread.Sleep(SLEEP_AMOUNT);
}
}
// Handle Exited event and display process information.
private void myProcess_Exited(object sender, System.EventArgs e)
{
eventHandled = true;
Console.WriteLine("Exit time: {0}\r\n" +
"Exit code: {1}\r\nElapsed time: {2}", myProcess.ExitTime, myProcess.ExitCode, elapsedTime);
}
public static void Main(string[] args)
{
// Verify that an argument has been entered.
if (args.Length <= 0)
{
Console.WriteLine("Enter a file name.");
return;
}
// Create the process and print the document.
PrintProcessClass myPrintProcess = new PrintProcessClass();
myPrintProcess.PrintDoc(args[0]);
}
}
One thing I noticed is, if you are not passing the filename as parameter, that will lead the process to crash, but still the application is intact (Since the exception is handled inside the process).
If you are not passing the filename the above code will crash beacuse the
myPrintProcess.PrintDoc(args[0]);
will throw exception from main process itself.
I tried to create an exceptin inside the Exit handler, at that time the application (main process) also crashed.
can you try commenting the code inside Exit handler?

Categories