I'm writing a c# program that will launch many child processes. At some time later on, I'll need to retrieve those processes by ID and then match those processes to a set of processes stored in a Dictionary that were added to the Dictionary when they were first created. However, I'm running into a problem that seems like pure ridiculousness...
Process notepad = new Process();
notepad.StartInfo.FileName = "notepad";
notepad.Start();
Process n2 = Process.GetProcessById(notepad.Id);
Debug.WriteLine(notepad == n2); //'False', but Why isn't this true???
Debug.WriteLine(notepad.Id == n2.Id); //'True'
I've used .NET Reflector to find out that GetProcessById returns a 'new Process(...)', but it seems like it should just find a reference to the already running process and return it instead.
You can assume the first Debug statement is essentially a call like
MyCustomDataType data = myDictionary[notepad];
I would expect to get the data I originally inserted, instead I get a KeyNotFoundException probably because the default comparer is doing a reference check. To counter this, I've added a custom IComparer on my dictionary that just checks that the two Process objects have the same ID, so I can get the associated data as expected. However, this has its own problem in that Processes that are not running do not have process IDs, so sometimes the call in my custom IComparer to Process.ID throws an InvalidOperationException!!! So, I've fixed one problem only to create another.
So, I guess I have two questions:
Running programs are operating system processes, not instances of the Process managed type. The Process
type is one type of managed wrapper object around an operating system concept. It allows control of the target process by hiding the P/Invoke calls. The operating system does not require a particular instance of the Process class perform these operations, which is why GetProcessById
can return a new instance and still expect everything to work.
The ID is valid for the life of the process itself. Perhaps you could set EnableRaisingEvents to true and add an event handler to the Process.Exited event that removes the process from your cache?