0

I am currently working on a c# project and am using the System.Diagnostic.Process class.

When my program starts it creates a new thread and within each thread starts a different process.

At some point I need to check a setting within my program to see whether each process should continue running or whether it should be stopped but I have no idea how I can reference the process that was started by a certain thread. Each thread I have given a name when the process started but my understanding is c# creates the thread, starts the process and then closes the thread even if the process is still running and is still receiving output.

Is there a way I can find out which process was started by which thread and cancel that processs from running.

But I can't see how I can use this method and the dictionary to be able to stop the process based on this thread name.

UPDATE As request below is the code that I am using that creates each process in the thread. I am using the thread in a dictionary so that I can references it from the outputreceived event but not sure how to do it if I need to close the process.

Thread worker = new Thread(new ThreadStart(() => startProducts(product.Value[0].startScript, product.Value[0].productName)));
                worker.IsBackground = false;
                worker.Name = product.Value[0].productName;
                worker.Start();
                logging.logger(string.Format("Starting product '{0}'", product.Value[0].productName));

The method that the thread calls is as follows, this is where each process is started. Each process is guaranteed to have a different named thread, there will never be two threads with the same name.

private void startProducts(string startScript, string product)
        {
            Process startProductProcess = new Process();
            startProductProcess.StartInfo.FileName = startScript;
            if ( configManagement.productConfig[product][0].requireArguments == true )
            {
                startProductProcess.StartInfo.Arguments = configManagement.productConfig[product][0].arguments;
            }
            startProductProcess.StartInfo.UseShellExecute = false;
            startProductProcess.StartInfo.RedirectStandardOutput = true;
            StringBuilder processOutput = new StringBuilder("");
            startProductProcess.OutputDataReceived += new DataReceivedEventHandler(startProductProcess_OutputDataReceived);
            startProductProcess.Exited += new EventHandler(startProductProcess_Exited);
            processTag.Add(startProductProcess, product);
            startProductProcess.Start();
            //Process localByName = Process.GetProcessById(startProductProcess.Id);
            startProductProcess.BeginOutputReadLine();
            logging.logger(string.Format("Started {0} with: {1} {2}", product, 
                startProductProcess.StartInfo.FileName, startProductProcess.StartInfo.Arguments));
        }
Boardy
  • 35,417
  • 104
  • 256
  • 447

2 Answers2

0

Why use the thread name for anything? If you were to pool this activity off, you wold have no idea which thread was going to run any particular process.

If you are managing processes, define a 'managedProcess' class that can contain fields and properties for the process name, process EXE path, process handle, the thread waiting on the handle for the process to finish, any status enum, any mutex to keep the fields thread-safe, methods to start it and stop it - anything to do with the process. Shove instances of this managedProcess class into your container.

IMHO, forget thread names for anything except debugging.

Terminating - in your stop() method, you can try posting a WM_CLOSE, (can you do that directly, or is it a P/Invoke?), waiting for some seconds to see if the thread waiting signals that the process has closed and, if not, call TerminateProcess(), (or whatever the managed thingy is for TerminateProcess).

Martin James
  • 24,453
  • 3
  • 36
  • 60
0

Unless you have a specific need that is solved by creating each process using a separate thread, don't use threads. If all you are looking for is a unique way to identify a given process in your code, you can use the name that you were giving to the thread as an identifier in your dictionary.

Dictionary<string, Process> processesByName = new Dictionary<string, Process>();
Process firstProcess = ... //Start your process
Process secondProcess = ... //Start your process
processesByName.Add("FirstProcessName", firstProcess);
processesByName.Add("SecondProcessName", secondProcess);

After that, you can just pull a given process by the name you've assigned and interact with it however you want.

Process process = processesByName["FirstProcessName"];
if (!process.HasExited)
{
    process.CloseMainWindow();
    process.Close();
}
Chris Hannon
  • 4,134
  • 1
  • 21
  • 26
  • Thanks for your help, but this wouldn't work as a new Process is started within a for each loop so I am unable to name each proces so I will have no idea which processs is what to close it – Boardy Apr 20 '12 at 18:48
  • @Boardy Let's back up. You're creating processes in a foreach loop. Does each thread have a loop that starts N processes or is the loop spawning N threads that each start a single process? Could each process theoretically _have the same name_ or is the thread name unique for a given process? – Chris Hannon Apr 20 '12 at 18:56
  • @Boardy If you can post code showing how you're creating the threads and processes, that would be good. – Chris Hannon Apr 20 '12 at 19:00
  • I've added the cod you requested where the thread starts the process. To answer your previous question it is guaranteed that each thread will have a separate name. I am not going to know the name of the process which is why I am using the thread name. Thanks for your help – Boardy Apr 20 '12 at 20:10
  • So you have a unique name for a process and you're already associating that with the process in your dictionary. How do you need to determine which process needs to close and why does the name even matter? – Chris Hannon Apr 20 '12 at 20:32
  • There is a config file that states whether or not that process should be running, if its set to false it needs to stop that process but how do I know which process it should stop, as far as I know there is no way I can determine which process to stop, this is why I was using the thread name. When you say the process has a unique name its based on the thread name, as far as I know you can name the process itself – Boardy Apr 20 '12 at 21:07
  • Then it sounds like you have a different problem than how to get the thread name that started a process. Associating the process or thread with the product name (or any name) does no good unless you _already know_ how that relates to a given configuration entry, and determining how best to set that mapping up goes far beyond the scope of the original problem and requires more domain-specific information about your current architecture and code. If you can clearly and concisely explain this new mapping problem, you may want to create a new Stack Overflow question and get more help on that. – Chris Hannon Apr 20 '12 at 21:48