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.