使用相同的参数启动程序的第二个副本

本文关键字:程序 第二个 副本 启动 参数 | 更新日期: 2023-09-27 18:36:12

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

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

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 或为参数获取字符串数组?

使用相同的参数启动程序的第二个副本

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

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,这都可以工作。

好的,

我想这应该可以工作。

[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

这就

足够了吗?

static void Main(string[] args)
{
    string commandLineArgs = args.Join(" ");
}