How does the command prompt know when to wait for exit? - c#

I was attempting to do a Windows command prompt re-code in C#. I was wondering how the command prompt knows when to wait for the process started to exit, and when not to wait for the called process to exit.
For example, if you type in the command prompt "notepad", Notepad will launch, but you can still execute other commands. However, if you open a utility such as more.com, ping.exe, or another utility, it will wait for the executing program to finish before letting you execute another command.
How does the command prompt know when to wait for exit, and how can this behavior be emulated in C#?

If the application is a Win32 GUI application, it will just run and command prompt won't wait for it to exit.
If the application is a console application, it will run in the command prompt and you'll need to wait for it to finish to get the command prompt back.
EDIT:
OK. It seems you need technical explanation. If you want to emulate the same feature in your application, you can check IMAGE_OPTIONAL_HEADER of EXE files here.
Inside IMAGE_OPTIONAL_HEADER, there is:
WORD Subsystem;
If SubSystem == 0x02 it means it's a GUI application.
If SubSystem == 0x03 it means it's a command prompt app.
EDIT 2:
If you want to see it in action:
Download http://www.ntcore.com/exsuite.php
Copy calc.exe or notepad.exe to your desktop
Open copied calc.exe in CFF Explorer
Navigate to Nt Headers -> Optional Headers
Change SubSystem from 0x002 to 0x003
Save it
Now run the new modified calc and you'll see the command prompt wait for it to be terminated.

The default from a command prompt is to spawn the GUI program in a separate process/fork.
However, you can run notepad (or other GUI program) inline with your command prompt / shell script:
start /w notepad.exe
This way, the command prompt / shell script only continues after the notepad.exe process has terminated.
Hope this helps, TW

When you start a new process, a GUI application in this context that actually works outside the boundaries of the prompt, the prompt will not wait. But, if you run a command that works entirely under the boundaries of the current instance of a prompt, it waits.
So, command notepad just starts the Notepad application and leaves control of application. While, command ipconfig runs under a domain (no this is not application domain), of the prompt.
To extremely generalize, when you use Process.Start in your C# equivalent, do not wait. It anyway will not.

Related

C# Started Command Prompt not closing

