How to Configure Group Policy Software Installation on Windows Server 2025
Group Policy Software Installation (GPSI) is the built-in mechanism in Active Directory environments for deploying, updating, and removing MSI-based applications across domain-joined computers without requiring third-party tools or agents. On Windows Server 2025, GPSI continues to be a practical solution for organizations managing a fleet of Windows machines that require consistent software deployment — particularly for internal line-of-business applications, admin tools, and standardized productivity software distributed as MSI packages. This guide covers the full GPSI workflow: creating a software distribution share, adding packages to GPOs, understanding the publish versus assign distinction, handling transforms, managing upgrades, and troubleshooting with gpresult, as well as the PowerShell App Deployment Toolkit as a modern complement for complex deployments.
Prerequisites
- Windows Server 2025 domain controller or a server with Group Policy Management Console (GPMC) installed
- Active Directory domain with organizational units (OUs) for targeting computers or users
- A file server or shared network path accessible to all target computers and users
- MSI packages for the software to be deployed (GPSI only supports MSI natively; EXE-based installers require repackaging or PSADT)
- Domain admin or delegated GPO management permissions
- Target machines running Windows 10/11 or Windows Server 2019/2022/2025
Step 1: Create the Software Distribution Share
GPSI installs software from a UNC path that must be accessible by the computer account (for computer-assigned packages) or user account (for user-published/assigned packages). Use a hidden administrative share with read-only access for client machines.
# Create the software distribution directory
New-Item -Path "D:SoftwareDeploy" -ItemType Directory -Force
# Create subdirectories per application
New-Item -Path "D:SoftwareDeploySevenZip" -ItemType Directory -Force
New-Item -Path "D:SoftwareDeployAdobeReader" -ItemType Directory -Force
New-Item -Path "D:SoftwareDeployNotePadPlusPlus" -ItemType Directory -Force
# Create a hidden share ($ suffix = hidden from network browsing)
New-SmbShare -Name "software$" -Path "D:SoftwareDeploy" `
-Description "GPO Software Distribution Share" `
-FullAccess "Domain Admins" `
-ReadAccess "Domain Computers", "Authenticated Users"
# Verify the share
Get-SmbShare -Name "software$" | Select-Object Name, Path, Description
Get-SmbShareAccess -Name "software$"
Copy the MSI installers into their respective subdirectories. Always test that the SYSTEM account (representing the computer) can read the share by testing with \serversoftware$AppNameapp.msi from a client machine.
Step 2: Create and Configure the GPO
Create a dedicated GPO for software deployment. Separate GPOs per application or per department OU keep management clean and allow independent linking and filtering.
# Install GPMC module (if not already available)
Install-WindowsFeature -Name GPMC -IncludeManagementTools
Import-Module GroupPolicy
# Create a new GPO for software deployment
$gpo = New-GPO -Name "Deploy-SevenZip-Computers" -Domain "corp.example.com" `
-Comment "Deploys 7-Zip 24.x MSI to workstations via Computer Configuration"
Write-Host "GPO created: $($gpo.DisplayName) | ID: $($gpo.Id)"
# Link the GPO to the target OU (Workstations OU in this example)
New-GPLink -Name "Deploy-SevenZip-Computers" `
-Target "OU=Workstations,DC=corp,DC=example,DC=com" `
-LinkEnabled Yes
Write-Host "GPO linked to Workstations OU."
Software Installation packages themselves are configured through the GPMC graphical editor or via the legacy gpedit.msc interface. Navigate to: Computer Configuration → Policies → Software Settings → Software Installation (for computer-assigned) or User Configuration → Policies → Software Settings → Software Installation (for user-published or user-assigned).
Step 3: Add an MSI Package to the GPO
Right-click Software Installation in the GPMC editor and select New → Package. Always browse to the UNC path (not a local drive letter) when adding the MSI — the path stored in the GPO must be network-accessible from client machines.
# PowerShell cannot directly add GPSI packages to the Software Installation node
# (it uses a COM-based interface). Use the GPMC MMC snap-in to add the MSI package.
# The following documents the UNC path to use when prompted in the UI:
$uncPath = "\filesrv01.corp.example.comsoftware$SevenZip7z2406-x64.msi"
Write-Host "Use this UNC path when adding the package in GPMC:"
Write-Host $uncPath
# After adding, you can verify the package was registered in the GPO via the XML definition:
Get-GPOReport -Name "Deploy-SevenZip-Computers" -ReportType Xml | `
Select-String -Pattern "SoftwareInstallation|msi|package" -Context 2
Step 4: Publish vs. Assign — Understanding the Difference
GPSI offers two deployment modes with important behavioral differences:
- Assigned (Computer Configuration): The application is installed automatically during the next Group Policy refresh or machine startup. Users cannot remove it. This is the most common mode for mandatory software.
- Assigned (User Configuration): The application appears as a shortcut and file-type association on next user logon, and installs on first launch (document activation) or at next logon. Users cannot permanently remove it.
- Published (User Configuration only): The application is available in Programs and Features → Install a program from your network but does not install automatically. Users can install it on demand. Document activation still applies if file-type associations are configured.
# When adding packages via GPMC, the deployment type dialog presents these options.
# For computer-assigned (automatic silent install at next reboot):
# - Select: Computer Configuration > Software Installation > New Package > Assigned
# Check existing software installation policy entries on a target machine:
gpresult /scope computer /v | Select-String -Pattern "Software Installation" -Context 5
# Force Group Policy refresh on remote target to trigger installation
Invoke-GPUpdate -Computer "ws-workstation01.corp.example.com" -Force -RandomDelayInMinutes 0
Step 5: Apply MST Transforms to Customize Installation
MST (Microsoft Transform) files customize the default MSI installation — suppressing features, setting default values, configuring silent installation properties — without modifying the original MSI.
# Place the transform file alongside the MSI in the distribution share
# Example: suppress Adobe Reader toolbar install and set default PDF viewer
Copy-Item -Path "D:TransformFilesAdobeReader-Silent.mst" `
-Destination "D:SoftwareDeployAdobeReader"
# The transform association is configured in the GPMC Package Properties dialog:
# Package > Properties > Modifications tab > Add the .mst file path
# Always use the UNC path:
$transformUNC = "\filesrv01.corp.example.comsoftware$AdobeReaderAdobeReader-Silent.mst"
Write-Host "MST UNC path: $transformUNC"
# Verify the MSI is compatible with the transform (version/upgrade codes must match):
$msiPath = "D:SoftwareDeployAdobeReaderAcroRdrDC2500120432_en_US.msi"
$installer = New-Object -ComObject WindowsInstaller.Installer
$db = $installer.OpenDatabase($msiPath, 0)
$view = $db.OpenView("SELECT Value FROM Property WHERE Property='ProductCode'")
$view.Execute()
$record = $view.Fetch()
Write-Host "Product Code: $($record.StringData(1))"
Step 6: Upgrade Packages
When a new version of an MSI is released, configure an Upgrade Package relationship in the GPO so the old version is automatically removed and replaced during the next policy refresh.
# In the GPMC editor, right-click the new package > Properties > Upgrades tab
# Click Add, select the older package from this GPO or another GPO
# Choose "Uninstall the existing package, then install the upgrade package"
# Alternatively, set "Package can upgrade over the existing package" for MSIs
# that support in-place major upgrades (same ProductCode, higher ProductVersion)
# You can verify upgrade relationships via GPO XML:
Get-GPOReport -Name "Deploy-SevenZip-Computers" -ReportType Xml | `
Select-String -Pattern "Upgrades|RequiredPackage" -Context 3
# Force policy re-evaluation and package re-installation on a specific computer:
Invoke-GPUpdate -Computer "ws-workstation02.corp.example.com" -Force
Step 7: Remove and Redeploy Packages
# To remove a package, right-click it in the GPMC Software Installation node > All Tasks > Remove
# Choose either:
# "Immediately uninstall the software from users and computers" (forced removal)
# "Allow users to continue to use the software, but prevent new installations" (soft removal)
# For forced redeployment (re-install even if already installed):
# Right-click package > All Tasks > Redeploy application
# This resets the package state so it reinstalls at next GP refresh
# Check installed software on a remote machine:
Invoke-Command -ComputerName "ws-workstation01" -ScriptBlock {
Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*7-Zip*" } |
Select-Object Name, Version, InstallDate
}
Step 8: Troubleshoot with gpresult and Event Logs
# Generate an HTML Group Policy results report for a specific user and computer
gpresult /h "C:Reportsgp_report_ws01.html" /user "corpjdoe" /f
Start-Process "C:Reportsgp_report_ws01.html"
# Check GP results in XML format for parsing
gpresult /scope computer /x "C:Reportsgp_computer.xml" /f
# Check Software Installation event logs on the client
Get-WinEvent -LogName "Application" -ComputerName "ws-workstation01" |
Where-Object { $_.ProviderName -eq "MsiInstaller" -and $_.TimeCreated -gt (Get-Date).AddDays(-1) } |
Select-Object TimeCreated, Id, Message | Format-Table -Wrap
# Check GP operational log for policy processing errors
Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -ComputerName "ws-workstation01" |
Where-Object { $_.LevelDisplayName -in "Error","Warning" } |
Select-Object TimeCreated, Message | Format-List
Step 9: PowerShell App Deployment Toolkit (PSADT) as a Modern Alternative
For EXE-based installers, complex installation logic, or deployments requiring user interaction deferral, the PowerShell App Deployment Toolkit (PSADT) wraps any installer in a standardized framework that integrates with GPSI, MECM, or Intune.
# PSADT structure — place in the software share alongside the installer:
# \filesrv01software$AppName
# Deploy-Application.ps1 <- main script
# Deploy-Application.exe <- launcher (runs PS as SYSTEM)
# Files <- installers, MSIs, etc.
# SupportFiles <- transforms, configs
# AppDeployToolkit <- PSADT framework files
# Example Deploy-Application.ps1 (Install section):
# $installTitle = "7-Zip 24.06"
# Execute-MSI -Action Install -Path "7z2406-x64.msi" -Transform "silent.mst" `
# -Parameters "REBOOT=ReallySuppress"
# Configure GPSI to run Deploy-Application.exe as the install command
# by wrapping it in a bootstrapper MSI (use WiX or MSIX packaging tools to create a thin MSI)
# Test PSADT installation silently:
& "\filesrv01.corp.example.comsoftware$SevenZipDeploy-Application.exe" -DeploymentType Install -DeployMode Silent
Write-Host "PSADT deployment exit code: $LASTEXITCODE"
Group Policy Software Installation on Windows Server 2025 remains a viable, zero-cost software deployment mechanism for Active Directory environments, particularly for MSI-based applications where silent installation with transforms is sufficient. For organizations requiring more flexibility — complex dependency chains, pre/post-install scripting, non-MSI formats, or user notification and deferral dialogs — augmenting GPSI with PSADT bridges the gap between the simplicity of Group Policy and the power of commercial deployment tools. As environments grow beyond a few hundred machines or require detailed compliance reporting, migrating to Microsoft Endpoint Configuration Manager or Microsoft Intune offers significantly richer inventory, packaging, and reporting capabilities.