Issue when passing multiple arguments to an external exe program using c# - c#

I have an exe file in which I am trying to pass arguments through c#. the code is as follows
class Class1
{
static void Main()
{
string[] arg;
arg = new string[3];
Process p = new Process();
p.StartInfo.FileName = #"D:\xxx.exe";
for (int i = 0; i < 3; i++)
{
arg[i] = Console.ReadLine();
}
p.StartInfo.Arguments = arg[0] + " " + arg[1] + " " + arg[2];
p.Start();
}
}
I open up a console and then write the arguments there. As soon as I am finished typing 3 arguments, I make a string out of the 3 arguments and then call Process.Start() with the arguments in the p.StartInfo.Arguments string. The exe file loads but it does not generate any output. The strange thing is that if I open the exe file from my computer and then write
Arg1.txt Arg2.txt Arg3.txt
and press enter the exe file generates the output. However the same arguments in the same style are currently being passed through C# code and it is not generating any output. I donot understand what I am doing wrong. There are multiple questions on StackOverflow about this, I know that, however they all suggest the same procedure as what I have done here. I have also tried giving arguments as
p.StartInfo.Arguments = "\"arg[0]\"\"arg[1]\"\"arg[2]\"";
but this also has not worked.

Try this:
p.StartInfo.Arguments = "\"" + arg[0] + " " + arg[1] + " " + arg[2] + "\"";
p.Start();
It is recomended to use "" when you use several parameters between gaps.
EDIT: No "\" have to be included if you type it ok. It is the escape character. See picture below.

Related

How should I format a string when passing multiple arguments to Process.Start when part of the string is a var

