Install-RemoteMSI.ps1 deploys an .msi or .msix package to one or more remote Windows machines over PowerShell Remoting (WinRM), with strong pre-validation, credential validation, retry logic, and full run logging.
-NonInteractive(switch): suppresses interactive prompts where possible.-RunLogPath <string>: optional custom path for the per-run aggregated log file.
- Script and installer source folder: script directory.
- Remote staging path:
C:\Temp - Log folder:
.\Logs - Max credential attempts:
2 - Transfer retry delays:
5, 10, 30, 60seconds. - Run ID format:
yyyyMMdd_HHmmss $ErrorActionPreference = 'Stop'
Mainstarts and captures run start time.Initialize-RunLogcreates the log file:- Uses
-RunLogPathif provided, otherwise: Logs\Deployment_<timestamp>.log
- Uses
Write-Logwrites timestamped messages to console and log file.
Invoke-PowerShell7Bootstrapchecks host PS version.- If PS 7+, continue.
- If below PS 7:
Get-PowerShell7Detailssearches forpwsh.exein PATH, common install folders, and registry App Paths.- In interactive mode, user can relaunch via
Invoke-PowerShell7Relaunch. - If not installed, user can optionally install via
Install-PowerShell7ViaWindowsUpdate(requires local admin).
- If relaunched successfully, parent exits and returns child exit code.
Test-InstallerFilesExistverifies at least one.msi/.msixexists in script directory.Get-MSIFile:- auto-selects single installer, or
- prompts selection when multiple installers are present.
Get-ExecutionModeprompts:Singlemachine modeBatchmode (.txt/.csvmachine list)
Get-ValidatedCredentialForDomain:- Uses current context if
Test-CurrentUserDomainAuthsucceeds. - Else prompts via
Request-Credentialsand validates withTest-DomainCredential.
- Uses current context if
Get-CredentialAfterUserConfirmationshows current/effective identity and optionally accepts alternate validated credentials.
Get-ValidatedSingleHostnamereads hostname.ConvertTo-Hostnamesanitizes hostname characters.Get-MachineAvailabilityReportruns checks in order:Test-ComputerInADResolve-ComputerIPAddressesTest-ComputerOnlineTest-ComputerWinRM
- Machine is classified into one state:
ReadyMachinesInvalidNameNotInADValidNoDNSIPReachabilityFailedWinRMUnavailable
- If not
ReadyMachines, run stops with explicit reason.
Invoke-AuthorizationCanaryCheck(single target) validates:- session establishment
- local admin rights (
Test-RemoteAdmin)
- Any failure aborts before installation.
Invoke-Deploymentis called with throttle1.- Per-machine work is done by
Invoke-MachineInstall:- Open PSSession.
- Ensure
C:\Tempexists. - Capture pre-install reboot state (
Get-PendingRebootState). - Copy installer with retry policy (
Copy-MSIWithRetry). - Execute
msiexec.exe /i <path> /quiet /norestart. - Map exit code using
Get-MSIExitDescription. - If success (
0,1641,3010), evaluate reboot requirement (Get-RebootRequirementEvaluation). - Clean remote installer via
Remove-RemoteMSIon success (and on1619). - Return normalized result object (
New-Result).
- Failed installs can be retried interactively using
Read-RetryChoice.
Find-BatchMachineFilediscovers.txt/.csvin script directory or prompts for full path.Get-MachineNamesFromFile:- reads machine names (first CSV column),
- ignores blank/comment lines (
#), - sanitizes names (
ConvertTo-Hostname), - deduplicates list.
Get-MachineAvailabilityReportapplies the same 5-state checks to all input machines.- Non-ready machines are excluded and logged.
- If zero machines are ready:
Write-MachineStateValidationSummaryprints pre-validation summary table,- run exits as failed.
Invoke-AuthorizationCanaryChecktests up to 3 ready machines.- Any canary failure aborts full rollout.
- Operator enters thread count (
1= sequential). - If host is below PS 7 and thread count > 1, script forces sequential and logs warning.
Invoke-Deploymentchunks list viaGet-ChunkedArrays.
- In each chunk:
- PS7+ with throttle >1 uses
ForEach-Object -Parallel -AsJob. - Otherwise sequential
Invoke-MachineInstall.
- PS7+ with throttle >1 uses
- Batch progress spinner is shown.
- Failed machines enter interactive retry rounds (failed machines only).
- Final result collapse per machine is done by
Get-FinalResultPerMachine. - Successful machine lines are commented in source list via
Update-BatchFileForSuccesses.
Write-Summaryprints:- overall status (
SUCCESS,PARTIAL SUCCESS,FAILED) - totals (success/fail/reboot)
- per-machine result table
- detailed failed-machine log entries
- overall status (
- Exit code:
0if all final machine results succeeded1if any machine failed or fatal exception occurred
- Script pauses for Enter key, then exits with final code.
Handled by Get-MSIExitDescription:
0Success1641Success, restart initiated3010Success, reboot required1601Installer service unavailable1602User cancelled1603Fatal error1618Another install in progress1619Package cannot be opened1625Blocked by policy1632Temp folder issue1633Platform unsupported1638Product version already installed- default: unknown code
MainInitialize-RunLogWrite-LogGet-ConfirmationConvertTo-HostnameTest-ComputerInADTest-ComputerOnlineResolve-ComputerIPAddressesTest-ComputerWinRMGet-ValidatedSingleHostnameGet-ExecutionModeGet-PowerShell7DetailsTest-IsInteractiveSessionTest-IsLocalAdministratorRead-YesNoChoiceInstall-PowerShell7ViaWindowsUpdateInvoke-PowerShell7RelaunchInvoke-PowerShell7BootstrapGet-InstallerFilesTest-InstallerFilesExistGet-MSIFileRequest-CredentialsTest-RemoteAdminTest-CurrentUserDomainAuthTest-DomainCredentialGet-ValidatedCredentialForDomainGet-EffectiveCredentialIdentityGet-CredentialAfterUserConfirmationInvoke-AuthorizationCanaryCheckFind-BatchMachineFileGet-MachineNamesFromFileGet-MachineAvailabilityReportWrite-MachineStateValidationSummaryGet-MSIExitDescriptionCopy-MSIWithRetryGet-PendingRebootStateGet-RebootRequirementEvaluationRemove-RemoteMSINew-ResultInvoke-MachineInstallRead-RetryChoiceGet-ChunkedArraysUpdate-BatchFileForSuccessesInvoke-DeploymentGet-FinalResultPerMachineWrite-Summary
Add-CandidatePath(insideGet-PowerShell7Details)Write-SpinnerStatusLine,Update-ValidationSpinner(insideGet-MachineAvailabilityReport)Get-ExitDesc,Get-RebootState,Get-RebootEval(inside parallel block ofInvoke-Deployment)
Get-DateSplit-PathJoin-PathTest-PathNew-ItemAdd-ContentWrite-HostRead-HostGet-CommandGet-ChildItemGet-ContentSet-ContentGet-ItemGet-ItemPropertyResolve-DnsNameTest-ConnectionTest-WSManNew-PSSessionInvoke-CommandRemove-PSSessionCopy-ItemRemove-ItemStart-ProcessStart-SleepGet-WmiObjectWhere-ObjectSort-ObjectSelect-ObjectGroup-ObjectForEach-Object(including-Parallel)Receive-JobRemove-JobOut-Null
Get-ADComputer(when ActiveDirectory module is available)pwsh.exe(PowerShell 7 relaunch target)msiexec.exe(remote installer execution)
- Requires WinRM/PowerShell Remoting availability on targets.
- Requires permissions sufficient for remote administration and install.
- Uses domain credential validation before deployment to fail fast.
- Canary authorization check prevents broad rollout with insufficient rights.
- Logs all key events to one per-run log for auditing.
- Supports resilient transfer retries and controlled retry prompts.
- Batch mode comments successful entries in source file to streamline reruns.