Правильное использование Invoke-Expression? - PullRequest
14 голосов
/ 31 августа 2009

Я только что завершил свой первый ночной сценарий сборки (на самом деле первый существенный сценарий что угодно) в powershell. Кажется, у меня все работает хорошо, если еще не надежно (я еще не занимался значительной проверкой ошибок), но я обнаружил, что попадаю в тупик вокруг командлета Invoke-Expression, и мне интересно, использую ли я это правильно.

В частности, я использую ряд переменных для построения командных строк, которые я буду использовать для построения решения, а затем запускаю модульные тесты решения. например, что-то вроде:

$tmpDir = "C:\Users\<myuser>\Development\Autobuild"
$solutionPath=$tmpDir+"\MyProj\MyProj.sln"
$devenv="C:\Program Files (x86)\Microsoft Visual Studio 10.0\common7\ide\devenv"
$releaseProfile="Release"
$releaseCommandLine="`"$devenv`" `"$solutionPath`" /build `"$releaseProfile`""

Это работает достаточно хорошо, $releaseCommandLine содержит командную строку, которую я хочу выполнить, когда я закончу. Затем я выполняю его через эту строку:

$output = Invoke-Expression "& $releaseCommandLine"

Это правильный способ выполнить командную строку, созданную вручную из сценария powershell? Сначала я думал, что Invoke-Command сделает это, но я, должно быть, делал что-то не так, потому что я не мог заставить это работать в течение получаса, и я получил это почти сразу.

Я следовал этому же шаблону несколько раз в этом же сценарии. Это лучшая практика?

Ответы [ 2 ]

10 голосов
/ 31 августа 2009

Я думаю, что здесь нет необходимости использовать Invoke-Expression. Я сделал это с помощью множества сценариев сборки, и обычно это выглядит так:

$vsroot = "$env:ProgramFiles(x86)\Microsoft Visual Studio 9.0"
$devenv = "$vsroot\Common7\IDE\devenv.exe"
$sln = Join-Path <source_root> Source\MyProj\MyProj.sln
& $devenv $sln /build Release

или

& $devenv $sln /build "Release|Any CPU"

Хотя в последнее время у меня были некоторые проблемы с использованием devenv.exe (надстройки неправильного поведения и т. Д.), Поэтому сейчас я использую msbuild.exe:

$msbuild = 'C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe'
& $msbuild $sln /p:Configuration=Release

В настоящее время MSBuild может обрабатывать C #, VB и C ++ (вызывает vcbuild), но не может обрабатывать решения с проектами установки и развертывания в них. Тем не менее, я обнаружил, что это более надежно, чем использование devenv.exe.

Кстати, вам обычно нужно вызывать другие инструменты (sn.exe, signtool.exe, mt.exe и т. Д.) В сценарии сборки, которые относятся к той версии Visual Studio / .NET, против которой вы хотите собрать. Поэтому обычно лучше настроить переменные среды так же, как это делает командная строка VS 2008. С установленными PowerShell Community Extensions вы можете включить одну строку в заголовке профиля PSCX, чтобы включить это для настроек .NET 3.5 / VS 2008:

$Pscx:Preferences["ImportVisualStudioVars"] = $true
10 голосов
/ 31 августа 2009

выглядит хорошо для меня. Единственное, что я хотел бы изменить, - это использовать больше возможностей Powershell вместо хрупких предположений. E.g.:

  • использовать Join-Path вместо конкатенации строк

  • используйте провайдера Env:\ для поиска %programfiles(x86)% dir (или, еще лучше, используйте провайдера HKML:\, чтобы найти путь - он находится в ПРОГРАММНОМ ОБЕСПЕЧЕНИИ \ Microsoft \ VisualStudio \\ InstallDir)

  • когда мне нужно написать строку, содержащую буквальные двойные кавычки и раскрытие переменной, я обычно прибегаю к синтаксису ниже. Очевидно, личные предпочтения.

    '"{0}" "{1}" /build "{2}"' -f $devenv, $solutionPath, $releaseProfile
    

В некоторых случаях я склонен использовать Process.Start (), чтобы можно было независимо захватывать потоки stdout и stderr (и, возможно, даже интерактивно управлять stdin, в зависимости от приложения).

PS - '&' не является строго обязательным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...