Process.Start()启动的应用程序没有获取到参数。

13
使用C#,我正在尝试使用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

当我使用C#应用程序时,我只能在argv[0]处得到路径参数:

Command-line arguments:
  argv[0]   C:

任务管理器显示每种启动Demo.exe方法的命令行参数: enter image description here

为什么我的C应用程序没有接收到来自C#应用程序的命令行参数?

编辑 @hvd建议我使用GetCommandLine()。这里是那段代码和结果:

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

输出:

GetCommandLine arguments:
  "C:

这个C应用程序是否可能将参数作为一个字符串接收,但忽略路径中第一个反斜杠之后的所有内容?

编辑:我在下面添加了一个答案。 这是一个解决方法,但我不确定我的问题的原因。


2
请展示你的C#代码。 - Jon Skeet
@JonSkeet,C# 代码在上面的第一个代码框中。您还想看什么? - GreenRibbon
1
感谢您在这个问题中提供了丰富的信息,这些信息可以用来找到问题所在。 - usr
1
当您使用cmd.exe运行进程时,您是否与C#应用程序中的应用程序路径位于同一目录中?我有一种感觉,您的C#应用程序无法看到或读取c:\ Demo目录。 - Bit
1
我首先使用了你的代码启动了一个C#控制台应用程序,并且正确显示了参数。然后我使用了一个C++控制台应用程序,但它只显示了每个参数的第一个字母,就像你在调用GetCommandLine()时的"C"一样。然后我意识到这可能是某种Unicode问题,所以我将我的C++从printf更改为_tprintf以正确显示数组中的Unicode,这时它对我起作用了。似乎当你使用printf时,它读取第一个字节并显示正确的第一个字符,但下一个字节是0(UTF),所以它认为这是字符串的结尾,因为0是空值。 - CodeCowboyOrg
显示剩余10条评论
3个回答

5

今天我回来了,已经有一个可行的解决方案。我不明白为什么我的原始尝试没有成功。

在命令行中输入 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

有人有什么想法为什么第一种方法不起作用吗?


不知道为什么你的第三个解决方案有效,但它确实有效...调用cmd.exe并传递/C somefile.exe somearguments对我也有效。 - Gerhard Schreurs

4
我能够重现您的问题。由于我没有访问C,所以我在Visual Studio 2013中使用了C++。看起来C#使用StartInfo将参数传递为Unicode字符,因此第一个字节不为零,而第二个字节很可能是0位,结果仅显示第一个字符,因为它表示字符串终止字符。当我使用printf时无法工作,我必须使用_tprintf才能查看传递的内容。而printf不处理Unicode。不仅如此,您的C程序在填充argv时也不会将Unicode转换为使用1字节字符的字符串。而TCHAR(宽字符)和C ++中的tprintf以及C#本地支持。
因此,当您以另一种方式执行时,使用"cmd.exe"调用"/C Demo.exe one two three" 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;
}

以下是调用它的C#代码:

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# 调用 C# 也是可以工作的。再次怀疑的原因是 C# 将参数作为 Unicode 字符传递给您的 C 程序。

目标编程调用的 C# 代码是有效的。

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

    }
}

-1

试试这个

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接