Okay, so I've been working on this a while (and I've gone through multiple questions to get this far in the project).
Here's the C# code I'm using:
Process p = new Process();
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "javac";
Directory.CreateDirectory(Path.Combine(Application.StartupPath + #"\TempJavaalfgwaepfgawe"));
p.StartInfo.Arguments = "-d " + Path.Combine(Application.StartupPath + #"\TempJavaalfgwaepfgawe") + " " + files;
p.Start();
p.WaitForExit();
MessageBox.Show(p.StandardError.ReadToEnd());
In essence, I am trying to invoke the Java compiler (javac) from a C# application.
Now, when I do this, it wasn't compiling the java code correctly, so I inserted the RedirectStandardError and UseShellExecute as well as the WaitForExit and MessageBox at the end to see the error that was occurring.
Anyways, the error is as follows:
javac: invalid flag: 2010\Projects\Java
Usage: javac [options] [source files]
use -help for a list of possible options
So, what's wrong with my code?
To me, the error looks like part of the location of one of the file paths.
I suggested the fix in the comments, but I also wanted to add a formal answer for others with this problem.
When you pass in arguments to a process, strings that have spaces need to be quoted. This tells the argument parser that you really mean one argument. (different arguments are usually divided by white space)
Related
At work we have a large number of on-site WES09 machines that are doing controls data gathering. Because we have thousands of these, upgrades are a pain. I have been slowly evolving a better process, and am currently working on a C# application to better manage these.
The machines are running File Based Write Filter, which has the effect that if PSEXEC had not been run on the machine before, it won't let it start. So I use WMIC to disable FBWF.
I am trying to add a status feature to see if FBWF is enabled, as I haven't always had 100% success with WMIC. Anyway, FBWF gives status output in the command window, but it's multiple lines. It seems when I use StandardOutput.ReadToEnd, it only gets the first line.
So here is what it looks like when you check FBWF status from PSEXEC:
FBWFOutput
When I run the C# Application I wrote, the output only gets this:
"\r\nPsExec v2.2 - Execute processes remotely\r\nCopyright (C)
2001-2016 Mark Russinovich\r\nSysinternals -
www.sysinternals.com\r\n\r\nFile-based write filter configuration for
the current session:\r\n"
I don't know why it stops there, I can't get the rest of it that actually says if it is enabled or not (which is the next line, of course).
Here is the relevant code piece, leaving out IP/User/Pass:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = #"C:\temp\PSTools\PsExec.exe";
p.StartInfo.Arguments = #"\\" + RemotePCName + " -u " + Username + " -p " + Password + " fbwfmgr";
p.Start();
string output = p.StandardOutput.ReadToEnd();
string errormessage = p.StandardError.ReadToEnd();
I thought my issue might be the line break, but there looks to be two between the PsExec portion and the FBWF output, but otherwise am not sure what else to try. I spent a couple hours looking through other comments on issues with getting the output, but almost all were that the application would hang which is not an issue I am having.
Thank you in advance for the assistance, I am slowly learning C# and programming in general and this community has been a huge help!
So im trying to make a ip pinger to see if a server is online and have got this so far i would like it so that the user can in put a ip on there own from a text box. but keep getting a error on the start part.
Error CS1501 No overload for method 'Start' takes 3 arguments
System.Diagnostics.Process.Start ("cmd", "/k ping" + flatTextBox1.Text ,"-t");
I see several issues here:
First, the "-t" is used as third parameter because of the comma before it. You should add it to the string you're building with "/k" in combination with the IP address.
Next, given the textbox text is "127.0.0.1" this will currently end up as: /k ping127.0.0.1
So you might just add a space in between the "ping" and the IP.
BUT: you should not use cmd.exe for this, consider to use the Ping class from the .NET framework.
Try using ProcessStartInfo:
ProcessStartInfo startInfo = new ProcessStartInfo("cmd");
startInfo.Arguments = "/k ping " + flatTextBox1.Text + " -t";
Process.Start(startInfo);
I'm trying to run a fortran executable with Process.Start and it is not working.
Process proc = new Process();
string args = "<C:\\file.in> C:\\file.out";
proc.StartInfo = new ProcessStartInfo(AppName, args);
proc.Start();
if I paste those arguments into a command window the application runs as expected. proc.Start() does not run as expected.
Any ideas how I can view what Start is actually passing as arguments? My gut feeling is that this is a quotes issue.
The executable launches and hangs, so I'm confident the AppName is getting passed in correctly, it looks like an argument problem.
I tried setting the WorkingDirectory to that of the input and output files as suggested in this question: process.start() arguments but that did not work.
Redirection with the < and > command line operators is a feature that's implemented by the command line processor. Which is cmd.exe. Use its /c argument to execute just a single command:
string args = "/c " + AppName + " < C:\\file.in > C:\\file.out";
proc.StartInfo = new ProcessStartInfo("cmd.exe", args);
proc.Start();
Your args string is exactly what is being passed as arguments to the executable. You can double check it reading your Process ProcessStartInfo.Arguments Property.
Something similar happened to me once, i.e., calling the executable from the command line worked and from code didn't, and it turned out that when called from the command line the executable was running on my PC's [C:] drive, and when called from code it was running on my PC's [E:] drive, which was full!
To check which directory your application is using to run the executable use the Directory.GetCurrentDirectory Method.
I found the following snippet of the code:
using System;
using System.Diagnostics;
public class RedirectingProcessOutput
{
public static void Main()
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c dir *.cs";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine("Output:");
Console.WriteLine(output);
}
}
but I can't figure out what this p.StartInfo.Arguments = "/c dir *.cs"; is doing? thanks in advance for any explanation
It's passing command line arguments to the process that will be launched.
In this particular case, the process is the Windows shell (cmd.exe). Passing a command line to it will cause it to execute this command when started; then, because of the /c parameter at the beginning it will terminate itself.
So the output of the process will be exactly what you will get if you open a command prompt and enter the command dir *.cs.
In the beginning was exec(3) and its friends, which accept the path to an executable and a variable length list of pointers to arguments. In sane operating systems, The process that gets started receives a point to the argument list, each word of which contains a pointer to and individual string. Sane shells parse the command line and populate the argument list required by exec(3).
You can see a direct correlation between the argument list accepted by exec(3):
exec ("some.executable.file", "arg1" , "arg2" , "arg3" , ... ) ;
and what gets passed to the entrypoint of the process:
int main ( char *arg[] ) { ... }
where argv[0] is the executable name, and argv[1]—argv[n-2] are the individual arguments, and argv[n-1] is a NULL pointer to indicate the end of the argument list.
Both conceptually simple and simple to implement.
CP/M didn't do it that way (I assume because of limited memory). It passed the started process the address of the raw command line from the shell and left its parsing up the process.
DOS followed in 1982 as clone of CP/M, handing a started process the address of the raw command line as well.
Windows hasn't deviated from that model since its inception. The Win32 CreateProcess() function
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
...
);
still does the same thing, passing the raw command line to be passed to the program. The C runtime library, of course, takes care of the command line parsing for you...more or less.
So...in the CLR/.Net world, because of all this history, and because the CLR was designed to be dependent on the Win32 APIs, you have pass a complete command line to the process to be started. Why they didn't let you pass a params string[], instead and have the CLR build the command line is something that Microsoft's developers kept close to their chest.
Building the command line required by the started program is simple. You just join each argument into a single string with an SP character separating the arguments. Easy!
...until one of your arguments contains whitespace or a double quote character (").
Then you have to quote one or all of the arguments. Should be easy, but due to the bizarre quote rules, there are a lot of edge conditions that can trip you up.
A Windows command-line is broken up into words separated by whitespace, optionally quoted with double-quoted ("). Partly because Windows also got the path separater wrong (\ rather than /), the quoting rules are...byzantine. If you dig into the Windows CRT source code (the file is something like {VisualStudioInstallLocation}\VC\crt\src\stdargv.c), you'll find the command line parsing code.
That line just gives an argument to that proccess.
I am scratching my head with this one. I am trying to run an exe from C# using system.diagnostics but it isnt passing over my arguments correctly so the exe falls over.
It splits the path after the word 'here' (see below) because of the space in it.
Does anyone know how I can get round this without renaming the directory (which isn't an option for me)
This works from command line:
"C:\Users\me\Desktop\myexternalexe\myexternalexe.exe" comments “\192.168.1.1\a\here is the problem\c\d\"
This doesn't from with in Visual Studio:
Process myexternalexe = new Process();
myexternalexe.StartInfo.FileName = #"C:\Users\me\Desktop\myexternalexe\myexternalexe.exe";
myexternalexe.StartInfo.Arguments = #"comments \\192.168.1.1\a\here is the problem\c\d\";
myexternalexe.Start();
But you've omitted the quotes from the C# version. It should be:
myexternalexe.StartInfo.Arguments = #"comments ""\\192.168.1.1\a\here is the problem\c\d\""";
Did you checked
this
In your case following should work.
string folderName = #"\\192.168.1.1\a\here is the problem\c\d\";
myexternalexe.StartInfo.Arguments= #"comments" + " \"" + folderName +"\"";
Have you tried:
alexe.StartInfo.Arguments = "comments \"\\\\192.168.1.1\\a\\here is the problem\\c\\d\\\"";