Console application not starting processes when scheduled in Windows - c#

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".

Related

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.

Start Node.js server from a C# Application

A requirement has arisen that I need to start a Node.js server from a C# application, this is as simple as running a server.js script within the Node.js console. However, I'm not entirely certain how exactly to achieve that.
Here's what I've looked into so far:
In the Node.js installation, there's a file called C:\Program Files (x86)\nodejs\nodevars.bat, this is the command prompt window for Node.js. To start the server, I could possibly be using the following steps:
Execute the nodevars.bat file.
SendKeys to the new process console window to start the server.
This approach feels a bit fragile. There's no guarantee that the target user will have their Node.js installation in the same place, also sending keys to a process may not be an ideal solution.
Another method could be:
Write a batch file that executes nodevars.bat.
Execute the batch file from the C# application.
This seems like a better approach. However, the only problem here is that the nodevars.bat opens in a new console window.
So to the question(s), is there a way I can start a node.js server script using functionality built into the node.js installation? Perhaps sending arguments to the node.exe?
If it is to serve multiple users, i.e. as a server, then you can use the os-service package, and install a Windows service. You can then start and stop the service using the standard API.
If you are to start the server as a "single purpose" server, i.e. to serve only the current user, then os-service is the wrong approach. (Typically when using this approach you will specify a unique port for the service to use, which will only be used by your application).
To start a batch file or other Console application, from C#, without showing a console window, use the standard method, but be sure to specify:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false; // This is important
psi.CreateNoWindow = true; // This is what hides the command window.
psi.FileName = #"c:\Path\to\your\batchfile.cmd";
psi.Arguments = #"-any -arguments -go Here"; // Probably you will pass the port number here
using(var process = Process.Start(psi)){
// Do something with process if you want.
}
There are a few different ones but I recommend the os-service package.

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

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.

downgrade rights of a started process

I need to start an application from another application. It looks like I have to use the shell to do it (since I need to be able to close the launcher), but I also would like to downgrade the rights given to the launching application.
Is this possible? The launcher must run as administrator, but I'd like to have the launching application run as user.
this is how I currently run the process:
Process process = new Process();
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = name;
process.Start();
Forgive me I forgot to add a couple of details:
I need to run it in .net 3.5 on mono
I'd prefer to not use native code
I need to run the launcher application in admin mode
This seems to be have discussed before, check this out: How do you de-elevate privileges for a child process
Looks like an UAC elevation is strictly one-way, so the solutions are a bit gnarly, i.e. code injection into explorer and stuff like that.
http://www.codeproject.com/Articles/18946/High-elevation-can-be-bad-for-your-application-How
Eventually I decided to create a bootstrapper that could run the launcher as administrator, but then the application as normal user. Once the launcher is done it goes back to the bootstrap executable which launches the application.

Restart program unelevated

For some reason, my C# program needs to restart with elevated privileges. I use the following code to achieve it:
private static void RestartForPermissionsFix()
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Assembly.GetExecutingAssembly().Location;
Process.Start(processInfo);
}
This works great.
After I "fix my privileges", I want to restart the program unelevated. I tried the same as above without the "runas", but it does not work. I assume the process being started from an elevated process automatically gets elevated. Any idea?
In order to launch a process at medium integrity from a high integrity process, I believe you would have to get the current process token using OpenProcessToken, duplicate it, remove the high integrity SID from the token using SetTokenInformation, and then use that token to create the new process using CreateProcessAsUser. This would be similar to this example, except rather than add the low integrity SID you'd have to remove the high integrity one. Note: I haven't tested this, so I'm not 100% sure it would work.
I suggest you leave the original unelevated process running, and have it wait for its elevated counterpart to finish (e.g. using Process.WaitForExit). Once that finishes, it can continue unelevated as before. This would be a lot easier and more foolproof.
I had the same problem with an application that I wanted to update automatically (The update program requires elevated privileges).
What I did was creating an external .exe that would start my updater program with elevated privileges, wait for it to exit, then restart my application with normal privileges.
I then embedded this .exe in my main application, and start this .exe just before leaving my application when I update it.

Categories

Resources