Start and manage external process from a WPF app - c#

I have a WPF application and I need to spin up a separate MFC application and then communicate with it. I was going to use Process.Start, but I'm wondering if there is a better way to do this these days. I can research things myself, but I need to know where to start. Thanks.
Edits:
I found this suggesting there isn't. Is this true?
Alternatives to System.Diagnostics.Process.Start()
Thanks.

For your immediate question, there is nothing new in the recent versions of .NET that gives a better or more up-to-date way to start a local executable. Process.Start is (and has been) the way to go.
The simplest, and most convenient, is to select one of the five static methods on Process. Passing strings or a populated StartInfo instance. You would use the latter if you needed more control over how the process got raised. Or of interest in your case, if you wanted to pipe the program's stdio as a stream into your own application. Here's a sample of populating a Start Info instance from one of my utilities...
ProcessStartInfo start = new ProcessStartInfo(BaseIoConstantsProvider.CommandProcessor)
{
Arguments = BaseIoConstantsProvider.KeepAlive,
UseShellExecute = false,
CreateNoWindow = BaseIoConstantsProvider.NoDosWindow,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
WindowStyle = ProcessWindowStyle.Hidden,
};
For the second part of your question, the static method will not do if you need to interact with the process once it is started. From the same utility...
Process p = new Process { StartInfo = start, EnableRaisingEvents = true };
p.ErrorDataReceived += PErrorDataReceived;
p.Exited += PExited;
p.Start();
p.StandardInput.AutoFlush = true;
p.StandardInput.WriteLine(cmdLine);
p.BeginOutputReadLine();
This example shows a two events being hooked along with reading the stdio from the process. It's great for that purpose, but overkill if you just want to start another executable.
So the main determinate in selecting a start method is the question: does my app need to interact with the process once it's started?
And finally, sometimes you may want to invoke a canonical verb, or even create a verb of your own to start a given process. These appear in the context menu when you right click an item and give you lots of additional flexibility for starting a process. There's an excellent article here http://msdn.microsoft.com/en-us/library/windows/desktop/cc144101(v=vs.85).aspx#canonical on how to implement a verb.

Related

How to change name of console app as displayed in task manager?

I am programmatically launching console applications. They all appear as conhost.exe in Task Manager.
How can I set a process name such that it appears as such in the task manager?
Example of how I'm setting up my process:
public static Process CreateMultiCoreExeProcess(int coreIndex, int coresToUse, string executableFilepath)
{
//* Create your Process
Process process = new Process
{
StartInfo =
{
FileName = executableFilepath,
Arguments = coreIndex + " " + coresToUse,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
},
EnableRaisingEvents = true
};
return process;
}
...as you can see there isn't an attribute that sets the process name (that I know of). I would like to be able to set the name of the process at the time that I create it.
DUPLICATE QUESTION REMARK: this is not a duplicate as attempted. The solution presented as a duplicate is for a STATIC name for the process, being set within project properties. I am running my process DYNAMICALLY (at run time) and would like to set the process name at that time.
UPDATE: I am convinced that this isn't possible. At least not in a realistic (i.e. permanent) way. I'm fairly certain we are "stuck" with the name as provided in the assembly information and it can't be programmatically changed in the Task Manager. This is unfortunate for my application, which is to spawn 10+ identical process executables. Sometimes I want to kill just one of them, but I can't determine which-is-which in the task manager because they all have the same name.
Use the line:
Console.Title = "My Console Application";
to set the console name
And to set the name/description in task manager, it's been answered before quite a few times. Check this link How can I set the Task Manager description for my program?
You can use P/Invoke to change the process name after creating it. (As you cannot specify it when you create it. The default name is the name specified in the program.)
[DllImport("user32.dll")]
static extern int SetWindowText(IntPtr hWnd, string text);
...
SetWindowText(process.MainWindowHandle, "Process Name/Title");
Edit: Looking around on the net, it appears you may need to wait 100ms or so before setting the name (either through Thread.Sleep or process.WaitForInputIdle in the case of a GUI application).

c# How to redirect stdout to new process window?

