2013-02-23 2 views
1

Я использую PowerShell v3.0 для запуска нового процесса cmd.exe, в котором я затем загружаю командную строку Visual Studio для выполнения сборки, например:Как получить вывод командной строки в переменную с помощью PowerShell

Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuildInVsCommandPrompt -WindowStyle $windowStyle -Wait 

Это работает, и это открывает новое окно командной строки, и я могу видеть сборки происходит, а потом, когда сборка закончена в окно командной строки закрывается. Я хотел бы получить текст, который записывается в окно командной строки, и хранить его в переменной, чтобы проверить, прошла ли сборка или нет. Я попытался использовать это, но это не сработает; переменная $ buildOutput пуст:

Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuildInVsCommandPrompt -WindowStyle $windowStyle -Wait -OutVariable buildOutput 
Write-Host "Build output = $buildOutput" 

Это имеет смысл, так как процесс cmd.exe не возвращает текст; он просто пишет это в свое окно. Есть ли способ для меня сохранить этот текст в переменной для исходного сценария powershell? Я знаю, что могу предоставить параметр MsBuild, чтобы он записывал журнал сборки в файл, но я ищу решение, которое не связано с записью в файл журнала и необходимостью его удалить позже.

Любые предложения приветствуются. Благодаря!

< # EDIT #>

Спасибо за все ответы до сих пор! Популярным предложением было просто вызвать MsBuild.exe напрямую, не используя cmd.exe. Причина, по которой мне нужно пройти через cmd.exe, - это некоторые проекты, которые не успешно создаются, если вызваны непосредственно из MsBuild.exe (например, проекты XNA). Вместо этого мне нужно вызвать MsBuild.exe из командной строки Visual Studio, чтобы (предположим) установить все необходимые переменные среды. Я думаю, я мог бы просто вызвать VS Command Prompt напрямую, но у него будет та же проблема, что и вызов cmd.exe. Если я не могу найти командную строку VS, я возвращаюсь к вызову MsBuild.exe напрямую, поэтому эти ответы по-прежнему оцениваются.

+1

Почему его нет написать в журнал? Вы можете использовать PowerShell, чтобы немедленно использовать файл журнала и удалить его для вас. – Matt

+2

Просто вызовите msbuild (или соответствующий исполняемый файл) напрямую и избегите 'cmd.exe'? Я не уверен, что «cmd.exe» имеет «stdout». Возможно, на это влияет флаг '/ c'? – 2013-02-23 00:22:33

+0

Вы можете запустить его как фоновое задание (используя cmd/c) и управлять отображением и окончательным отображением вывода с помощью задания-получателя. – mjolinor

ответ

3

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

Я создал модуль powershell для Invoke-MsBuild, чтобы сделать здание с MsBuild быстрым, предоставляя множество параметров для дополнительной функциональности (возвращается, если сборка выполнена успешно или неудачно, может показать/скрыть окно сборки, может ждать/не ждать построить для завершения, может автоматически показывать журнал сборки с ошибками сборки и т. д.). Вы можете view and download the script from my blog.

10

Вы всегда можете получить вывод консольных программ таким образом:

$output = [string](nuget.exe) 

Здесь я использовал NuGet ($ Результат будет содержать список доступных команд), но вы можете использования конечно MSBuild.exe с соответствующим аргументы.

+1

Это отличное решение, если я хочу запустить сборку в текущем процессе, но я искал ее запуск на новом процессе так что он появляется в собственном окне, и пользователи могут использовать PassThru, если они хотят, чтобы им не пришлось ждать завершения сборки до того, как их сценарий продолжит выполнение. Upvote хотя для полезного ответа :) – deadlydog

+0

Это именно то, что я искал. Исходя из названия вопроса, это отвечает на вопрос 100%. Понятно, что содержание вопроса меняет требования. Спасибо, что опубликовали этот ответ. –

2
$process = New-Object System.Diagnostics.Process; 
$process.StartInfo.UseShellExecute = $false; 
$process.StartInfo.RedirectStandardOutput = $true; 
$process.StartInfo.FileName = "cmd.exe"; 
$process.StartInfo.Arguments = $cmdArgumentsToRunMsBuildInVsCommandPrompt; 
$process.Start(); 
$outputStream = $process.StandardOutput; 
$outputStream.ReadToEnd(); 

Вы также можете перенаправить StandardError.

+0

Я уверен, что это сработает (я еще не тестировал его), но это также помешало бы писать текст в окне cmd. В идеале я все еще хочу, чтобы это было написано в окне cmd, чтобы пользователи могли видеть прогресс сборки, а затем, когда сборка заканчивается, я хочу проверить этот вывод, чтобы увидеть, была ли сборка неудачной или нет. Будьте внимательны, хотя за полезный ответ :) – deadlydog

0

редактировать: Я закончил с использованием ответ @David Брабант

Я столкнулся с этой проблемой и создал эхо-функции

function echo() 
{ 
    $input 
} 

, который позволит мне сделать это

$output = &"cmd.exe" $args | echo