I have a app I have been working on that just sends and receives dicom files using dcmtk. My current problem is that I need help trying to figure out a way to monitor a exe actively when called. So once my code runs which spits out console output to a textbox. Im grabbing the last entry in that text box and if it is "I: Releasing Association" and storescu closes it will delete all the items in a folder(dicompath)
startInfo2.ErrorDataReceived += proc_DataReceived;
startInfo2.OutputDataReceived += proc_DataReceived;
startInfo2.Start();
startInfo2.BeginOutputReadLine();
startInfo2.WaitForExit(10);
//Thread.Sleep(1000);
DeBug.Invoke(new MethodInvoker(delegate { DeBug.Text = finalpath; }));
Process[] processes = Process.GetProcessesByName("storescu-beta.exe");
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
if (trig.Text == "I: Releasing Association")
clearFolder(dicompath);clearFolder(dicompath);
}
So far I have not be able to get any of this to work. It seems the output to the textbox is trying to look for the "I: releasing Association" before its there so I need to add somehow a wait until its done updating. each output to the textbox is one line of the console so at the very end it just has "I: releasing Association".
As for the monitoring storescu-beta.exe Im at a loss because I dont know how to monitor for its running status actively when called.
Related
i have this C# code (WPF app, but it probably doesnt matter):
void StartEditing(string projectPath) {
InitializeProject(projectPath);
Process process = Process.Start(new ProcessStartInfo(#"path\to\Code.exe", projectPath));
if (!process.HasExited) {
process.Exited += (sender, args) => { CleanupProject(projectPath); }
process.EnableRaisingEvents = true;
}
}
Basically i wanna to do some initialization before vscode starts and then do some cleanup after it exits (start/stop synchronization of changes with remote storage using FileSystemWatcher).
My code works only when there is no Code.exe process already running at time of call Process.Start method.
When there is already another Code.exe process (from different project), then my process exits immediately but vscode window is still opened afterwards (guessing vscode detects previous instance and pass its arguments to it before exiting)
So my question is: How to detect, that vscode opened at projectPath was closed?
PS: on my machine opening folder in vscode spawns 13 Code.exe processes and opening second one spawns additional 3.
I have a batch file that i run through process but when the batch file finish running and closed the Form also close. How can i prevent the process in closing the form. Here is the code.
Process support = new Process();
support.StartInfo.FileName = #"C:\Support\Support.bat";
support.EnableRaisingEvents = true;
support.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
support.StartInfo.CreateNoWindow = true;
support.StartInfo.UseShellExecute = false;
support.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
support.StartInfo.RedirectStandardOutput = true;
support.Start();
support.BeginOutputReadLine();
Here is the output handler that writes the output of the batchfile to a richTextbox
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
string line;
line = (outLine.Data.ToString());
txtStatus.AppendText(line + "\n");
}
The batch file automatically close when done and the Program close also and never executed the remaining codes.
You can use either
Console.ReadLine();
or
Console.ReadKey();
ReadLine() waits for the Enter key to be pressed, while ReadKey() waits for any key to be pressed (Except modifier keys - Shift, Control, Alt, Command, Option.. to name a few)
If this is purely for testing from VS then you can run the app without debugging using Ctrl + F5
Process will open up a window by itself, and once the .bat file exits, will exit and close the main window. It's not your code that is wrong, it's by default the way a .bat file is run if you just double-clicked it in Explorer (cmd opens until .bat is completed and then closes again)
You mentioned that you tried "Process.WaitForExit()" but I'd like to point out, in your context, it should be "support.WaitForExit()" much like your "dt.WaitForExit()" (code you posted that is now removed)
If that doesn't work, add "PAUSE" on a new line in your support.bat file. This will prevent the window from closing as well until a key is pressed.
If you do not have access to edit the support.bat file, all you need to do is read the file contents and save it somewhere temporarily, and then run it... or add it:
using (StreamWriter w = File.AppendText("support.bat"))
{
w.WriteLine("PAUSE");
}
Above is obviously an example, you'd need to check if "PAUSE" is already the last line before writing to the file again. I also didn't show code on how to create a file and saving it, you should be able to handle that :)
This question already has answers here:
How to open an application on active display while using Process.Start()?
(1 answer)
Programmatically, how does this application detect that a program is ready for input
(3 answers)
Determining when a process has finalized initialization
(2 answers)
Check if Windows Application is running (not process)
(4 answers)
Closed 5 years ago.
I'm working on an application that starts other processes (some console applications, etc.). Each process has a user interface. When each process is started (via process.Start()), I want to move the process UI to some other location on the screen (also on the second monitor). I know how to do this later after a "sleep" or button click action. The problem is that I want the window to move right after the process starts. The window handle is still not "available" (value is 0).
I searched for a solution and came across the process.WaitForExit(100) method and the process.Exited event handler. After investigating these, I discovered that:
the process.Exited event is called when the process ends and not when the process "loads," and
process.WaitForExit(100) causes the program to "sleep" when it is invoked.
So, I need some architecture guidance. How can I solve my problem without "sleeping" (for example, via process.WaitForExit(100))? Should I consider an approach that involves one of the following techniques:
Mutex,
Multithreading, or
Async process start?
Or, is process.WaitForExit(100) really OK (not "dangerous") for a stable application (if I will run up to 15 processes)? Here is my code example:
private void startApplication(
int aApplicationId,
string aBrowserPath,
string aAppPath,
int aMid,
int aAppLeft,
int aAppTop,
int aAppWidth,
int aAppHeight) // Try to start application process
{
Process process = new Process();
try
{
process.StartInfo.FileName = aAppPath;
//process.EnableRaisingEvents = true;
//process.Exited += new EventHandler(myProcess_Exited);
//process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit(100);
mProcessMap.Add(aApplicationId, process); // Add to process map
// Move process window to right position
IntPtr windowHandle = process.MainWindowHandle;
this.moveAppToRightPosition(windowHandle, aMid, aAppLeft, aAppTop,
aAppWidth, aAppHeight);
}
catch (Exception exc)
{
Console.WriteLine("ERROR! Process start exception!");
}
}
You can't retrieve the MainWindowHandle immediately after the process is created because the creation of a process and of a window are two completely independent things (not to mention that a process may not even have a window). So there is nothing wrong with sleeping and waiting for the MainWindowHandle to appear. MSDN says you need to call Refresh to update it.
If you don't want to sleep you have two options:
Set a hook that will notify you when the process created a window. More details in this answer.
If you also created the process you are launching then you can insert the logic that will notify the master process via a socket or named pipe once the window is created.
Sleeping might not be the right way, because the process might need more time to start.
It may be possible to start a thread (if you want to asynchronously run the function startApplication) and in that thread check for the state of the process and when available set the position of window (looping with sleep at the end of loop).
I would use SendMessageTimeout to send WM_NULL messages in a loop, with a small timeout of say 50-100ms. If the function succeeds, that means that the new process is alive and going strong. In this way, you will block only for the timeout interval.
updated
I have a problem related to Process.Start();
My program launches files as processes, like so:
Process processMonitor = new Process();
processMonitor.StartInfo.FileName = filePath; // Example: #"C:\test.txt"
processMonitor.StartInfo.CreateNoWindow = true;
processMonitor.Exited += new EventHandler(Process_Exited);
processMonitor.EnableRaisingEvents = true;
processMonitor.Start();
// Handle Exited event and display process information.
private void Process_Exited(object sender, EventArgs e)
{
// This code is called on every exit, except images: (Windows Photo Viewer, *jpg, *png, *bmp etc.)
}
This successfully launches a process, notepad.exe with the correct file.
Catching the Exited event also works so basically i have everything in place to monitor the close event for the process.
Now for the problem...
When doing exactly the same, but now for an image:
processMonitor.StartInfo.FileName = filePath; // Example: #"C:\test.jpg"
This is not successfull.. The process launches perfectly, But i can not detect if the process is ever closed. A little research shows me that a process called:
DLLHOST.EXE (COM Surrogate)
Is launched and i cannot detect the Exited event for this process.
Can anybody help me, or at least point me in the right direction?
If all other doesn't work, you can look into WMI: http://msdn.microsoft.com/en-us/library/aa394582(v=vs.85).aspx - this will require you to do some wrapping work (or use a wrapper, like the one here: http://www.codeproject.com/Articles/21971/WMI-Interface-for-NET)
Another option you can use as last resort and as a workaround only is polling for the process state, but this is really not recommended for most project, and it certainly doesn't sound like something you want to do in your project.
I think it has to do with the nature of an image. Opening a .txt file launches notepad whereas opening a .jpg opens a viewer. Any way to key into the viewer itself?
I try to open 2 pdf files in Adobe Reader from my C# code. Lets call them A and B and A is opened before B.
Now when I try to kill the process associated with file A file B also closes down because they are linked to same process. Is there a way to close File A without closing file B.
Also when I first try to kill the process associated with File B , nothing happens and File B still remains open.
How should I go about in solving the above two scenarios.
I have handle of both the files. Is there a way I can close the handle
Sounds to me like you should be using the Interapplication Communication API for Acrobat, which has the facility to open and close documents. What you're doing is fairly inelegant compared with what you can get with IAC (pdf documentation here).
you can find the process of PDF viewer of A by following code.
using System.Diagnostics;
public bool FindAndKillProcess(string name)
{
//here we're going to get a list of all running processes on
//the computer
foreach (Process clsProcess in Process.GetProcesses()) {
//now we're going to see if any of the running processes
//match the currently running processes by using the StartsWith Method,
//this prevents us from incluing the .EXE for the process we're looking for.
//. Be sure to not
//add the .exe to the name you provide, i.e: NOTEPAD,
//not NOTEPAD.EXE or false is always returned even if
//notepad is running
if (clsProcess.ProcessName.StartsWith(name))
{
//since we found the proccess we now need to use the
//Kill Method to kill the process. Remember, if you have
//the process running more than once, say IE open 4
//times the loop thr way it is now will close all 4,
//if you want it to just close the first one it finds
//then add a return; after the Kill
clsProcess.Kill();
//process killed, return true
return true;
}
}
//process not found, return false
return false;
}
then call above method.
FindAndKillProcess("AcroRd32.exe");
so you can kill the process of PDF viewer.
TRY:
if (clsProcess.ProcessName.Contains(name))
INSTEAD:
if (clsProcess.ProcessName.StartsWith(name))
using System.Diagnostics;
public bool FindAndKillProcess(string name)
{
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(name))
{
//To know if it works
//MessageBox.Show(clsProcess);
clsProcess.Kill();
return true;
}
}
//process not found, return false
return false;
}
////// call the function:
FindAndKillProcess("AcroRd32");
////// if you have been saved all the variables also you can close you main form
FindAndKillProcess("Form_Name");
I think one way to do this would be to find that instance of the program and close it from your application. Here is an example of how to find the window and close it: http://www.mycsharpcorner.com/Post.aspx?postID=32
Since you have 2 instances of Adobe reader open you will want to determine which is which. You can search by the text in the frame. If you have a copy of spy++ (or a similar alternative) it makes working with outside GUI components much easier because, you can find out so much about that window, including the name, the window handle and more.