Remote software deployment scripts for Windows machines via PowerShell remoting.
This project provides reusable PowerShell scripts for deploying .exe and .msi installers to remote Windows machines. Configuration is driven by JSON files, making it easy to add support for new software packages.
- PowerShell 5.1 or later
- Administrator privileges on the local machine
- WinRM enabled on target machines (
Enable-PSRemoting -Force) - Network access to target machines (ping, admin shares)
- Installer files accessible via network share
PSRemoteInstaller/
├── Install-RemoteExe.ps1 # Script for .exe installers (NSIS, etc.)
├── Install-RemoteMsi.ps1 # Script for .msi installers
├── configs/
│ ├── anaconda-exe.json # Anaconda configuration
│ ├── python-exe.json # Python configuration
│ └── office-msi.json # MSI example (SSMS)
└── README.md
# Install Anaconda via .exe installer
.\Install-RemoteExe.ps1 -ComputerName SERVER01 -Config .\configs\anaconda-exe.json
# Install software via .msi installer
.\Install-RemoteMsi.ps1 -ComputerName SERVER01 -Config .\configs\office-msi.json.\Install-RemoteExe.ps1 -Help
.\Install-RemoteMsi.ps1 -HelpEach installer requires a JSON configuration file with the following fields:
| Field | Description |
|---|---|
DisplayName |
Human-readable name for logging and help output |
NetworkSharePath |
UNC path to the network share containing the installer |
InstallerFilename |
Name of the installer file |
RemoteTempPath |
Temporary directory on the remote machine |
InstallPath |
Target installation directory |
SilentArgs |
Command-line arguments with {{InstallPath}} placeholder |
VerifyPath |
Relative path to verify after installation (confirms success) |
ExitCodes |
Maps installer-specific exit codes to messages |
{
"DisplayName": "Anaconda3 2025.12",
"NetworkSharePath": "\\\\SMB\\Shared\\",
"InstallerFilename": "Anaconda3-2025.12-1-Windows-x86_64.exe",
"RemoteTempPath": "C:\\Temp",
"InstallPath": "C:\\ProgramData\\Anaconda3",
"SilentArgs": "/S /AddToPath=1 /RegisterPython=0 /D={{InstallPath}}",
"VerifyPath": "Scripts\\conda.exe",
"ExitCodes": {
"0": "Success",
"1": "Installation cancelled by user",
"2": "Installation aborted (disk space, permissions, path issues)"
}
}- Copy an existing config file
- Update the values (paths, args, exit codes)
- Save as
<software>-<type>.json - Run with the appropriate script
Script-level exit codes (same for both scripts):
| Code | Description |
|---|---|
| 0 | Success |
| 1 | Not run as Administrator |
| 10 | Target unreachable (ping failed) |
| 11 | DNS resolution failed |
| 12 | WinRM unavailable |
| 13 | Remote session failed |
| 20 | Failed to create temp directory |
| 21 | Source file not found |
| 22 | File copy failed |
| 23 | File copy verification failed |
| 30 | Config file not found |
| 31 | Config file invalid |
| 99 | Unexpected error |
| 100+ | Installer-specific exit codes (offset by 100) |
| Code | Description |
|---|---|
| 0 | Success |
| 1641 | Success, reboot initiated |
| 3010 | Success, reboot required |
| 1602 | User cancelled installation |
| 1603 | Fatal error during installation |
Run on the target machine:
Enable-PSRemoting -ForceEnsure:
- You're running as an administrator with domain credentials
- The target machine's firewall allows File and Printer Sharing
- Administrative shares (C$, ADMIN$) are enabled
The VerifyPath setting checks if a specific file exists after installation. If installation succeeds but verification fails:
- Check if the
InstallPathis correct - Verify the
VerifyPathis the correct relative path fromInstallPath - Some installers may require a reboot before files appear
- No automatic reboots - exit codes 1641/3010 indicate reboot is needed
- PowerShell 5.1 compatible (no newer language features used)
- All file transfers use admin shares (\target\C$...)