%20%D1%83%D1%81%D0%BF%D0%B5%D1%88%D0%BD%D0%BE%D0%B9%20%D0%B8%D0%BB%D0%B8%20%D0%BD%D0%B5%D1%82%3F.png)
Я написал скрипт PowerShell (см. ниже) для установки очень большого количества обновлений MSP (файлов с .msp
расширениями, развернутых через установщик Windows) одного за другим. Теперь я хотел бы, чтобы этот скрипт также сообщал мне, когда установка обновления MSP не удалась.
Что я пробовал: Запрос кода ошибки.Существует два подхода:
- Один из них — получить код ошибки с помощью $LASTEXITCODE после
MSIEXEC.EXE
прямого запуска. Это утомительно. Другой включал добавление
-PassThru
switch кStart-Process
, сохранение его результата в объекте, скажем,$a
и чтение кода ошибки с помощью$a.ExitCode
. Вот так:$a=Start-Process msiexec.exe -ArgumentList "/p `"$MspRelPath`" /log `"$LogRelPath`" /passive /norestart" -Wait -PassThru Write-Host $a.ExitCode
Ни то, ни другое не оказалось полезным. Кажется, msiexec.exe
всегда возвращается ноль в качестве кода выхода.
Если кому интересно, вот скрипт:
param (
[parameter(mandatory=$false)][Switch]$BypassAdminPrompt
)
Try
{
Clear-Host
# Get script name
$ScriptFileObject=(Get-Item $PSCommandPath)
$ScriptName=$ScriptFileObject.Name
$ScriptPath=$ScriptFileObject.DirectoryName
# Load Windows Forms and initialize visual styles
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.Application]::EnableVisualStyles()
# Is the script holding administrative privileges?
$wid=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$prp=new-object System.Security.Principal.WindowsPrincipal($wid)
$adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator
$IsAdmin=$prp.IsInRole($adm)
if ($IsAdmin -eq $false) {
if (!$BypassAdminPrompt) {
Start-Process powershell.exe -ArgumentList "-ExecutionPolicy $env:PSExecutionPolicyPreference -File `"$PSCommandPath`" -BypassAdminPrompt" -Verb RunAs
} else {
$result=[System.Windows.Forms.MessageBox]::Show("This script requires administrative privileges, which are absent.", $ScriptName, "OK", "Error");
}
break;
}
# Install...
Set-Location $ScriptPath
$MSP_list = Get-ChildItem *.msp -Recurse
if ($MSP_list -eq $null) {
$result=[System.Windows.Forms.MessageBox]::Show("Nothing found to install.`rSearch path was "+$ScriptPath, $ScriptName, "OK", "Error");
}
else
{
$MSP_list | ForEach-Object {
# Ordinarily, I'd pass the path in the form of ".\foldername\filename.msp" but Windows Installer does not accept that.
# It must be in "foldername\filename.msp" form.
$MspRelPath = $_.FullName.Substring($ScriptPath.Length+1)
$LogRelPath = $MspRelPath+".log"
Write-Host $MspRelPath
Start-Process msiexec.exe -ArgumentList "/p `"$MspRelPath`" /log `"$LogRelPath`" /passive /norestart" -Wait
}
Remove-Variable MspRelPath
Remove-Variable LogRelPath
Pause
}
Remove-Variable MSP_list
}
Catch
{
$result=[System.Windows.Forms.MessageBox]::Show("Error!`r`r"+$Error[0], $ScriptName, "OK", "Error");
break;
}
решение1
либо проверьте события Windows на наличие событий MSIExec, либо получите содержимое выходного журнала после завершения и проверьте наличие признаков сбоя.
У меня есть скрипт, который устанавливает MSI удаленно с помощью MSIExec, ждет, пока MSIExec завершит работу (или запустится процесс/служба)... если после типичного времени установки ничего не происходит, я проверяю путь к журналу, включенный в вызов MSIExec, и проверяю сообщения об ошибках или успехах.