I am new to C# and I am creating a UI for iperf(windows).
Since I could not obtain the source code for the windows version, I have to try a different method.
My aim is to create a UI which will re-direct the commands to command prompt and get the output and display it back in Visual Studio.
How do I achieve this?
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "your command here";
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Now output string variable holds result of command execution.
More details here
I suggest you check out the Process class. It will allow you to start a new process and redirect the output and error streams.
EDIT:
After reading again it is not clear why you would want to redirect back to Visual Studio. I initially read this as you want to write a UI that will send commands and display the output using Visual Studio, not actually displaying in Visual Studio.
Related
I'm trying to open an external executable. I can easily open external executables by using the Process class from System.Diagnostics:
Process p = new Process()
p.StartInfo.FileName = processName;
p.Start();
This works fine with most programs, like browsers and notepad, creating a process and showing its graphical interface. However, when I try to open my desired program, the process is started (can see it in the task manager, it even takes a whole CPU core for processing) but the GUI window doesn't show. What could possibly happen to a process from Process.Start to not show its GUI?
For reference, the program I want to execute is ADOM release 60, which runs 100% fine when I open it directly in the Explorer shell or in the Powershell. This is reproducible in both console and WindowsForms applications.
Here are some other settings that did not help:
p.StartInfo.CreateNoWindow = true; // or false
p.StartInfo.ErrorDialog = false;
p.StartInfo.WindowStyle = /* any of possible values */;
p.StartInfo.UseShellExecute = true; // or false
You need to set the WorkingDirectory to the root folder where the executable is located.
var executablePath = .....;
var p = new Process();
p.StartInfo = new ProcessStartInfo(executablePath);
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(executablePath);
p.Start();
The default value of WorkingDirectory is %SYSTEMROOT%\System32. Many legacy applications have hard coded relative paths that resolve to full paths with said directory and will fail miserably when trying to read (or create) files where they are not supposed to.
I am trying to use Plink to access information on a machine. I followed this tutorial:
http://www.mindfiresolutions.com/Creating-a-SSH-connection-using-plink-PuTTY-via-C-application-1760.ph
So far I am only using my program to just open up Plink, and I will be adding in the login information and such once I can at least get Plink to be openable in my program. I have this based on the tutorial:
ProcessStartInfo psi = new ProcessStartInfo(#"C:\Windows\System32\cmd");
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
psi.UseShellExecute = false;
psi.CreateNoWindow = false;
Process process = Process.Start(psi);
Thread.Sleep(3000);
string cmdForTunnel = "plink";
process.StandardInput.WriteLine(cmdForTunnel);
process.WaitForExit();
Thread.Sleep(10000);
//DoBusinessLogic();
process.StandardInput.WriteLine("logout");
Thread.Sleep(10000);
if (process.HasExited)
{
process.Close();
process.Dispose();
}
But nothing is displayed, which bothers me. The command plink is supposed to display the help information on how to use the program (I will be replacing the command with something more useful later), but the command prompt remains empty. I also experimented by replacing plink with ipconfig, which also displayed nothing.
I know how to open up cmd myself and type in plink to access it. I want to replicate this action in my program.
You have many faults in your code:
You are redirecting an output, and you are not reading/processing/printing it (that's why "nothing is displayed")
Running plink by "typing" plink to cmd.exe is insane. You can run plink directly, avoiding cmd.exe completely (and even if you needed to use the cmd.exe, you should pass plink.exe to it on a command-line: /c path\plink.exe). And no, running it directly would not cause Plink to close instantly.
Calling WaitForExit() without reading the redirected output will deadlock your code once an output buffer fills. See Remarks section for ProcessStartInfo.RedirectStandardOutput. Alternatively, use process.StandardOutput.ReadToEnd() (it's like WaitForExit, but also reads the output). It's actually what the MSDN recommends in the previous link.
If you are going to execute one command only, using Plink, it's also better to pass the command on Plink command-line, rather than "typing" it to its (redirected) input:
plink.exe -ssh user#host command
See also answer to Testing using Plink.exe to connect to SSH in C#
So I have a chunk of code to call powercfg with the /requests option and get the result back from stdout.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "powercfg";
p.StartInfo.Arguments = "/requests";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
However when I run this code I get entirely different output than when I run the same command on the command line.
In the case of the code version I only get a load of "[DRIVER] ?" values back, but on the command line I get usually 2 or 3 properly formed responses.
I've run my code from the same command prompt window as the same user with the same environment, still no joy.
Any ideas ?
So the actual reason was that my application needed to be compiled for "Any CPU". Setting it to x86 or x64 caused issues with it loading the correct version of one of the dependent libraries.
It may have something to do with the user context your application is running in, for example if you run your app as an administrator Process.Start will attempt to start the process in the same context.
I am trying to input console commands on a desktop app (through a text box) click a button, execute the command and get the returned values back for display.
The point is, I want to make my work faster and less stressful when trying to input repetitive commands on the console over and over again everyday.
I know some console application programming on C# and web applications(.NET, ADO.NET) on C# as well, but nothing about desktop applications. Any ideas?
The Process class can be used to start an application, and read it's output (from the standard output or standard error streams).
For example, to start a process, and read it's "output", you could use:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Foo.exe";
p.Start();
// Read the output
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
If you make a basic windows forms applications, you could store repetitive commands in a local file and have a mechanism to choose a command from this file in your application and run it. Windows forms shouldn't be too hard for you. it is just drag and drop.
I have a custom console command, which if executed in command prompt just displays some text in the command window (similar to 'dir' command).
I'm trying to execute the command 'myCommand' from a windows service and it is always returning blank string values. However, if run the same command in a command prompt, the result is displayed in the command window. Also, if I run the below code in a windows forms application, it works fine and I get the same data which is displayed in the command screen to a string variable.
Where am I going wrong? Why is the code returning a blank string when I execute it from a windows service, where as it works in a forms application. Is there any other method to capture the result of a command to a string variable in a windows service? Please advise. Thank you.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c myCommand");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
Attach the Visual Studio debugger to your running service (Debug menu, Attach to Process), put a breakpoint in the code where you execute the the command, and then execute the comand. This will enable you to debug the problem. If necessary, you can call the System.Diagnostics.Debugger.Break method in your service to force it to break into the debugger at the appropriate point, without having to attach the debugger first.
Edit:
I suggest you also capture the standard error stream:
procStartInfo.RedirectStandardError = true;
...
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
Check what you get in the error string. I use WaitForExit to wait until the command exits too.
You are not setting the working Directory (ie procStartInfo.WorkingDirectory), so if the system can not find 'myCommand' , you will get this result.
Even if 'myCommand' is in the same directory as your service exe file, that does not normally work as the working directory for a service is normally windows\system32.
I preferred this Easier way to debug a C# Windows Service
I added the conditional If to launch the debugger from the OnStart method, then put a breakpoint in my OnCustomCommand(int command) method.