作为我们使用Powershell完成的服务器构建和配置的一部分,我需要在许多Server 2012机器上远程安装.net framework 4.5.1。 The offline install作为.exe提供,在运行时,解压缩许多MSI安装程序和安装程序。
我们用来运行安装程序的代码可以使用MSI文件或exe。如果我们使用MSI文件,则调用MSIEXEC,如果是EXE,则直接调用该程序。任何所需的参数也可以传递。
出于我们的目的,这是使用Powershell cmdlet Start-Process实现的。
我需要获取返回代码以确定安装是否已正确完成,并且还希望捕获stdout和stderr以帮助诊断安装失败时的任何问题。
我有以下自定义编写函数来包装Start-Process cmdlet。
Function Start-Proc()
{
[CmdletBinding()]
param (
[string][ValidateNotNullOrEmpty()][ValidateScript({Test-Path -Path $_ -Type Leaf})] $FilePath,
[string][ValidateNotNullOrEmpty()]$Arguments,
[switch] $Hidden,
[switch] $WaitForExit
)
#Create files to hold the output to avoid the deadlock issue that seems to arise when we read
#the output and error at the same time http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
$errorFilePath = Join-Path -Path $env:TEMP -ChildPath ([system.guid]::NewGuid().ToString())
$outputFilePath = Join-Path -Path $env:TEMP -ChildPath ([system.guid]::NewGuid().ToString())
$process = Start-Process `
-FilePath $FilePath `
-ArgumentList $Arguments `
-RedirectStandardError $errorFilePath `
-RedirectStandardOutput $outputFilePath `
-NoNewWindow:$Hidden `
-PassThru `
-Wait:$WaitForExit
$errorOut = Get-Content -Path $errorFilePath
$stdOut = Get-Content -Path $outputFilePath
#Tidy up files
If ($process.HasExited)
{
Remove-Item $errorFilePath
Remove-Item $outputFilePath
}
#Create new object to send the messages and exit code back
$output = New-Object -TypeName PSObject
$output | Add-Member –MemberType NoteProperty -Name Message -Value $stdOut
$output | Add-Member –MemberType NoteProperty -Name ErrorMessage -Value $errorOut
$output | Add-Member –MemberType NoteProperty -Name ExitCode -Value $process.ExitCode
return $output
}
注意:我必须使用-RedirectStandardOutput和-RedirectStandardInput Params将输出发送到文件,然后使用Get-Content来避免死锁将属性读取为文本。
调用此函数以安装.NET framework 4.5.1始终失败,错误代码为5,即拒绝访问。
调查一下,看来你需要使用 -Verb RunAs 带有Start-Process的参数以管理员身份提升命令,但是将该参数添加到cmdlet会导致以下错误:
Parameter set cannot be resolved using the specified named parameters.
这是因为-Verb和-RedirectStandardOutput& -RedirectStandardError在不同的参数集中。
因此我的问题是:
如何从Powershell运行执行以下操作的可执行文件:
我已经尝试过直接使用.NET System.Diagnostics.Process.Start方法,但这会遇到同样的问题。
感谢您的帮助,因为这被证明是一个难题!
答案 0 :(得分:0)
我会使用另一个脚本,它具有参数,例如exe路径,参数和输出文件的名称,并让它返回退出代码。使用Start-Process重定向,等待进程并获取退出代码以返回到父脚本。在父脚本中,使用Start-Process -verb runas以脚本路径作为参数启动PowerShell,以及启动脚本提升的脚本参数。
答案 1 :(得分:0)
我没有捕获退出代码-但我确实得到了stdout + stderr。然后,您可以调整“脚本块”以执行此操作……
$output = "c:\temp\psoutput.txt"
$computername = "xxxxxx"
$code = "Stop-WebAppPool -Name `"my.app.pool" 2>&1 >>$output"
$prog = "powershell.exe"
Invoke-Command -ComputerName $computername -ScriptBlock { param($p,$a,$o)
Start-Process $p -ArgumentList $a -wait -verb RunAs
get-content $o
} -ArgumentList $prog,$code,$output