I was creating a Process using the call:
Process.Start(startInfo);
with
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.UseShellExecute = true;
startInfo.RedirectStandardInput = false;
startInfo.RedirectStandardOutput = false;
when the process runs with these arguments, it outputs to the new process's window fine.
However, when I make UseShellExecute false without redirecting standard output, the process no longer prints to the screen. Is this the expected behavior?
If so, how can i write to the new window that the process starts?
I can manually get the data from the process using StandardOutput.Read(), but I don't know how to write that to the new window. When I create that window, it appears to have a console by default.
I can use pinvoke to call the C++ function on the new process:
[DllImport("kernel32", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
I think that I may be able to just write to the console of the new window using the function "writeconsole"
https://msdn.microsoft.com/en-us/library/windows/desktop/ms687401%28v=vs.85%29.aspx
however, i was wondering if it's possible to do this just using .net libraries. I feel like what I want isn't so complicated that this should be necessary.
All I want is to be able to start a new process and redirect the stdout of that process to the new window that is created in that process, while retaining the ability to write to stdin.
edit:
Writing using console.writeline would just write to the main console of the program. My application is a gui app, so to be honest, I don't know exactly where it writes to, but I do know that you can see this output under the tab "output" in visual studio but not in the windows of the program itself. I think that there is a separate buffer allocated by .net for the console.
You can redirect stdout and stdin with freopen.
Example:
freopen ("file.txt","w", stdout); //or stdin
EDIT:
You could also use createpipe() and read from the end of the pipe. You can tell the pipe, then, where you would like your data to be read to or stored/displayed. If this is not what you are looking for, please elaborate more in depth with a comment.

C# equivalent to fork()/exec()

I'm developing a program that needs to call an outside program, but needs to wait for it to execute. This is being done in C# (to which I am brand new, but have lots of experience in C++, Qt, and C) and CreateProcess does not seem to be what I'm looking for (starts the process, then forgets it, which I don't need).
This is one of my first Windows projects (or at least, only Windows and definitely only .NET) and I'm much more used to doing this sort of thing for *nix where I would use fork and then exec in the child, then wait for the child to terminate. But I have no idea where to even start looking to do something like this.
Oh, and I'm pretty sure I'm stuck in .NET because I need read access to the registry to complete this project and .NET's registry access is absolutely amazing (in my opinion, I don't have anything to compare it to).
Thanks.
You can use the Process class. It lets you specify some options about how you want to execute it, and also provides a method which waits the process to exit before executing the next statement.
look at this link (the msdn reference):
http://msdn.microsoft.com/fr-fr/library/system.diagnostics.process.aspx
basically what you can do is:
Process p;
// some code to initialize it, like p = startProcessWithoutOutput(path, args, true);
p.WaitForExit();
an example of initializing the process (that's just some code I used once somewhere):
private Process startProcessWithOutput(string command, string args, bool showWindow)
{
Process p = new Process();
p.StartInfo = new ProcessStartInfo(command, args);
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = !showWindow;
p.ErrorDataReceived += (s, a) => addLogLine(a.Data);
p.Start();
p.BeginErrorReadLine();
return p;
}
as you can see in this code you can also do some output redirection, error redirection.... If you dig in the class I think you'll find quite quickly what you need.
var p = System.Diagnostics.Process.Start("notepad");
p.WaitForExit();
You can use the Process class to start external processes.
It will let you start arbitrary programs
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

InvalidOperationException if the process is started as a default associated program for a file type

Situation:
I spawn processes for various file types (pictures, Word documents, etc) by relying on the default associated handler program. This means that I only specify the particular file name as the StartInfo.FileName, and no actual executable precedes that file name. At the same time I specify StartInfo.UseShellExecute = true. This way the associated software with that file type will start.
My goal is to get notified when that process exits.
Process process = new Process();
try
{
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = pFullPath;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardError = true;
bool notReused = process.Start();
}
catch (Win32Exception ex)
Variations:
Process's static Start method does return a Process, but I get back null/empty object for my scenario. So that's why I instantiate a Process class explicitly, set parameters for its StartInfo property, and then call non-static Start() in the end, so I have a hold of that Process object instance.
If I say StartInfo.UseShellExecute = false, I get an exception, 'cause I didn't specify executable name. It seems that that's the way to invoke associated program with a file type.
The non-static Process.Start has a boolean return value, and it indicates that the system reused a Process. I don't want that, but I don't know how to avoid it.
I tried to set Redirect* booleans of StartInfo, but that throws the InvalidOperationException again, and that conforms to the documentation.
If I had a "good" Process object, I could hook up the Exited handler and set EnableRaisingEvents to true. I'm amazed and sad how such a PITA is this.
This is completely impossible.
Launching a file is not guaranteed to create a process at all.
Raymond Chen has far more detail.

What’s the difference between Process and ProcessStartInfo in C#?

What’s the difference between Process and ProcessStartInfo? I’ve used both to launch external programs but there has to be a reason there are two ways to do it. Here are two examples.
Process notePad = new Process();
notePad.StartInfo.FileName = "notepad.exe";
notePad.StartInfo.Arguments = "ProcessStart.cs";
notePad.Start();
and
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "notepad.exe";
startInfo.Arguments = "ProcessStart.cs";
Process.Start(startInfo);
They are pretty close to the same, both are from the Process class. And there are actually 4 other overloads to Process.Start other than what you mentioned, all static.
One is a static method way to do it. It returns the Process object representing the process that is started. You could for example start a process with a single line of code by using this way.
And the other is a member method way to do it which reuses the current object instead of returning a new one.
Heh.
If you look closely at your code, you will note that they are both using the same classes. The StartInfo property in your first example is, unsurprsingly, a ProcessStartInfo. In your second example, you call the static .Start method on the Process class.
So what are the differences? Significant. They're different classes. One is for launching processes, one is for saying which process to launch (and lots of other little things, like capturing output, etc). In the first case, you just use the default ProcessStartInfo property that the class has.
It seems that ProcessStartInfo is a subset of Process if you look at the members of notePad variable below
Process notePad = new Process();
You will notice that StartInfo has type (or of class) ProcessStartInfo
which is why the two initializations are the same
notePad.StartInfo.FileName = "notepad.exe"; Vs startInfo.FileName = "notepad.exe";
Since Process is the full class I would think it can do everything ProcessStartInfo can do plus extra But Don't take my word for it I only less than a year experience in .Net

Categories

Resources