Приложение, запущенное Process.Start(), не получает аргументов

Используя С#, я пытаюсь передать аргументы командной строки новому процессу с помощью 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);

Мое приложение C Demo.exe просто перефразирует аргументы командной строки:

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);
}

Если я запускаю свое приложение из cmd.exe, я получаю разумный вывод:

Command-line arguments:
 argv[0]   Demo.exe
 argv[1]   one
 argv[2]   two
 argv[3]   three

Когда я использую приложение С#, единственное, что я получаю, это аргумент path в argv [0]:

Command-line arguments:
  argv[0]   C:

Диспетчер задач показывает аргументы командной строки для каждого метода запуска Demo.exe: enter image description here

Почему приложение C не получает аргументы командной строки из приложения С#?

Edit @hvd предложил использовать GetCommandLine(). Вот код и результат:

char* ar = GetCommandLine();
printf( "\nGetCommandLine arguments:\n" );
printf("  %s", ar);

Вывод:

GetCommandLine arguments:
  "C:

Возможно ли, что приложение C получает аргументы как одну строку, но игнорирует все после первого\в пути?

Изменить: я добавил ответ ниже. Это обходной путь, но я не уверен в причине моей проблемы.

Ответы

Ответ 1

Я смог воспроизвести вашу проблему. У меня не было доступа к C, поэтому я использовал C++ в Visual Studio 2013. Похоже, что С# с использованием StartInfo передает аргументы в виде символов Unicode, поэтому первый байт отличен от нуля, тогда как 2-й байт, скорее всего, 0 бит в результате отображается только первый символ, так как это указывает на символ окончания строки. Когда я использовал printf, это не сработало, мне пришлось использовать _tprintf, чтобы узнать, что передано. И printf не обрабатывает Unicode. Мало того, что printf не обрабатывает его, ваша программа C при заполнении argv не переводит Unicode в строку с использованием 1 байтового символа. Хотя TCHAR (широкий символ) и tprintf в C++, как и С# изначально.

Итак, когда вы сделали это другим способом, используя "cmd.exe" для вызова "/C Demo.exe один два три", cmd не передавал строку как Unicode. Это моя гипотеза, учитывая результаты, которые я получаю.

Связанный вопрос о StackOverflow

Код C++, который правильно отображал аргументы (tprintf) и неверно (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;

}

Это код С#, который вызвал его

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);
        }
    }
}

Только для информационных целей, С#, вызывающий С#, также работал. Опять же, подозреваемая причина заключается в том, что С# передает аргументы вашей программе на C как символы Unicode.

Код С#, который работает как запрограммированный вызов.

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();
        }

    }
}

Ответ 2

Я вернулся к этому сегодня, и у меня есть обходной путь. Я не понимаю, почему моя первоначальная попытка не сработала.

Вот разница в командной строке между типизацией Demo.exe и "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

Вызов Process.Start(), казалось, делал многообразие "Demo.exe".

Не работает:

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:

Работает:

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

У кого-нибудь есть идеи, почему первый метод не работает?

Ответ 3

Попробуй это

Arguments = "\"arg1\" \"arg2\" \"arg3\"";