Using C#, I am trying to pass command-line arguments to a new process using Process.Start():
string path = @"C:\Demo\Demo.exe";
string arguments = "one two three";
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = path,
Arguments = arguments
};
var process = Process.Start(startInfo);
My C application Demo.exe just echos the command line arguments:
int main( int argc, char *argv[] )
{
int count=0;
// Display each command-line argument.
printf( "\nCommand-line arguments:\n" );
for( count = 0; count < argc; count++ )
printf( " argv[%d] %s\n", count, argv[count] );
while(1);
}
If I start my application from cmd.exe, I get reasonable output:
Command-line arguments:
argv[0] Demo.exe
argv[1] one
argv[2] two
argv[3] three
When I use the C# application, the only thing I get is the path argument at argv[0]:
Command-line arguments:
argv[0] C:
Task Manager shows command line arguments for each method of starting Demo.exe:
Why isn't my C application receiving the command-line arguments from the C# application?
Edit @hvd suggested I use GetCommandLine(). Here is the code and result of that:
char* ar = GetCommandLine();
printf( "\nGetCommandLine arguments:\n" );
printf(" %s", ar);
Output:
GetCommandLine arguments:
"C:
Is it possible that the C app is receiving the args as one string, but ignores everything after the first \ in the path?
Edit: I've added an answer below. It is a workaround, but I'm not sure the cause of my issue.
I've gotten back to this today and have a workaround working. I don't understand why my original attempt didn't work.
Here is the difference on the command line between typing Demo.exe and “Demo.exe.”
C:\Users\me\Desktop\Work\Builds\Win32>Demo.exe one two three
There are 4 arguments.
Command-line arguments:
argv[0]: Demo.exe
argv[1]: one
argv[2]: two
argv[3]: three
C:\Users\me\Desktop\Work\Builds\Win32>"Demo.exe" one two three
There are 1 arguments.
Command-line arguments:
argv[0]: Demo.exe
The Process.Start() call seemed to be doing the “Demo.exe” variety.
Doesn’t work:
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = @"Demo.exe",
WorkingDirectory = @"C:\Users\me\Desktop\Work\Builds\Win32",
Arguments = "one two three"
};
var process = Process.Start(startInfo);
There are 1 arguments.
Command-line arguments:
argv[0]: C:
Does work:
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
WorkingDirectory = @"C:\Users\me\Desktop\Work\Builds\Win32",
Arguments = "/C Demo.exe one two three"
};
var process = Process.Start(startInfo);
There are 4 arguments.
Command-line arguments:
argv[0]: Demo.exe
argv[1]: one
argv[2]: two
argv[3]: three
Does anyone have any ideas why the first method doesn't work?
I was able to reproduce your issue. I didn't have access to C, so I used C++ in Visual Studio 2013. It appears that C# using StartInfo passes the arguments as Unicode characters, so the first byte is non-zero, while the 2nd byte is likely 0 bits resulting in displaying only the first character since that indicates the string termination character. When I used printf it did not work, I had to use _tprintf to see what is passed. And printf does not handle Unicode. Not only does printf not handle it, your C program when populating argv will not translate Unicode to a string using 1 byte characters. While TCHAR (wide char) and tprintf in C++ does, as does C# natively.
So, when you did it the other way, using "cmd.exe" to call "/C Demo.exe one two three" cmd was not passing the string as Unicode. That's my hypothesis, given the results I am getting.
Related Question on StackOverflow
The C++ code that displayed the Arguments correctly (tprintf) and incorrectly (printf)
#include "stdafx.h"
#include "string.h"
int _tmain(int argc, _TCHAR* argv[])
{
int count=0;
// Display each command-line argument.
printf( "\nCommand-line arguments:\n" );
for( count = 0; count < argc; count++ )
//Correct. This statement worked, displaying the arguments
//_tprintf( _T(" argv[%d] %s\n"), count, argv[count] );
//Incorrect. Displayed only the first character of each argument
//printf( " argv[%d] %s\n", count, argv[count] );
getchar();
return 0;
}
This is the C# code that called it
namespace ProcessPassArguments
{
class Program
{
static void Main(string[] args)
{
string path = @"C:\Temp\Demo.exe";
string arguments = "one two three";
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = path,
Arguments = arguments
};
var process = Process.Start(startInfo);
}
}
}
For informational purposes only, C# calling the C# also worked. Again the suspected cause is that C# is passing the arguments to your C program as Unicode Characters.
The C# code that works as the target programmed called.
namespace Demo
{
class Program
{
static void Main(string[] args)
{
int i = 0;
foreach (string arg in args)
{
i++;
Console.WriteLine("Argument {0}: {1}", i, arg);
}
Console.ReadLine();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With