2012-06-01 4 views
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 или принимает строковый массив для аргументов?

+1

Aww, .NET, вилка бомба, как мило :) – Codeman

+1

@ Pheonixblade9 Существует причина, я положил 'Console.ReadLine()' в :) –

+1

Смотрите HTTP://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx о объединении проанализированных аргументов командной строки в одну строку. Более короткая версия: это сложнее, чем '' '' + arg + '"''. –

ответ

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 временное решение вы сейчас кажется отлично, иначе вы можете отключить всю вещь vshost, сняв флажок «Включить процесс хостинга Visual Studio» на вкладке отладки вашего проекта. Некоторые функции отладки отключены, когда вы это делаете. Here - хорошее объяснение этого.

EDIT:

Лучший способ обойти это было бы, чтобы получить кодовую к точке входа сборки:

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 включен.

+0

+1 для упоминания опции «Включить хостинг Visual Studio». Мне это нравится намного лучше, чем пытаться взломать его в коде. – jnylen

+0

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

+0

@ScottChamberlain Добавлена ​​еще одна альтернатива, позволяющая избежать проблемы vshost. – vcsjones

-1

этого достаточно?

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

Нет, проверьте это с помощью аргументов командной строки 'Это« некоторые аргументы ».« Ваш первый запуск будет «args [0] =« This »; args [1] = "is"; args [2] = "some args" ', но ваш seccond run будет' args [0] = "This"; args [1] = "is"; args [2] = «некоторые»; args [3] = "args" ' –

+0

Также вы не рассматриваете, как начать процесс вообще. Включите это и обработайте дополнительный аргумент, который вы создаете, и я удалю свой -1. –

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

+0

Это функция, о которой я думал, но не мог вспомнить имя. – jnylen

+1

Это более сложный способ сказать «Environment.CommandLine», и он не будет работать, потому что «Process.Start» ожидает имя файла и аргументы как два отдельных параметра. – vcsjones

+0

его не сложный способ его просто фактическая командная строка. Кстати, почему? обновил код, чтобы дать вам только аргументы. Вы также можете удалить текущий исполняемый exe-путь из командной строки, а не выражение подстроки, которое я использовал. –