What is the correct way for a application to restart another copy of itself with the same arguments?
My current method is to do the following
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);
}
However it seems like there is a lot of busy work in there. Ignoring the striping of the vshost, I still need to wrap arguments that have spaces with "
and combine the array of arguments in to a single string.
Is there a better way to launch a new copy of the program (including the same arguments), perhaps a way just needing to pass in Enviroment.CommandLine or takes a string array for the arguments?
You would have to quote command line arguments that contain spaces (and perhaps other characters, that I am not sure of). Perhaps something like this:
var commandLine = string.Join(" ", args.Select(s => s.Contains(' ') ? "\"" + s + "\"" : s));
var newProcess = Process.Start("yourapplication.exe", commandLine);
Additionally, rather than using
string[] args = Environment.GetCommandLineArgs();
You could just accept them in your Main
method instead:
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);
}
The vshost workaround you have right now seems fine, alternatively you could disable the whole vshost thing by unchecking "Enable Visual Studio hosting process" on the debug tab of your project. Some debugging features do get disabled when do you that. Here is a good explanation of that.
EDIT:
A better way to work around it would be to get the codebase to the entry point assembly:
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);
}
That will work with or without the vshost enabled.
Ok this should work I guess.
[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);
}
Reference: http://pinvoke.net/default.aspx/kernel32/GetCommandLine.html
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