Кто-нибудь знает, как лучше всего определить конкретную основную причину этого исключения?Как устранить неполадки в «System.Management.Automation.CmdletInvocationException»
Рассмотрите службу WCF, которая должна использовать удаленную версию Powershell 2.0 для запуска MSBuild на удаленных компьютерах. В обоих случаях среды сценариев называются in-process (через C# для Powershell и через Powershell для MSBuild), а не «об отладку» - это было конкретное дизайнерское решение, чтобы избежать адского черта командной строки, а также разрешить передачу фактические объекты в сценарий Powershell.
Сокращенная версия сценария Powershell, который вызывает MSBuild показано ниже:
function Run-MSBuild
{
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Build.Engine")
$engine = New-Object Microsoft.Build.BuildEngine.Engine
$engine.BinPath = "C:\Windows\Microsoft.NET\Framework\v3.5"
$project = New-Object Microsoft.Build.BuildEngine.Project($engine, "3.5")
$project.Load("deploy.targets")
$project.InitialTargets = "DoStuff"
# Process the input object
while ($input.MoveNext())
{
# Set MSBuild Properties & Item
}
# Optionally setup some loggers (have also tried it without any loggers)
$consoleLogger = New-Object Microsoft.Build.BuildEngine.ConsoleLogger
$engine.RegisterLogger($consoleLogger)
$fileLogger = New-Object Microsoft.Build.BuildEngine.FileLogger
$fileLogger.Parameters = "verbosity=diagnostic"
$engine.RegisterLogger($fileLogger)
# Run the build - this is the line that throws a CmdletInvocationException
$result = $project.Build()
$engine.Shutdown()
}
При выполнении этого скрипта из команды PS подскажите что все работает нормально. Однако, как только скрипт выполняется с C#, он не справляется с указанным выше исключением.
C# код используется для вызова Powershell показано ниже (ремоутинг функциональных возможностей удалены для простоты):
// Build the DTO object that will be passed to Powershell
dto = SetupDTO()
RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create();
using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig))
{
runspace.Open();
IList errors;
using (var scriptInvoker = new RunspaceInvoke(runspace))
{
// The Powershell script lives in a file that gets compiled as an embedded resource
TextReader tr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("MyScriptResource"));
string script = tr.ReadToEnd();
// Load the script into the Runspace
scriptInvoker.Invoke(script);
// Call the function defined in the script, passing the DTO as an input object
var psResults = scriptInvoker.Invoke("$input | Run-MSBuild", dto, out errors);
}
}
Примечания: Перегрузка методы Invoke() позволяет передавать в IEnumerable объекта и он заботится об экземпляре счетчика в переменной Powershell «$ input» - это затем передается в скрипт по конвейеру. Вот некоторые вспомогательные ссылки:
- http://msdn.microsoft.com/en-us/library/ms569104(VS.85).aspx
- http://knicksmith.blogspot.com/2007/03/managing-exchange-2007-recipients-with.html (переход к «пропускания ввода объекту к пространству выполнение» раздела)
Если предположить, что проблема была связана с MSBuild выводя то, что Powershell пространство выполнения не может справиться, я также попробовал следующие варианты на второй .Invoke() вызов:
var psResults = scriptInvoker.Invoke("$input | Run-MSBuild | Out-String", dto, out errors);
var psResults = scriptInvoker.Invoke("$input | Run-MSBuild | Out-Null", dto, out errors);
var psResults = scriptInvoker.Invoke("Run-MSBuild | Out-String");
var psResults = scriptInvoker.Invoke("Run-MSBuild | Out-String");
var psResults = scriptInvoker.Invoke("Run-MSBuild | Out-Null");
var psResults = scriptInvoker.Invoke("Run-MSBuild");
Обратите внимание, что основная проблема все еще возникает независимо от того, используется ли входной объект.
Я также рассмотрел использование пользовательского PSHost (на основе этого примера: http://blogs.msdn.com/daiken/archive/2007/06/22/hosting-windows-powershell-sample-code.aspx), но во время отладки я не смог увидеть никаких «интересных» звонков на него.
Есть ли у великого и хорошего Stackoverflow какое-либо понимание, которое может спасти мое здравомыслие?
Можете ли вы предоставить более подробную информацию о том, где вы определили $ input? Кроме того, глядя на вашу функцию Run-MSBuild, я не буду следить за тем, как она должна допускать ввод конвейера ($ input | run-msbuild). –
Привет, Марко, спасибо за комментарий. Я добавил дополнительную информацию об этом, однако проблема существует с использованием или без использования входного объекта. – JamesD