1- <#
1+ <#
22. SYNOPSIS
33 Deploy/upgrade GLPI Agent via GPO without blocking startup.
44
1717#>
1818
1919param (
20- # Path to the GLPI Agent MSI installer (desired version)
21- [string ]$GLPIAgentMSI = " \\headq.scriptguy\netlogon\glpi-agent115-install.msi" ,
22- # Directory where logs will be recorded
23- [string ]$GLPILogDir = " C:\Logs-TEMP" ,
24- # Target version string to compare (prefix match, e.g. '1.15')
25- [string ]$ExpectedVersion = " 1.15" ,
26- # GLPI server URL and TAG to write during MSI install
27- [string ]$ServerUrl = " http://cmdb.headq.scriptguy/front/inventory.php" ,
28- [string ]$TagOverride = $null
20+ # Path to the GLPI Agent MSI installer (desired version)
21+ [string ]$GLPIAgentMSI = " \\headq.scriptguy\netlogon\glpi-agent115-install.msi" ,
22+ # Directory where logs will be recorded
23+ [string ]$GLPILogDir = " C:\Logs-TEMP" ,
24+ # Target version string to compare (prefix match, e.g. '1.15')
25+ [string ]$ExpectedVersion = " 1.15" ,
26+ # GLPI server URL and TAG to write during MSI install
27+ [string ]$ServerUrl = " http://cmdb.headq.scriptguy/front/inventory.php" ,
28+ [string ]$TagOverride = $null
2929)
3030
3131$ErrorActionPreference = ' Stop'
3232
3333# ------------------------ Logging ------------------------
34- $scriptName = [IO.Path ]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name )
34+ $scriptName = [IO.Path ]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name )
3535$logFileName = " $scriptName .log"
36- $logPath = Join-Path $GLPILogDir $logFileName
36+ $logPath = Join-Path $GLPILogDir $logFileName
3737
3838function Log-Message {
39- param (
40- [Parameter (Mandatory = $true )][string ]$Message ,
41- [ValidateSet (' INFO' , ' WARNING' , ' ERROR' )][string ]$Level = ' INFO'
42- )
43- $ts = Get-Date - Format ' yyyy-MM-dd HH:mm:ss'
44- $line = " [$ts ] [$Level ] $Message "
45- try { Add-Content - Path $logPath - Value $line - ErrorAction Stop } catch { Write-Host $line }
39+ param (
40+ [Parameter (Mandatory = $true )][string ]$Message ,
41+ [ValidateSet (' INFO' , ' WARNING' , ' ERROR' )][string ]$Level = ' INFO'
42+ )
43+ $ts = Get-Date - Format ' yyyy-MM-dd HH:mm:ss'
44+ $line = " [$ts ] [$Level ] $Message "
45+ try { Add-Content - Path $logPath - Value $line - ErrorAction Stop } catch { Write-Host $line }
4646}
4747
4848# Ensure log directory
4949if (-not (Test-Path - Path $GLPILogDir )) {
50- try { New-Item - Path $GLPILogDir - ItemType Directory - Force | Out-Null } catch {}
50+ try { New-Item - Path $GLPILogDir - ItemType Directory - Force | Out-Null } catch {}
5151}
5252
5353# -------------------- Context detection --------------------
5454function Get-IsGpoStartup {
55- try {
56- $isSystem = ([Security.Principal.WindowsIdentity ]::GetCurrent().User.Value -eq ' S-1-5-18' )
57- $session0 = ([Diagnostics.Process ]::GetCurrentProcess().SessionId -eq 0 )
58- $pp = Get-CimInstance Win32_Process - Filter " ProcessId=$pid "
59- $parent = if ($pp.ParentProcessId ) { Get-Process - Id $pp.ParentProcessId - ErrorAction SilentlyContinue }
60- $pname = ($parent.Name -replace ' \.exe$' , ' ' ).ToLower()
61- $gpParents = @ (' gpscript' , ' gpupdate' , ' winlogon' , ' services' )
62- return ($isSystem -and $session0 -and $gpParents -contains $pname )
63- } catch { return $false }
55+ try {
56+ $isSystem = ([Security.Principal.WindowsIdentity ]::GetCurrent().User.Value -eq ' S-1-5-18' )
57+ $session0 = ([Diagnostics.Process ]::GetCurrentProcess().SessionId -eq 0 )
58+ $pp = Get-CimInstance Win32_Process - Filter " ProcessId=$pid "
59+ $parent = if ($pp.ParentProcessId ) { Get-Process - Id $pp.ParentProcessId - ErrorAction SilentlyContinue }
60+ $pname = ($parent.Name -replace ' \.exe$' , ' ' ).ToLower()
61+ $gpParents = @ (' gpscript' , ' gpupdate' , ' winlogon' , ' services' )
62+ return ($isSystem -and $session0 -and $gpParents -contains $pname )
63+ } catch { return $false }
6464}
6565
6666$IsGpoStartup = Get-IsGpoStartup
6767Log- Message " GPO Startup context: $IsGpoStartup "
6868
6969# -------------------- Utilities --------------------
7070function Get-GLPIAgentPath {
71- $candidates = @ (
72- " C:\Program Files\GLPI-Agent\glpi-agent.exe" ,
73- " C:\Program Files (x86)\GLPI-Agent\glpi-agent.exe" ,
74- " C:\Program Files\GLPI-Agent\perl\bin\glpi-agent.exe"
75- )
76- foreach ($p in $candidates ) { if (Test-Path $p ) { return $p } }
77- return $null
71+ $candidates = @ (
72+ " C:\Program Files\GLPI-Agent\glpi-agent.exe" ,
73+ " C:\Program Files (x86)\GLPI-Agent\glpi-agent.exe" ,
74+ " C:\Program Files\GLPI-Agent\perl\bin\glpi-agent.exe"
75+ )
76+ foreach ($p in $candidates ) { if (Test-Path $p ) { return $p } }
77+ return $null
7878}
7979
8080function Get-InstalledGLPIInfo {
81- $roots = @ (
82- " HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" ,
83- " HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
84- )
85- foreach ($r in $roots ) {
86- Get-ChildItem $r - ErrorAction SilentlyContinue | ForEach-Object {
87- $it = Get-ItemProperty $_.PSPath - ErrorAction SilentlyContinue
88- if ($it -and $it.DisplayName -and ($it.DisplayName -like " *GLPI Agent*" )) {
89- [PSCustomObject ]@ {
90- DisplayName = $it.DisplayName
91- DisplayVersion = $it.DisplayVersion
92- UninstallString = $it.UninstallString
93- InstallLocation = $it.InstallLocation
94- RegistryKey = $_.PSChildName
81+ $roots = @ (
82+ " HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" ,
83+ " HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
84+ )
85+ foreach ($r in $roots ) {
86+ Get-ChildItem $r - ErrorAction SilentlyContinue | ForEach-Object {
87+ $it = Get-ItemProperty $_.PSPath - ErrorAction SilentlyContinue
88+ if ($it -and $it.DisplayName -and ($it.DisplayName -like " *GLPI Agent*" )) {
89+ [PSCustomObject ]@ {
90+ DisplayName = $it.DisplayName
91+ DisplayVersion = $it.DisplayVersion
92+ UninstallString = $it.UninstallString
93+ InstallLocation = $it.InstallLocation
94+ RegistryKey = $_.PSChildName
95+ }
96+ }
9597 }
96- }
9798 }
98- }
9999}
100100
101101# Resolve domain/TAG
102102$domainTag = if ($TagOverride ) { $TagOverride } elseif ($env: USERDOMAIN ) { $env: USERDOMAIN } else {
103- try { (Get-CimInstance Win32_ComputerSystem).Domain } catch { ' UNKNOWN' }
103+ try { (Get-CimInstance Win32_ComputerSystem).Domain } catch { ' UNKNOWN' }
104104}
105105
106106# -------------------- Pre-checks --------------------
@@ -109,77 +109,77 @@ if (-not (Test-Path $GLPIAgentMSI)) { Log-Message "MSI not found: $GLPIAgentMSI"
109109# Installed version?
110110$installed = Get-InstalledGLPIInfo | Select-Object - First 1
111111if ($installed ) {
112- Log- Message " Detected installed GLPI Agent: '$ ( $installed.DisplayName ) ' version '$ ( $installed.DisplayVersion ) '."
112+ Log- Message " Detected installed GLPI Agent: '$ ( $installed.DisplayName ) ' version '$ ( $installed.DisplayVersion ) '."
113113} else {
114- # Try fallback by file version
115- $exe = Get-GLPIAgentPath
116- if ($exe ) {
117- try {
118- $fv = (Get-Item $exe ).VersionInfo.ProductVersion
119- if ($fv ) {
120- $installed = [PSCustomObject ]@ { DisplayName = ' GLPI Agent (file)' ; DisplayVersion = $fv ; UninstallString = $null ; InstallLocation = (Split-Path $exe - Parent); RegistryKey = ' (file)' }
121- Log- Message " Detected GLPI Agent by executable: '$exe ' (file version: $fv )."
122- }
123- } catch {}
124- }
114+ # Try fallback by file version
115+ $exe = Get-GLPIAgentPath
116+ if ($exe ) {
117+ try {
118+ $fv = (Get-Item $exe ).VersionInfo.ProductVersion
119+ if ($fv ) {
120+ $installed = [PSCustomObject ]@ { DisplayName = ' GLPI Agent (file)' ; DisplayVersion = $fv ; UninstallString = $null ; InstallLocation = (Split-Path $exe - Parent); RegistryKey = ' (file)' }
121+ Log- Message " Detected GLPI Agent by executable: '$exe ' (file version: $fv )."
122+ }
123+ } catch {}
124+ }
125125}
126126
127127# -------------------- Idempotent decision --------------------
128128$needInstall = $true
129129if ($installed -and $installed.DisplayVersion ) {
130- if ($installed.DisplayVersion -like " $ExpectedVersion *" ) {
131- $needInstall = $false
132- Log- Message " Same version '$ExpectedVersion ' already installed; skipping installation (idempotent)."
133- } else {
134- Log- Message " Installed version '$ ( $installed.DisplayVersion ) ' differs from target '$ExpectedVersion '; will run MSI."
135- }
130+ if ($installed.DisplayVersion -like " $ExpectedVersion *" ) {
131+ $needInstall = $false
132+ Log- Message " Same version '$ExpectedVersion ' already installed; skipping installation (idempotent)."
133+ } else {
134+ Log- Message " Installed version '$ ( $installed.DisplayVersion ) ' differs from target '$ExpectedVersion '; will run MSI."
135+ }
136136} else {
137- Log- Message " GLPI Agent not found; will run MSI."
137+ Log- Message " GLPI Agent not found; will run MSI."
138138}
139139
140140# -------------------- Install (no uninstall) --------------------
141141if ($needInstall ) {
142- # Build MSI arguments. We log MSI to a separate file for troubleshooting.
143- $msiLog = Join-Path $GLPILogDir ' glpi-install.log'
144- $installArgs = @ (
145- ' /i' , " `" $GLPIAgentMSI `" " ,
146- ' /qn' , ' /norestart' , ' REBOOT=ReallySuppress' ,
147- ' /l*v' , " `" $msiLog `" " ,
148- " RUNNOW=1" ,
149- " SERVER=`" $ServerUrl `" " ,
150- " TAG=`" $domainTag `" "
151- ) -join ' '
152-
153- Log- Message " Executing: msiexec.exe $installArgs "
154-
155- try {
156- # IMPORTANT: Do not block in GPO Startup. We omit -NoNewWindow to avoid conflicts with -WindowStyle.
157- $proc = Start-Process - FilePath ' msiexec.exe' - ArgumentList $installArgs `
142+ # Build MSI arguments. We log MSI to a separate file for troubleshooting.
143+ $msiLog = Join-Path $GLPILogDir ' glpi-install.log'
144+ $installArgs = @ (
145+ ' /i' , " `" $GLPIAgentMSI `" " ,
146+ ' /qn' , ' /norestart' , ' REBOOT=ReallySuppress' ,
147+ ' /l*v' , " `" $msiLog `" " ,
148+ " RUNNOW=1" ,
149+ " SERVER=`" $ServerUrl `" " ,
150+ " TAG=`" $domainTag `" "
151+ ) -join ' '
152+
153+ Log- Message " Executing: msiexec.exe $installArgs "
154+
155+ try {
156+ # IMPORTANT: Do not block in GPO Startup. We omit -NoNewWindow to avoid conflicts with -WindowStyle.
157+ $proc = Start-Process - FilePath ' msiexec.exe' - ArgumentList $installArgs `
158158 - WindowStyle Hidden - PassThru - Wait:(! $IsGpoStartup ) - ErrorAction Stop
159159
160- # If we did not wait (GPO Startup), $proc may be $null; log accordingly.
161- if ($proc ) {
162- Log- Message " msiexec exited with code: $ ( $proc.ExitCode ) "
163- if ($proc.ExitCode -ne 0 ) { Log- Message " MSI returned non-zero exit code. See $msiLog " ' WARNING' }
164- } else {
165- Log- Message " Started msiexec in background (GPO Startup); see $msiLog for progress."
160+ # If we did not wait (GPO Startup), $proc may be $null; log accordingly.
161+ if ($proc ) {
162+ Log- Message " msiexec exited with code: $ ( $proc.ExitCode ) "
163+ if ($proc.ExitCode -ne 0 ) { Log- Message " MSI returned non-zero exit code. See $msiLog " ' WARNING' }
164+ } else {
165+ Log- Message " Started msiexec in background (GPO Startup); see $msiLog for progress."
166+ }
166167 }
167- }
168- catch {
169- Log- Message " Failed to launch msiexec. Error: $_ " ' ERROR'
170- exit 1
171- }
172- } else {
173- # Optionally ensure service is running, but do not block.
174- try {
175- $svc = Get-Service - ErrorAction SilentlyContinue | Where-Object {
176- $_.Name -like ' *glpi*agent*' -or $_.DisplayName -like ' *GLPI*Agent*'
177- } | Select-Object - First 1
178- if ($svc -and $svc.Status -ne ' Running' ) {
179- Start-Service - Name $svc.Name - ErrorAction SilentlyContinue
180- Log- Message " Started service '$ ( $svc.Name ) '."
168+ catch {
169+ Log- Message " Failed to launch msiexec. Error: $_ " ' ERROR'
170+ exit 1
181171 }
182- } catch {}
172+ } else {
173+ # Optionally ensure service is running, but do not block.
174+ try {
175+ $svc = Get-Service - ErrorAction SilentlyContinue | Where-Object {
176+ $_.Name -like ' *glpi*agent*' -or $_.DisplayName -like ' *GLPI*Agent*'
177+ } | Select-Object - First 1
178+ if ($svc -and $svc.Status -ne ' Running' ) {
179+ Start-Service - Name $svc.Name - ErrorAction SilentlyContinue
180+ Log- Message " Started service '$ ( $svc.Name ) '."
181+ }
182+ } catch {}
183183}
184184
185185# -------------------- End --------------------
0 commit comments