I am trying to pass 2 arguments to the Process.start in c# and part of the string has to be a string var that is built from the input of the user.
This code works fine when I use a simple folder path but my path is determined by the user to the process.StartInfo.Arguments must = "-format mp4 -outfolder " + myVar.
I cannot get this to work.
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files (x86)\NCH Software\Prism\Prism.exe";
process.StartInfo.Arguments = "-format mp4 -outfolder C:/users/john";
process.Start();
The expected results would be the prism opening screen having the mp4 format automatically selected (which works fine) and the output folder is set by the variable. that part of the argument is being ignored and a default folder is being set up.
I think in your case you have to use \" \" between the var.
process.StartInfo.Arguments = "-format mp4 -outfolder #\" " + myVar + "\""
Follow this site and you can find more information.
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.arguments?view=netframework-4.8
or else try,
string a = "aaa";
string b = "bbb";
Process.Start(#"something.exe ", "#"+ a + " " + b );

SCHTASKS Invalid Syntax in C# but working in CMD

I've got a command I'm trying to run through C# to get a list of tasks in CSV format from a bunch of computers.
To do this, I am using the SCHTASKS command with command redirection to a CSV. So I wrote this code in C# to do this for me:
string commandGetStatus = "schtasks";
string argumentsGetStatus = "/s:" + CompName +
" /fo:csv" +
" > \"" + #"\\BIG\OL\UNC\PATH\"+CompName+".csv" + "\"";
getLatestTaskStatus.StartInfo.FileName = commandGetStatus;
getLatestTaskStatus.StartInfo.Arguments = argumentsGetStatus;
getLatestTaskStatus.StartInfo.CreateNoWindow = true;
getLatestTaskStatus.StartInfo.RedirectStandardOutput = true;
getLatestTaskStatus.StartInfo.RedirectStandardInput = true;
getLatestTaskStatus.StartInfo.RedirectStandardError = true;
getLatestTaskStatus.StartInfo.UseShellExecute = false;
getLatestTaskStatus.Start();
It returns the output:
ERROR: Invalid syntax.
Type "SCHTASKS /?" for usage.
So I used StartInfo.FileName + " " + StartInfo.Arguments to print out the exact command that should be being executed. From there, I copy and pasted the command into CMD. Where it worked without a problem. This was the command + args:
schtasks /s:COMPUTERNAME /fo:csv > "\\BIG\OL\UNC\PATH\COMPUTERNAME.csv"
I'm not sure what the problem is at this point.
My Solution
Luaan was absolutely correct about the problem. The command prompt redirection operator,>, is not available without using Command Prompt. Fortunately, the solution was quote simple and easy to implement. I reduced the argument variable to:
"/s:" + CompName + " /fo:csv"
And with standard output being redirected, I simply used:
string output = process.StandardOuptut.ReadToEnd();
File.WriteAllText(#"\\UNC\File\Path\" + myfile + ".csv", output);
You explicitly disabled UseShellExecute - > is a shell operator, not something inherent to processes. It definitely isn't an argument. You need to read the output and write it out manually :)

Process.Start not executing command

I am using ImageMagick C# tool to convert PDF to JPG by calling the executable from C#. I believe I set up the command correctly but it does not execute; it just passes through Process.Start(startInfo) without executing it. I do see the command prompt popping up but nothing happens.
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe");
startInfo.Arguments = arguments;
Process.Start(startInfo);
I wasn't sure if it was because of the double quotes I added to each argument before hand but after commenting it out and running it again, it still skipped over. Any thoughts?
Edit: To add some clarity, I am expecting a JPG files from a PDF but I see no output file from this part of code. I ran the following in my command prompt to convert PDF to JPG
"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.PDF" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.png"
I explicitly called the convert.exe for clarity sake in my code. The command works fine in command prompt but when coping the structure over to C# it doesn't do anything. I see the code step into it but it continues without an error.
Edit2: Upon request below is the code and output for a Process Exit code
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
try
{
Process myprocess = null;
string[] arguments = { PDFfile, PNGfile };
myprocess=Process.Start(#"C:\ProgramFiles\ImageMagick6.9.2Q16\convert.exe", String.Join(" ", arguments));
Console.WriteLine("Process exit code: {0}", myprocess.ExitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Process exit code: 1
Assuming that you are right and there was a problem (rather than the process just executed very quickly and exited), you can check the return code as follows:
if (Process.Start(startInfo) == null)
{
int lastError = Marshal.GetLastWin32Error();
}
You then go here to look up the error code:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
Hopefully, that vendor actually sets an error code on failure (they may or may not).

How to rar/unrar with command line parameters

I've looked through the internet on how winrar's command line parameters work, and this is what I have so far
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "rar a -p" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}
void UNLOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "unrar x -p" + pw + " PL_LOCKED_ARCHIVE.rar";
p.Start();
}
However it doesn't seem to create any archive anywhere, with a test folder being C:\PicsAndStuff
The StartInfo you define results in running WinRAR.exe with command line:
C:\Program Files\WinRAR\WinRAR.exe unrar x -p pw PL_LOCKED_ARCHIVE.rar
That is of course wrong as you do not want to run WinRAR.exe with first argument being a reference to console version Rar.exe or UnRAR.exe. The result is most likely an error message because of invalid command rar respectively unrar as the first argument must be a or x for WinRAR.exe.
So first of all you need to correct StartInfo:
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\Rar.exe";
p.StartInfo.Arguments = "a -p" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}
void UNLOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\UnRAR.exe";
p.StartInfo.Arguments = "x -p" + pw + " PL_LOCKED_ARCHIVE.rar";
p.Start();
}
Further all commands and switches of console version Rar.exe are briefly explained when simply running Rar.exe without any parameter in a command prompt window. Also UnRAR.exe outputs a brief help if executed without any parameter.
Last but not least there is a complete manual for Rar.exe which of course can also extract files and folders from a RAR archive which makes additional usage of UnRAR.exe useless. The manual is text file Rar.txt in program files folder of WinRAR which you should read from top to bottom. I suggest to build the command line while reading it and test the command line first from within a command prompt window.
Note 1:
Rar.exe is shareware. Only UnRAR.exe is freeware.
Note 2:
GUI version WinRAR.exe supports more than console version Rar.exe and therefore the list of switches differ slightly. Complete documentation for WinRAR.exe can be found in help of WinRAR opened with Help - Help Topics or pressing key F1. Open in help on tab Contents the item Command line mode and read. WinRAR.exe is also shareware.
You need to encrypt both file data and headers.
According to Documentation (Command line mode > Switches > "-hp[pwd] - encrypt both file data and headers"):
This switch is similar to -p[p], but switch -p encrypts only file data
and leaves other information like file names visible. This switch
encrypts all sensitive archive areas including file data, file names,
sizes, attributes, comments and other blocks, so it provides a higher
security level.
This is how you can access to it using command line:
Syntax: rar a -hp[MyPassword] -r [filepath] [folderpath]
"C:\Program Files\WinRAR\WinRAR.exe" a -hp12345678 -r d:\zipProject d:\Project
C# Code:
void LOCK(string fld, string pw)
{
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\WinRAR\WinRAR.exe";
p.StartInfo.Arguments = "rar a -hp" + pw + " PL_LOCKED_ARCHIVE.rar " + fld;
p.Start();
}

Netstat focus on (find port)

Im recently trying to execute the following line ;
string strCmdText;
strCmdText = "netstat -np TCP | find " + quote + number + quote + "";
System.Diagnostics.Process.Start("netstat.exe", strCmdText);
Logs.Write("LISTEN_TO(" + Registry_val1.Text + ")", strCmdText);
now what this has to do is basicly find all TCP ports that contain '80' in them and show them up in my custom-made log system that will make a logbook in my folder called;
LISTEN_TO(80)-{date_time}.txt
inside this .txt it should contain the command issued text, however all i get is a time.
i debugged this command as above, and unfortunately all i know is that the CMDtext is set correctly, and that my logging system works correctly, leaving me with no choice that NETSTAT may be closed as soon as the query is launched?
hopefully i provided anough information, as this is my first post.
Regards,
Co
Due to vague description, here's an other-sort same code i tried to do, however still remain getting only a time.
const string quote = "\"";
Process p = new Process();
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments = "netstat -np TCP | find " + quote + number + quote + "";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
String output = p.StandardOutput.ReadToEnd();
Logs.Write("LISTEN_TO(" + Registry_val1.Text + ")", output);
basicly, you could see this as; textbox1.text = output; execpt now the output is being putten to a log file.
I don't understand why you use netstat in the first place. The .Net framework has a load of classes that give all kind of data, in this case IPGlobalProperties has the method you need.
var ip = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
foreach(var tcp in ip.GetActiveTcpConnections()) // alternative: ip.GetActiveTcpListeners()
{
if (tcp.LocalEndPoint.Port == number
|| tcp.RemoteEndPoint.Port == number)
{
Logs.Write(
String.Format(
"{0} : {1}",
tcp.LocalEndPoint.Address,
tcp.RemoteEndPoint.Address));
}
}
The benefit of using the build-in classes is the ease of shaping and selecting whatever you need and most important: you spare yourself and your user an out-of-process call and parsing of output.
You may try this:
strCmdText = "cmd /c \"netstat -np TCP | find " + quote + number + quote + "\"";
if this does not work, try first to use the command in a cmd prompt to make sure it returns data.
cmd /c "netstat -an | find "80"

Categories