如何在PowerShell中运行Windows安装程序并获取成功/失败值?

时间:2011-01-20 15:42:41

标签: powershell windows-installer

我想安装一组应用程序:.NET 4,IIS 7 PowerShell管理单元,ASP.NET MVC 3等。如何安装应用程序和返回一个确定安装是否成功的值?

4 个答案:

答案 0 :(得分:18)

这些答案似乎都过于复杂或不够完整。在PowerShell控制台中运行安装程序有一些问题。 MSI在Windows subsystem中运行,因此您无法仅调用它们(Invoke-Expression&)。有些人声称通过管道传输到Out-NullOut-Host来获取这些命令,但我没有注意到这一点。

适用于我的方法是Start-Process,其静默安装参数为msiexec

$list = 
@(
    "/I `"$msi`"",                     # Install this MSI
    "/QN",                             # Quietly, without a UI
    "/L*V `"$ENV:TEMP\$name.log`""     # Verbose output to this log
)

Start-Process -FilePath "msiexec" -ArgumentList $list -Wait

您可以从Start-Process命令获取exit code并检查其是否为通过/失败值。 (这里是exit code reference

$p = Start-Process -FilePath "msiexec" -ArgumentList $list -Wait -PassThru

if($p.ExitCode -ne 0)
{
    throw "Installation process returned error code: $($p.ExitCode)"
}

答案 1 :(得分:3)

取决于。可以使用WMI安装MSI。对于exes和其他方法,您可以使用Start-Process并检查Process ExitCode。

答案 2 :(得分:3)

也可以使用msiexec.exe安装msi,也可以使用wusa.exe安装msu,两者都有/quiet开关,/norestart/forcerestart开关以及/log用于记录的选项(指定文件名)。

如果您使用/?

进行调用,可以阅读有关这些选项的更多信息

注意:wusa在失败时会无声地失败,因此您必须检查日志文件或事件日志以确定是否成功。

答案 3 :(得分:0)

我已经在我当前的项目中实现了您正在寻找的内容。我们需要跨多个环境和数据中心自动部署和灌输n个应用程序。为简单起见,这些脚本略微修改了原始版本,因为我的完整代码达到了1000行,但核心功能完好无损。我希望这能满足你的要求。

此PS函数从注册表中提取所有应用程序(添加/删除程序的内容),然后搜索提供的应用程序名称和显示版本。在我的代码(PSM1)中,我在安装之前运行此函数,无论它是否是他们的然后后续文件来验证它已安装....所有这些都可以包含在一个主函数中,用于管理器流控制。

function Confirm-AppInstall{
param($AppName,$AppVersion)
$Apps = Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*|?{$_.DisplayName -ne $Null}|?{$_.DisplayName -ne ""}

$Apps += Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*|?{$_.DisplayName -ne $Null}|?{$_.DisplayName -ne ""}

$Installed = $Apps|?{$_.DisplayName -eq ""}|?{$_.DisplayVersion -eq ""}|select -First 1
if($Installed -ne $null){return $true}else{return $false}
}

此PS函数将加载一个txt文件,该文件具有预先填充的安装命令(每行一个命令)。然后单独运行每一行并等待安装完成,然后继续下一行。

function Install-Application{
param($InstallList = "C:\Install_Apps_CMDS.txt")

$list = gc -Path $InstallList
foreach ($Command in $list){
    Write-Output ("[{0}]{1}"  -f (Get-Date -Format G),$call)
    #Make install process wait for exit before continuing.
    $p = [diagnostics.process]::Start("powershell.exe","-NoProfile -NoLogo -Command $Command")
    $p.WaitForExit()
    Start-Sleep -Seconds 2
    #Searches for the installer exe or msi that was directly opened by powershell and gets the process id.
    $ProcessID = (gwmi -Query ("select ProcessId from Win32_Process WHERE ParentProcessID = {0} AND Name = '{1}'" -f $p.Id,$ParentProcessFile)|select ProcessId).ProcessId
    #waits for the exe or msi to finish installing
    while ( (Get-Process -Id $ProcessID -ea 0) -ne $null){
        Start-Sleep -Seconds 2
        $ElapsedTime = [int](New-TimeSpan -Start $P.StartTime -End (Get-Date)|select TotalSeconds).TotalSeconds
        #install times out after 1000 seconds so it dosent just sit their forever this can be changed 
        if(2000 -lt $ElapsedTime){
            Write-Output ('[{0}] The application "{1}" timed out during instilation and was forcfully exited after {2} seconds.'  -f (Get-Date -Format G),$App.Name,(([int]$App.InstallTimeOut) * 60))
            break
        }
    }
    #clean up any old or hung install proccess that should not be running at this point.
    Stop-Process -Name $ParentProcessName -ea 0 -Force
    Stop-Process -Name msiexec -ea 0 -Force
    }
}

TXT文件应格式化为......您需要研究如何安装每个应用程序。一个很好的资源是appdeploy.com

C:\Install.exe /q
C:\install.msi /qn TRANSFORMS='C:\transform.mst'
C:\install2.msi /qn /norestart
C:\install3.exe /quiet

让我知道是否有任何错误我必须修改我的现有代码以删除专有值并使其更简单一些。我从自定义XML答案表中提取我的值。但是这段代码应该像我提供的那样工作。

如果您希望我更多地讨论我的实现,请告诉我,我可以做出更详细的解释,并添加更多我已实施的支持功能。

相关问题