I just started using C# again and I encountered a bug/issue while trying to start a process using command prompt.
I am trying to start/open the default On-Screen Keyboard from windows using command prompt. However, after the osk.exe executed, The command prompt window is still open. After manually closing the command prompt window by clicking "x" button and tried to click the button to execute the code again, The command prompt will then close after opening osk.exe as it should be.
Here is the code I tried to run:
Process.Start(Path.Combine(Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.System)).FullName, "Sysnative", "cmd.exe", "/c osk.exe ; exit");
I got this code from this website
I even tried to run another line just to kill all open command prompt with code below. But after executing, another command prompt is opened and never automatically closed....
System.Diagnostics.Process.Start("CMD.exe", "taskkill /IM cmd.exe");
I tried to manually run in command prompt just to see if my windows command prompt has bugs, but its working fine.
I just want to open on-screen keyboard when a button is clicked without keeping an open command prompt and without changing the platform type of my application (i tried to do this before and it messed up most of my OLEDB Connections).
Any answers and suggestions is highly appreciated.
Also, I'm very sorry for my bad English.
This should work, it doesn't start CMD though:
//specify full path - possible through environment variables
var psi = new ProcessStartInfo(#"c:\windows\system32\osk.exe");
psi.UseShellExecute = true;
var process = Process.Start(psi);

How to terminate a command issued to cmd.exe

I created a cmd process in which I display the output to a window. I would like to be able to terminate the command like pressing Control-c in the command prompt.
new ProcessStartInfo("cmd.exe");
The only option I can think of is to terminate the process. Is this what pressing control-c does? The problem with this is some user settings will be lost. Two I can think of are prompt and the current directory. could there be any others? I can remember these and create a new process and reset them. Or is there another way to simulate the interruption?
enter image description here
You can start a process by calling the Start method. You can also end the process by calling the Kill method. All well and good. Now lets start a process by running cmd.exe and redirecting the input and output. So now assume we execute a command that takes a long time. It would be nice to cancel the command like we can do in a DOS window (Command Prompt) instead of forcing the user to close and reopen the app losing their history in the process.
I can provide more details if necessary.
The mechanism that cmd.exe uses1 is GenerateConsoleCtrlEvent, and it is not available when your Process.Start call created a new console, because of this restriction in the documentation:
Only those processes in the group that share the same console as the calling process receive the signal. In other words, if a process in the group creates a new console, that process does not receive the signal, nor do its descendants.
The option you have is to not launch cmd.exe directly, but start a console program that is in turn responsible both for starting cmd.exe in its shared console, and also keeping a communication link with your program open in order to know when to generate console control events.
Actually it should be the console subsystem detecting Ctrl+C and generating the console event, and it's received by both cmd.exe and any child process. cmd.exe has a complex handler that will cancel a running builtin command (like dir) and not exit. Child processes may also have logic to exit cleanly and save state when the console control eventis seen.

Custom Powershell Host Invoke external program without console window

I'm writing an embedded powershell host in C# (windows application), and if there is an external program called in the pipeline the console window flashes as it's executed. Ping and netstat are examples of this as shown in the following code snippet
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("Get-Content test.txt; ls; ping www.google.com");
PowerShellInstance.Invoke();
# ...more code here to print output etc
}
Once the ping command is reached in the pipeline a console window will popup execute the command and return results. I would like to do this without the console window showing. I've searched and found examples of how to deal with this by starting a process for external commands and redirecting output.
I can do that of course, but then how would I test if a command in the pipeline is a call to an external program?
I would really like to be able to handle this generically if possible; meaning that I don't want to test for specific programs (e.g. ping, netstat, net) if I don't have to. The native powershell.exe does this so it's somehow possible.
It turns out that this is expected behavior of invoking console commands. In Windows 7 and above conhost.exe is responsible for handling calls to console programs. In this case, ping and netstat trigger an instance of conhost to be created, it handles the request, returns the results, and then remains open. conhost.exe starting up is what is causing the console flash I'm seeing. The fact that it remains open is why I was only seeing the console window flash once. Once conhost is connected to the calling process all subsequent console commands are handled by that same instance.
I'm marking this as an answer because a new question should be created to address conhost specifically.
Source. Windows Internals Part 1

How to run a dos command with p4.Net API

I have some batch commands to run in the Perforce. Generally, I open the command prompt from "Perforce->Right click a file->Open Command Window Here".
I am trying to automate some task that involves running a command from Command Window that is opened from Perforce.
Using p4.Net API, How can I run the dos command from current perforce Client?
I believe the only thing special about "Open Command Window Here" is that:
The command window current directory is set to that directory in your source tree.
The P4USER, P4PORT, and P4CLIENT environment variables are configured to match the settings of the Perforce client workspace that you are using.
So you can use ordinary C#.Net techniques to run a child process. Here's a somewhat similar question that should give you some ideas (it uses Source Depot as its example, which is like Perforce but it's a different SCM; still, the overall concept should be similar): How to run cmd.exe using c# with multiple arguments?

Console application not starting processes when scheduled in Windows

I have a simple .NET console app in C#, that runs an external process "pscp" (putty secure copy). This works great when I just run the .exe.
However, when I schedule the application in windows scheduled tasks, the application does not seem to open the external process pscp.exe. Normally it should pop up an extra console screen and open pscp.exe there. This works, just not when scheduled.
I start the process like this:
pscp.FileName = "pscp.exe";
Process p = Process.Start(pscp);
p.WaitForExit();
Any ideas on how to fix this?
Starting cmd with the /c argument runs "your exe" in a new cmd window.
The scheduled task runs under a different identity. Make sure that's working. Also, make sure you wrap the call to your exe with a cmd /c "your exe".

Categories

Resources