Public/Disable-ServicePathQuoting.ps1
|
function Disable-ServicePathQuoting { <# .SYNOPSIS Removes quotation marks from a Windows service's executable path. .DESCRIPTION Reads the ImagePath registry value for the specified service and strips the quotation marks from around the executable path. Arguments that follow the executable are preserved. After updating the registry the service is restarted and its status is verified. Requires elevation (Administrator). Use -WhatIf to preview changes without applying them. Remote operations use Invoke-Command and require WinRM to be configured on the target machine. .INPUTS None. Parameters must be supplied directly. .OUTPUTS System.Management.Automation.PSCustomObject .PARAMETER Name The service name (as returned by Get-Service). .PARAMETER DisplayName The display name of the service. .PARAMETER ComputerName The target computer. Defaults to the local machine. .EXAMPLE Disable-ServicePathQuoting -Name 'MySvc' Removes quotes from the ImagePath for MySvc on the local machine and restarts it. .EXAMPLE Disable-ServicePathQuoting -Name 'MySvc' -ComputerName 'Server01' Removes quotes from the ImagePath for MySvc on Server01 and restarts it. .EXAMPLE Disable-ServicePathQuoting -DisplayName 'My Service' -WhatIf Previews the unquoting change without applying it. .NOTES Modifying service registry keys requires Administrator privileges. The service is restarted after the path is updated. Ensure this is acceptable before running. Remote operations require WinRM to be configured on the target machine. Use Enable-ServicePathQuoting to reverse this change. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [OutputType([System.Management.Automation.PSCustomObject])] param ( [Parameter(Mandatory = $true, ParameterSetName = 'ByName', Position = 0)] [string]$Name, [Parameter(Mandatory = $true, ParameterSetName = 'ByDisplayName', Position = 0)] [string]$DisplayName, [Parameter(Mandatory = $false)] [string]$ComputerName = $env:COMPUTERNAME ) $isLocal = ($ComputerName -ieq $env:COMPUTERNAME) -or ($ComputerName -ieq 'localhost') -or ($ComputerName -eq '127.0.0.1') $svcParams = @{ ErrorAction = 'Stop' } if ($PSCmdlet.ParameterSetName -eq 'ByDisplayName') { $svcParams.DisplayName = $DisplayName } else { $svcParams.Name = $Name } if (-not $isLocal) { $svcParams.ComputerName = $ComputerName } $service = Get-Service @svcParams $serviceName = $service.Name $registryPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName" if ($isLocal) { $currentImagePath = (Get-ItemProperty -Path $registryPath -Name ImagePath -ErrorAction Stop).ImagePath } else { $currentImagePath = Invoke-Command -ComputerName $ComputerName -ScriptBlock { (Get-ItemProperty -Path $using:registryPath -Name ImagePath -ErrorAction Stop).ImagePath } } $previousPath = $currentImagePath if (-not $currentImagePath.TrimStart().StartsWith('"')) { Write-Warning "The ImagePath for '$serviceName' is not quoted. No changes made." return } if ($currentImagePath -imatch '^"([^"]+)"(.*)$') { $exePath = $Matches[1].Trim() $arguments = $Matches[2].Trim() $newImagePath = if ($arguments) { "$exePath $arguments" } else { $exePath } } else { $newImagePath = $currentImagePath.Replace('"', '') } if ($PSCmdlet.ShouldProcess("$ComputerName\$serviceName", "Set ImagePath to '$newImagePath' and restart service")) { if ($isLocal) { Set-ItemProperty -Path $registryPath -Name ImagePath -Value $newImagePath -ErrorAction Stop Write-Verbose "Registry updated for '$serviceName'. Restarting..." Restart-Service -Name $serviceName -Force -ErrorAction Stop $newStatus = (Get-Service -Name $serviceName).Status } else { Invoke-Command -ComputerName $ComputerName -ScriptBlock { Set-ItemProperty -Path $using:registryPath -Name ImagePath -Value $using:newImagePath -ErrorAction Stop Restart-Service -Name $using:serviceName -Force -ErrorAction Stop } Write-Verbose "Registry updated and '$serviceName' restarted on '$ComputerName'. Verifying status..." $newStatus = (Get-Service -Name $serviceName -ComputerName $ComputerName).Status } if ($newStatus -ne 'Running') { Write-Warning "Service '$serviceName' on '$ComputerName' did not return to Running after restart. Current status: $newStatus" } else { Write-Verbose "Service '$serviceName' on '$ComputerName' is Running." } [PSCustomObject]@{ ComputerName = $ComputerName ServiceName = $serviceName PreviousPath = $previousPath NewPath = $newImagePath } } } |