How to run a dos command with p4.Net API - c#

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?

Related

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.

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

Start a new explorer.exe process from C#

If I run this command:
C:\WINDOWS\explorer.exe "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\::{2227A280-3AEA-1069-A2DE-08002B30309D}"
from the Windows shell (via Windows+R), my printer and faxes open in a new explorer.exe process. (So I have 2 running explorer.exe processes.)
If i execute:
Process.Start(#"C:\WINDOWS\explorer.exe", #"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\" +
#"::{21EC2020-3AEA-1069-A2DD-08002B30309D}\" +
#"::{2227A280-3AEA-1069-A2DE-08002B30309D}");
from a C# program, my printer and faxes open too, but as an child process of the main explorer.exe process (the one running the Windows shell, including the taskbar, etc.).
What can I do to start a second explorer.exe process with the printer and faxes window from C#?
Initial thoughts - check your "Launch folder windows in a separate process" in Folder Options (Organize -> Folder & Search Options -> View tab). This is unchecked by default, hence "Check" this and try your C# code again.
I know this setting affects the ShellExecute function but I am not sure if .NET's Diagnostic namespace uses the same route.
ShellExecute(handle, "explore", , NULL, NULL, SW_SHOWNORMAL);
Second thoughts - a similar issue has been already discussed in stackoverflow and this post might give you some idea.
Start new process, without being a child of the spawning process

Run a DOS command in .NET

I have a set of commands like:
C:
cd Project
testproj.exe
My system gets these commands one by one from a remote system.
I need to execute each command in cmd.exe on receiving the command from the remote system. How to execute these using .NET?
I also need to return the result of testproj.exe to the remote machine. How to take the result after running command?
Process.Start cmd.exe, and hook StandardIn, StandardOut, and StandardError. Then, when a command comes in, just write it to StandardIn and read StandardOut/Error for the return. The whole thing shouldn't be more than 15 LOC.
That being said, just installing the Telnet Server would probably be easier - as it sounds like that's what you're essentially replicating....
var process = System.Diagnostics.Process.Start( "testproj.exe" );
process.WaitForExit();
var result = process.ExitCode;
This won't really honor things like "C:" or "CD path". Instead you'd want to create a batch file in a temporary folder then call the batch file.
Take a look at System.Diagnostics.Process. You can redirect stdout/stderr somewhere to get the output.
The C: and cd Project operations can be done inside the lanching application using the Directory class using the SetCurrentDirectory method.
Then just use the Process class to launch the testproj.exe executable.
Instead of trying to support all the commands of DOS, just have a small subset implemented which will guarantee nothing can go wrong. Like Don't allow DELETE, RD, FORMAT etc.
So, basically you would only have a subset of DOS commands. Once you have the command set, you can code for those specific commands using a extension mechanisms or as pluggable modules.
This will also helps you safe guard your machine from malicious attacks and worst to happen is there could be data sent out but from machine, the data / system can never be harmed.
UPDATE: The implementaion of specific commands is left to you. You could use .NET API or have System.Diagnostics.Process

Categories

Resources