How do I programmatically use the "using" keyword in C#? - c#

I have some System.Diagnotics.Processes to run. I'd like to call the close method on them automatically. Apparently the "using" keyword does this for me.
Is this the way to use the using keyword?
foreach(string command in S) // command is something like "c:\a.exe"
{
try
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
catch (Exception e)
{
// notify of process failure
}
}
I'd like to start multiple processes to run concurrently.

using(p = Process.Start(command))
This will compile, as the Process class implements IDisposable, however you actually want to call the Close method.
Logic would have it that the Dispose method would call Close for you, and by digging into the CLR using reflector, we can see that it does in fact do this for us. So far so good.
Again using reflector, I looked at what the Close method does - it releases the underlying native win32 process handle, and clears some member variables. This (releasing external resources) is exactly what the IDisposable pattern is supposed to do.
However I'm not sure if this is what you want to achieve here.
Releasing the underlying handles simply says to windows 'I am no longer interested in tracking this other process'. At no point does it actually cause the other process to quit, or cause your process to wait.
If you want to force them quit, you'll need to use the p.Kill() method on the processes - however be advised it is never a good idea to kill processes as they can't clean up after themselves, and may leave behind corrupt files, and so on.
If you want to wait for them to quit on their own, you could use p.WaitForExit() - however this will only work if you're waiting for one process at a time. If you want to wait for them all concurrently, it gets tricky.
Normally you'd use WaitHandle.WaitAll for this, but as there's no way to get a WaitHandle object out of a System.Diagnostics.Process, you can't do this (seriously, wtf were microsoft thinking?).
You could spin up a thread for each process, and call `WaitForExit in those threads, but this is also the wrong way to do it.
You instead have to use p/invoke to access the native win32 WaitForMultipleObjects function.
Here's a sample (which I've tested, and actually works)
[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
static extern uint WaitForMultipleObjects( uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds );
static void Main( string[] args )
{
var procs = new Process[] {
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'" ),
Process.Start( #"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'" ) };
// all started asynchronously in the background
var handles = procs.Select( p => p.Handle ).ToArray();
WaitForMultipleObjects( (uint)handles.Length, handles, true, uint.MaxValue ); // uint.maxvalue waits forever
}

For reference:
The using keyword for IDisposable objects:
using(Writer writer = new Writer())
{
writer.Write("Hello");
}
is just compiler syntax. What it compiles down to is:
Writer writer = null;
try
{
writer = new Writer();
writer.Write("Hello");
}
finally
{
if( writer != null)
{
((IDisposable)writer).Dispose();
}
}
using is a bit better since the compiler prevents you from reassigning the writer reference inside the using block.
The framework guidelines Section 9.3.1 p. 256 state:
CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.
In your code example, the outer try-catch is unnecessary (see above).
Using probably isn't doing what you want to here since Dispose() gets called as soon as p goes out of scope. This doesn't shut down the process (tested).
Processes are independent, so unless you call p.WaitForExit() they spin off and do their own thing completely independent of your program.
Counter-intuitively, for a Process, Close() only releases resources but leaves the program running. CloseMainWindow() can work for some processes, and Kill() will work to kill any process. Both CloseMainWindow() and Kill() can throw exceptions, so be careful if you're using them in a finally block.
To finish, here's some code that waits for processes to finish but doesn't kill off the processes when an exception occurs. I'm not saying it's better than Orion Edwards, just different.
List<System.Diagnostics.Process> processList = new List<System.Diagnostics.Process>();
try
{
foreach (string command in Commands)
{
processList.Add(System.Diagnostics.Process.Start(command));
}
// loop until all spawned processes Exit normally.
while (processList.Any())
{
System.Threading.Thread.Sleep(1000); // wait and see.
List<System.Diagnostics.Process> finished = (from o in processList
where o.HasExited
select o).ToList();
processList = processList.Except(finished).ToList();
foreach (var p in finished)
{
// could inspect exit code and exit time.
// note many properties are unavailable after process exits
p.Close();
}
}
}
catch (Exception ex)
{
// log the exception
throw;
}
finally
{
foreach (var p in processList)
{
if (p != null)
{
//if (!p.HasExited)
// processes will still be running
// but CloseMainWindow() or Kill() can throw exceptions
p.Dispose();
}
}
}
I didn't bother Kill()'ing off the processes because the code starts get even uglier. Read the msdn documentation for more information.

try
{
foreach(string command in S) // command is something like "c:\a.exe"
{
using(p = Process.Start(command))
{
// I literally put nothing in here.
}
}
}
catch (Exception e)
{
// notify of process failure
}
The reason it works is because when the exception happens, the variable p falls out of scope and thus it's Dispose method is called that closes the process is how that would go. Additionally, I would think you'd want to spin a thread off for each command rather than wait for an executable to finish before going on to the next one.

Related

C# Does Process.Dispose() also cleanup the StandardInput and StandardInput.BaseStream?

Currently working with a process I am starting up and then accessing the StandardInput.BaseStream and then copying a Stream to it. Do I need to Dispose of the StandardInput and/or the StandardInput.BaseStream at all or is that handled with Process.Dispose()?
Process someProgram = null;
try
{
someProgram = new Process();
someProgram.StartInfo.RedirectStandardInput = true;
someProgram.StartInfo.FileName = #"C:\Temp\SomeProgram.exe";
someProgram.Start();
streamParamater.CopyTo(someProgram.StandardInput.BaseStream);
someProgram.WaitForExit();
}
catch
{
// Error Logging
}
finally
{
if (someProgram != null)
{
someProgram.Dispose();
}
streamParamater.Dispose();
}
The readers / writers and their base streams are not disposed by calling Close() or Dispose() on the Process instance.
The Process.Close() method just sets the references to null so that they can be collected by GC once there are not other references left.
There is also this comment in the source code of Process.Close():
//Don't call close on the Readers and writers
//since they might be referenced by somebody else while the
//process is still alive but this method called.
So, you have to call Dispose() on the readers / writers if you want to make sure that the resources are freed as soon as possible.

Memory Mapped File gets deleted from memory

For some reason, when i read from a memory mapped file a couple of times it just gets randomly deleted from memory, i don't know what's going on. Is the kernel or GC deleting it from memory? If they are, how do i prevent them from doing so?
I am serializing an object to Json and writing it to memory.
I get an exception when trying to read again after a couple of times, i get FileNotFoundException: Unable to find the specified file.
private const String Protocol = #"Global\";
Code to write to memory mapped file:
public static Boolean WriteToMemoryFile<T>(List<T> data)
{
try
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null", "data");
}
var mapName = typeof(T).FullName.ToLower();
var mutexName = Protocol + typeof(T).FullName.ToLower();
var serializedData = JsonConvert.SerializeObject(data);
var capacity = serializedData.Length + 1;
var mmf = MemoryMappedFile.CreateOrOpen(mapName, capacity);
var isMutexCreated = false;
var mutex = new Mutex(true, mutexName, out isMutexCreated);
if (!isMutexCreated)
{
var isMutexOpen = false;
do
{
isMutexOpen = mutex.WaitOne();
}
while (!isMutexOpen);
var streamWriter = new StreamWriter(mmf.CreateViewStream());
streamWriter.WriteLine(serializedData);
streamWriter.Close();
mutex.ReleaseMutex();
}
else
{
var streamWriter = new StreamWriter(mmf.CreateViewStream());
streamWriter.WriteLine(serializedData);
streamWriter.Close();
mutex.ReleaseMutex();
}
return true;
}
catch (Exception ex)
{
return false;
}
}
Code to read from memory mapped file:
public static List<T> ReadFromMemoryFile<T>()
{
try
{
var mapName = typeof(T).FullName.ToLower();
var mutexName = Protocol + typeof(T).FullName.ToLower();
var mmf = MemoryMappedFile.OpenExisting(mapName);
var mutex = Mutex.OpenExisting(mutexName);
var isMutexOpen = false;
do
{
isMutexOpen = mutex.WaitOne();
}
while (!isMutexOpen);
var streamReader = new StreamReader(mmf.CreateViewStream());
var serializedData = streamReader.ReadLine();
streamReader.Close();
mutex.ReleaseMutex();
var data = JsonConvert.DeserializeObject<List<T>>(serializedData);
mmf.Dispose();
return data;
}
catch (Exception ex)
{
return default(List<T>);
}
}
The process that created the memory mapped file must keep a reference to it for as long as you want it to live. Using CreateOrOpen is a bit tricky for exactly this reason - you don't know whether disposing the memory mapped file is going to destroy it or not.
You can easily see this at work by adding an explicit mmf.Dispose() to your WriteToMemoryFile method - it will close the file completely. The Dispose method is called from the finalizer of the mmf instance some time after all the references to it drop out of scope.
Or, to make it even more obvious that GC is the culprit, you can try invoking GC explicitly:
WriteToMemoryFile("Hi");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
ReadFromMemoryFile().Dump(); // Nope, the value is lost now
Note that I changed your methods slightly to work with simple strings; you really want to produce the simplest possible code that reproduces the behaviour you observe. Even just having to get JsonConverter is an unnecessary complication, and might cause people to not even try running your code :)
And as a side note, you want to check for AbandonedMutexException when you're doing Mutex.WaitOne - it's not a failure, it means you took over the mutex. Most applications handle this wrong, leading to issues with deadlocks as well as mutex ownership and lifetime :) In other words, treat AbandonedMutexException as success. Oh, and it's good idea to put stuff like Mutex.ReleaseMutex in a finally clause, to make sure it actually happens, even if you get an exception. Thread or process dead doesn't matter (that will just cause one of the other contendants to get AbandonedMutexException), but if you just get an exception that you "handle" with your return false;, the mutex will not be released until you close all your applications and start again fresh :)
Clearly, the problem is that the MMF loose its context as explained by Luaan. But still nobody explains how to perform it:
The code 'Write to MMF file' must run on a separate async thread.
The code 'Read from MMF' will notify once read completed that the MMF had been read. The notification can be a flag in a file for example.
Therefore the async thread running the 'Write to MMF file' will run as long as the MMF file is read from the second part. We have therefore created the context within which the memory mapped file is valid.

C# Only part of a ReadProcessMemory or WriteProcessMemory request was completed during Process.Kill()

I have been researching this issue pretty extensively and cannot seem to find an answer.
I know that the Only part of a ReadProcessMemory or WriteProcessMemory request was completed exception is thrown when a 32-bit process tries to access a 64-bit process and the same for a 64-bit modifying a 32-bit process.
The solution to that issue is to change the Platform Target to 'Any CPU'. I have tried this and unfortunately this does not solve my issue.
The next block of code is what keeps throwing the exception. The program that runs this code is used to open up applications on remote computers and keeps a list of all the processes that the program itself opened so that I don't have to loop through all the processes.
Process processToRemove = null;
lock (_runningProcesses)
{
foreach (Process p in _runningProcesses)
{
foreach (ProcessModule module in p.Modules)
{
string[] strs = text.Split('\\');
if (module.ModuleName.Equals(strs[strs.Length - 1]))
{
processToRemove = p;
break;
}
}
if (processToRemove != null)
{
break;
}
}
if (processToRemove != null)
{
processToRemove.Kill();
_runningProcesses.Remove(processToRemove);
}
}
These processes can and most likely will be 32-bit and 64-bit, mixed together.
Is there anything I am doing that I shouldn't be doing, or is there just a better way to do all of this?
As detailed in the comments of the MSDN page for Process.Modules and this thread there is a known issue in Process.Modules when enumerating 32 bit processes from a 64 bit process and visa-versa:
Internally .NET's Process.Modules is using function EnumProcessModules
from PSAPI.dll. This function has a known issue that it cannot work
across 32/64 bit process boundary. Therefore enumerating another
64-bit process from 32-bit process or vice versa doesn't work
correctly.
The solution seems to be to use the EnumProcessModulesEx function, (which must be called via P/Invoke), however this function is only available on later versions of Windows.
We fixed this issue by adding
a new function called EnumProcessModulesEx to PSAPI.dll
(http://msdn2.microsoft.com/en-us/library/ms682633.aspx), but we
currently cannot use it in this case:
it only works on Windows Vista or Windows Server 2008
currently .NET 2.0 Framework don't have a service pack or hotfix to make Process.Modules use this new API
There are only some issues regarding the handling of the processes and the locking that I would change:
object lockObject = new object();
List<Process> processesToRemove = new List<Process>();
foreach (Process p in _runningProcesses)
{
foreach (ProcessModule module in p.Modules)
{
string[] strs = text.Split('\\');
if (module.ModuleName.Equals(strs[strs.Length - 1]))
{
processesToRemove.Add(p);
break;
}
}
}
lock (lockObject)
{
foreach (Process p in processesToRemove)
{
p.Kill();
_runningProcesses.Remove(p);
}
}
I'm not answering for the bounty, just wanted to give some ideas. This code isn't tested because I don't exactly know what you are trying to do there.
Just consider not to lock the process-list and to keep the lock as short as possible.
I agree with #sprinter252 that _runningProcesses should not be used as your sync object here.
//Somewhere that is accessible to both the thread getting the process list and the thread the
//code below will be running, declare your sync, lock while adjusting _runningProcesses
public static readonly object Sync = new object();
IList<Process> runningProcesses;
lock(Sync)
{
runningProcesses = _runningProcesses.ToList();
}
Process processToRemove = null;
foreach (Process p in _runningProcesses)
{
foreach (ProcessModule module in p.Modules)
{
string[] strs = text.Split('\\');
if (module.ModuleName.Equals(strs[strs.Length - 1]))
{
processToRemove = p;
break;
}
}
if (processToRemove != null)
{
break;
}
}
if (processToRemove != null)
{
//If we've got a process that needs killing, re-lock on Sync so that we may
//safely modify the shared collection
lock(Sync)
{
processToRemove.Kill();
_runningProcesses.Remove(processToRemove);
}
}
If this code is wrapped in a loop to continue to check _runningProcesses for the process you wish to kill, consider changing processToRemove to processesToRemove and change it's type to a collection, iterate over that list in the bottom block after a check for a non-zero count and lock outside of that loop to decrease the overhead of obtaining and releasing locks per process to kill.

How to make C# Powershell Invoke member thread safe

I have this service that, when request is received, runs a powershell command and returns result. Here is the invoker class code:
public class PowerShellScript {
public PowerShellScript() {
}
public Object[] Invoke( String strScriptName, NameValueCollection nvcParams ) {
Boolean bResult = true;
int n = 0;
Object[] objResult = null;
PowerShell ps = PowerShell.Create();
String strScript = strScriptName;
for (n = 0; n < nvcParams.Count; n++) {
strScript += String.Format( " -{0} {1}", nvcParams.GetKey( n ), nvcParams[n] );
}
//ps.AddScript( #"E:\snapins\Init-profile.ps1" );
ps.AddScript( strScript );
Collection<PSObject> colpsOutput = ps.Invoke();
if (colpsOutput.Count > 0)
objResult = new Object[colpsOutput.Count];
n = 0;
foreach (PSObject psOutput in colpsOutput) {
if (psOutput != null) {
try {
objResult[n] = psOutput.BaseObject;
}
catch (Exception ex) {
//exception should be handeled properly in powershell script
}
}
n++;
}
colpsOutput.Clear();
ps.Dispose();
return objResult;
}
}
Method Invoke returns all results returned by powershell script.
All fine and well. As long as this runs in a single thread. As some powershell scripts we invoke can take up to an hour to complete and we don't want for service to do nothing in that time, we decided to go multi-threaded.
Unfortunately Powershell class is not thread safe, resulting in sever memory leaks and cpu burn rate. However, if I use lock on Invoke method, this would mean that the entire idea why we went multithreaded will go down the drain.
Any ideas how to solve this?
You can use BeginInvoke() method of PowerShell class instead of Invoke() that you use. In this case you execute your script asynchronously and do not block the calling thread. But you have to review your whole scenario as well. Your old synchronous method returns results that can be easily consumed right after the call. In new asynchronous approach this is not possible in the same way.
see
http://msdn.microsoft.com/en-us/library/system.management.automation.powershell.begininvoke
Anyway... I gave up on multithreading when executing powershell commands. I created a small program that is able to execute powershell scripts. Then, each thread creates new process for that program. I know it is a bit of an overhead, but it works.
Basically, Powershell classes are not thread safe. Except static variables (http://msdn.microsoft.com/en-us/library/system.management.automation.powershell%28VS.85%29.aspx).
Hence, an attempt to call multiple scripts via separate threads results in memory leakage and some unexplained CPU usage. My wild guess is that it doesn't close properly. Changing from multi-threaded to multi-process environment should sort things out. However, that means a major politics change.

Kill some processes by .exe file name

How can I kill some active processes by searching for their .exe filenames in C# .NET or C++?
Quick Answer:
foreach (var process in Process.GetProcessesByName("whatever"))
{
process.Kill();
}
(leave off .exe from process name)
My solution is to use Process.GetProcess() for listing all the processes.
By filtering them to contain the processes I want, I can then run Process.Kill() method to stop them:
var chromeDriverProcesses = Process.GetProcesses().
Where(pr => pr.ProcessName == "chromedriver"); // without '.exe'
foreach (var process in chromeDriverProcesses)
{
process.Kill();
}
Update:
In case if you want to do the same in an asynchronous way (using the C# 8 Async Enumerables), check this out:
const string processName = "chromedriver"; // without '.exe'
await Process.GetProcesses()
.Where(pr => pr.ProcessName == processName)
.ToAsyncEnumerable()
.ForEachAsync(p => p.Kill());
Note: using async methods doesn't always mean code will run faster.
The main benefit is that the foreground thread will be released while operating.
You can use Process.GetProcesses() to get the currently running processes, then Process.Kill() to kill a process.
If you have the process ID (PID) you can kill this process as follow:
Process processToKill = Process.GetProcessById(pid);
processToKill.Kill();
You can Kill a specific instance of MS Word.
foreach (var process in Process.GetProcessesByName("WINWORD"))
{
// Temp is a document which you need to kill.
if (process.MainWindowTitle.Contains("Temp"))
process.Kill();
}
Depending on how many processes there are to kill (e.g. when its hundreds like in my case), foreaching over all of them might take quite a while. (interesting sidenote: while Kill() was usually quite quick in .NET FW 4.8 , somehow in NET 6.0 Windows its a lot slower - seeing multiple Win32Exceptions in the debug/trace until the target process is finally done)
Anyway back to topic:
In case of an app shutdown, where u need to make sure every process is is gone, consider using the TAP library - particulary the Parallel shortcuts, hundreds of processes killed within a glimpse.
Usage example:
var procs = Process.GetProcessByName("mydirtyprocesses");
if (procs.Length == 0) return;
procs.AsParallel().ForAll(process =>
{
try
{
process.Kill();
// No process linked to the process comp (mostly because the process died in
// the short timespan between invoking GetProcess() and the effective
// initialization of the props/fields of the component. -OR- Process has
// already exited (when the exit happened after the process component has
// beenpopulated (difference is, in case 1 you cannot even get the Process
// ID from // the component, in case 2 you see data like Id and get the true
// for HasExited // - so always be prepared for that.
// catch (InvalidOperationException)
{
// Process is gone, no further action required
return;
}
// Ensuring process is gone (otherwise try again or fail or whatever)
if (!process.HasExited)
{
// Handle it
}
}
In this particular scenario just wrap it properly in try/catch , as with such a number of processes the probability for an exception is quite increased
static void Main()
{
string processName = Process.GetCurrentProcess().ProcessName;
int processId = Process.GetCurrentProcess().Id;
Process[] oProcesses = Process.GetProcessesByName(processName);
if (oProcesses.Length > 1)
{
if ((MessageBox.Show("Application is opened!", "",MessageBoxButtons.YesNo) == DialogResult.Yes)) ;
{
foreach (var process in Process.GetProcessesByName(processName))
{
if (process.Id != processId)
{
process.Kill();
}
}
}
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmLogin());
}
}
public void EndTask(string taskname)
{
string processName = taskname.Replace(".exe", "");
foreach (Process process in Process.GetProcessesByName(processName))
{
process.Kill();
}
}
//EndTask("notepad");
Summary: no matter if the name contains .exe, the process will end. You don't need to "leave off .exe from process name", It works 100%.

Categories