6

应用程序使用相同参数重新启动自身的另一个副本的正确方法是什么?

我目前的方法是执行以下操作

static void Main()
{
    Console.WriteLine("Start New Copy");
    Console.ReadLine();

    string[] args = Environment.GetCommandLineArgs();

    //Will not work if using vshost, uncomment the next line to fix that issue.
    //args[0] = Regex.Replace(args[0], "\\.vshost\\.exe$", ".exe");

    //Put quotes around arguments that contain spaces.
    for (int i = 1; i < args.Length; i++)
    {
        if (args[i].Contains(' '))
            args[i] = String.Concat('"', args[i], '"');
    }

    //Combine the arguments in to one string
    string joinedArgs = string.Empty;
    if (args.Length > 1)
        joinedArgs = string.Join(" ", args, 1, args.Length - 1);

    //Start the new process
    Process.Start(args[0], joinedArgs);
}

然而,那里似乎有很多忙碌的工作。忽略 vshost 的条带化,我仍然需要将带有空格"的参数包装起来,并将参数数组组合成一个字符串。

有没有更好的方法来启动程序的新副本(包括相同的参数),也许只需要传入Enviroment.CommandLine或使用字符串数组作为参数?

4

3 回答 3

3

您必须引用包含空格(可能还有其他字符,我不确定)的命令行参数。也许是这样的:

var commandLine = string.Join(" ", args.Select(s => s.Contains(' ') ? "\"" + s + "\"" : s));
var newProcess = Process.Start("yourapplication.exe", commandLine);

此外,而不是使用

string[] args = Environment.GetCommandLineArgs();

您可以在您的Main方法中接受它们:

public static void Main(string[] args)
{
    var commandLine = string.Join(" ", args.Select(s => s.Contains(' ') ? "\"" + s + "\"" : s));
    var newProcess = Process.Start(Environment.GetCommandLineArgs()[0], commandLine);
}

您现在拥有的 vshost 解决方法似乎很好,或者您可以通过取消选中项目调试选项卡上的“启用 Visual Studio 托管进程”来禁用整个 vshost。当你这样做时,某些调试功能确实会被禁用。是一个很好的解释。

编辑

解决它的更好方法是将代码库获取到入口点程序集:

public static void Main(string[] args)
{
    var imagePath = Assembly.GetEntryAssembly().CodeBase;
    var commandLine = string.Join(" ", args.Select(s => s.Contains(' ') ? "\"" + s + "\"" : s));
    var newProcess = Process.Start(imagePath, commandLine);
}

无论是否启用 vshost,这都可以使用。

于 2012-06-01T17:28:11.970 回答
1

好的,我猜这应该可行。

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern System.IntPtr GetCommandLine();
static void Main(string[] args)
{
  System.IntPtr ptr = GetCommandLine();
  string commandLine = Marshal.PtrToStringAuto(ptr); 
  string arguments = commandLine.Substring(commandLine.IndexOf("\"", 1) + 2);
  Console.WriteLine(arguments);
  Process.Start(Assembly.GetEntryAssembly().Location, arguments);
}

参考: http: //pinvoke.net/default.aspx/kernel32/GetCommandLine.html

于 2012-06-01T17:37:49.197 回答
-1

这足够了吗?

static void Main(string[] args)
{
    string commandLineArgs = args.Join(" ");
}
于 2012-06-01T17:07:42.837 回答