UninstallFastLinqPowerKit.ps1
# Script level parameters Param ( [Switch] $UninstallRESTServerOnly = $false ) # Functions Function Test-IfNano { # Check if OS is Nano or Non-Nano $envInfo = [Environment]::OSVersion.Version $envInfoCimInst = Get-CimInstance Win32_OperatingSystem return ( ($envInfo.Major -eq 10) -and ($envInfo.Minor -eq 0) -and ($envInfoCimInst.ProductType -eq 3) -and ($envInfoCimInst.SuiteMask -eq 272) ) } Function Test-IfServerCore { # Check if OS is Server Core $regKey = 'hklm:/software/microsoft/windows nt/currentversion' return (Get-ItemProperty $regKey).InstallationType -eq 'Server Core' } Function Test-RegistryValue { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Path, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Value ) try { Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop 2>&1 | Out-Null return $true } catch { return $false } } Function Get-AppxPackageWrapper { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxName ) $numAttempts = 3 $numSecondsBetweenAttempts = 5 for ($i=0; $i -lt $numAttempts; $i++) { $appxPkg = Get-AppxPackage | Where-Object { $_.name -eq $AppxName } if ($appxPkg -ne $null) { break } Write-Host "Couldn't find Appx package. Trying again in $numSecondsBetweenAttempts seconds (attempt $($i+1) of $numAttempts) ..." -ForegroundColor DarkRed Start-Sleep -Seconds $numSecondsBetweenAttempts } if ($appxPkg -eq $null) { Write-Host 'Failed to find Appx package. Please try running this script again.' -ForegroundColor Red Exit } return $appxPkg } Function Remove-ProviderAppxProvisionedPackage { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxDisplayName ) if ($Script:isNano) { return } # Skip if Nano $appxProvPkg = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -eq $AppxDisplayName } if ($appxProvPkg -ne $null) { Remove-AppxProvisionedPackage -Online -PackageName $appxProvPkg.PackageName 2>&1 | Out-Null Write-Host "Removed AppxProvisionedPackage $($appxProvPkg.PackageName)" } } Function Remove-CmdletsPathFromPSModulePath { # This function removes cmdlet module path(s) from system PSModulePath environment variable. if ($Script:isServerCore) { $appxCmdletsPath = "$env:ProgramFiles\QLogic Corporation\PowerKit\Cmdlets" } else { $appxCmdletsPath = (Get-AppxPackageWrapper -AppxName 'QLGCProvider').InstallLocation + '\Cmdlets' } if (Test-RegistryValue -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Value 'PSModulePath') { $currPSModulePathArr = ((Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment').PSModulePath).Split(';') $newPSModulePathArr = @() # Remove any paths containing 'QLGCProvider' from PSModulePath foreach ($path in $currPSModulePathArr) { if (-not $path.Contains('QLGCProvider')) { $newPSModulePathArr += $path } else { Write-Host "Removed '$path' from PSModulePath." } } $newPSModulePathStr = $newPSModulePathArr -join ';' # Write PSModulePath to registry and set local session variable & setx /s $env:COMPUTERNAME PSModulePath $newPSModulePathStr /m 2>&1 | Out-Null $env:PSModulePath = $newPSModulePathStr } } Function Remove-CLSIDRegistryPaths { if (Test-Path -Path "Registry::HKCR\CLSID\$Script:CLSID") { Remove-Item -Path "Registry::HKCR\CLSID\$Script:CLSID" -Recurse Write-Host "Removed HKCR:\CLSID\$Script:CLSID from registry." } if (Test-Path -Path "HKLM:\Software\Classes\CLSID\$Script:CLSID") { Remove-Item -Path "HKLM:\Software\Classes\CLSID\$Script:CLSID" -Recurse Write-Host "Removed HKLM:\Software\Classes\CLSID\$Script:CLSID from registry." } } Function Uninstall-MofComp { # TODO - Determine if this function is always necessary if ($Script:isServerCore) { $mofCompFilePath = "$env:ProgramFiles\QLogic Corporation\PowerKit\QLGCProviderUninstall.mof" } else { $mofCompFilePath = (Get-AppxPackageWrapper -AppxName 'QLGCProvider').InstallLocation $mofCompFilePath += '\QLGCProviderUninstall.mof' } # $mofcompOutput = & mofcomp.exe -N:root\qlgcfastlinq -class:forceupdate $appxPath\QLGCProviderUninstall.mof 2>&1 $mofcompOutput = & mofcomp.exe -N:root\qlgcfastlinq $mofCompFilePath 2>&1 if ($mofcompOutput -match 'Error') { Write-Host "Failed to unregister `"$mofCompFilePath`": $($mofcompOutput -match 'Error')" -ForegroundColor Red } else { Write-Host "QLGCProvider unregistered." } if (Test-RegistryValue -Path 'HKLM:\Software\Microsoft\Wbem\CIMOM\SecuredHostProviders' -Value 'Root/qlgcfastlinq:__Win32Provider.Name="QLGCProvider"') { Remove-ItemProperty -Path 'HKLM:\Software\Microsoft\Wbem\CIMOM\SecuredHostProviders' -Name 'Root/qlgcfastlinq:__Win32Provider.Name="QLGCProvider"' } } Function Remove-CmdletsFromProgramData { # Remove any ProgramData directories containing 'QLGCProvider_' $progDataPaths = (Get-ChildItem $env:ProgramData | Where-Object { ($_.Name).StartsWith('QLGCProvider_') }).FullName foreach ($path in $progDataPaths) { Remove-Item $path -Recurse -Force Write-Host "Cmdlets removed from `"$path`"." } } Function Remove-CmdletsFromProgramFiles { Remove-Item -Path "$env:ProgramFiles\QLogic Corporation\PowerKit" -Recurse -Force 2>&1 | Out-Null } Function Remove-RESTFilesFromProgramData { # Remove any ProgramData directories containing 'QLGCProviderREST_' $progDataPaths = (Get-ChildItem $env:ProgramData | Where-Object { ($_.Name).StartsWith('QLGCProviderREST_') }).FullName foreach ($path in $progDataPaths) { Remove-Item $path -Recurse -Force Write-Host "REST files removed from `"$path`"." } } Function Remove-AppxPackageWrapper { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxDisplayName ) $appxPkg = Get-AppxPackage | Where-Object { $_.Name -eq $AppxDisplayName } if ($appxPkg -ne $null) { $savedProgressPreference = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' Remove-AppxPackage -Package $appxPkg 2>&1 | Out-Null $Global:ProgressPreference = $savedProgressPreference Write-Host "Removed $AppxDisplayName AppxPackage." } } Function Remove-FromIIS { $appcmd = "$env:SystemRoot\system32\inetsrv\appcmd.exe" # Stop all sites $sites = (& $appcmd list site 2>&1) if ($sites -ne $null) { if ($sites.GetType() -eq [System.String]) { $siteName = $sites.Split('"')[1] $appcmdOutput = (& $appcmd stop site $siteName 2>&1) } else { foreach ($s in $sites) { $siteName = $s.Split('"')[1] $appcmdOutput = (& $appcmd stop site $siteName 2>&1) } } } # Stop DefaultAppPool and MOData apppool $appcmdOutput = (& $appcmd stop apppool /apppool.name:DefaultAppPool 2>&1) $appcmdOutput = (& $appcmd stop apppool /apppool.name:MOData 2>&1) # Delete MOData appool $appcmdOutput = (& $appcmd delete apppool /apppool.name:MOData 2>&1) # Delete MODataSvc app $appcmdOutput = (& $appcmd delete app MODataSvc/MODataSvc 2>&1) # Delete MODataSvc site $appcmdOutput = (& $appcmd delete site MODataSvc 2>&1) Remove-Item "$env:HOMEDRIVE\inetpub\wwwroot\MOData" -Recurse -Force # Start DefaultAppPool apppool $appcmdOutput = (& $appcmd start apppool /apppool.name:DefaultAppPool 2>&1) # Start all sites $sites = (& $appcmd list site 2>&1) if ($sites -ne $null) { if ($sites.GetType() -eq [System.String]) { $siteName = $sites.Split('"')[1] $appcmdOutput = (& $appcmd start site $siteName 2>&1) } else { foreach ($s in $sites) { $siteName = $s.Split('"')[1] $appcmdOutput = (& $appcmd start site $siteName 2>&1) } } } # Remove any existing firewall rules if ((Get-NetFirewallRule | Where-Object { ($_.DisplayName).StartsWith('MOData_IIS_Port') }) -ne $null) { Remove-NetFirewallRule -DisplayName 'MOData_IIS_Port' } Write-Host "Removed from IIS." } Function Test-LastExitCode { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $ExitCode, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Message, [Parameter(Mandatory=$false)] [AllowNull()] [Switch] $ExitScriptIfBadErrorCode ) if ($ExitCode -eq 0) { return; } if (-not $ExitScriptIfBadErrorCode) { Write-Host "WARNING: $Message" -ForegroundColor Yellow } else { Write-Host "ERROR: $Message" -ForegroundColor Red Exit } } #-------------------------------------------------------------------------------------------------- # Globals $Script:CLSID = '{BC33E6C0-DB6A-4781-B924-CB1CDA88E4A1}' $Script:isNano = Test-IfNano $Script:isServerCore = Test-IfServerCore #-------------------------------------------------------------------------------------------------- # Script - Cmdlets Uninstall if (-not $UninstallRESTServerOnly) { if ($Script:isServerCore) { Remove-CmdletsPathFromPSModulePath Remove-CLSIDRegistryPaths Uninstall-MofComp Remove-CmdletsFromProgramFiles } else { Remove-ProviderAppxProvisionedPackage -AppxDisplayName 'QLGCProvider' Remove-CmdletsPathFromPSModulePath Remove-CLSIDRegistryPaths Uninstall-MofComp Remove-CmdletsFromProgramData Remove-AppxPackageWrapper -AppxDisplayName 'QLGCProvider' } Write-Host "Successfully uninstalled FastLinq PowerKit.`n" -ForegroundColor Green } #-------------------------------------------------------------------------------------------------- # Script - Old REST API Uninstall $oldRestIsInstalled = (Get-AppxPackage | Where-Object { $_.Name -eq 'QLGCProviderREST' }) -ne $null if ($oldRestIsInstalled) { Remove-ProviderAppxProvisionedPackage -AppxDisplayName 'QLGCProviderREST' Remove-RESTFilesFromProgramData Remove-AppxPackageWrapper -AppxDisplayName 'QLGCProviderREST' Remove-FromIIS Write-Host 'Successfully uninstalled FastLinq REST API PowerKit.' -ForegroundColor Green } #-------------------------------------------------------------------------------------------------- # Script - New REST API Uninstall $restServerRegistryPath = 'HKLM:\Software\QLogic Corporation\PowerShell Cmdlets REST Server' if (Test-Path -Path $restServerRegistryPath) { # Check if running inside a container $runningInContainer = $env:USERNAME -eq 'ContainerAdministrator' -and $env:USERDOMAIN -eq 'User Manager' # Get values from registry $restServerInstallPath = (Get-ItemProperty -Path $restServerRegistryPath).path $restServerProtocol = (Get-ItemProperty -Path $restServerRegistryPath).protocol $restServerHttpPort = (Get-ItemProperty -Path $restServerRegistryPath).http_port $restServerHttpsPort = (Get-ItemProperty -Path $restServerRegistryPath).https_port $restServerThumbprint = (Get-ItemProperty -Path $restServerRegistryPath).thumbprint # Uninstall Windows service Write-Host "`nUninstalling Windows service" -ForegroundColor Cyan $null = & "$restServerInstallPath\PowerShellCmdletsRestServer.exe" -uninstall Test-LastExitCode -ExitCode $LASTEXITCODE -Message "Failed to uninstall Windows service" -ExitScriptIfBadErrorCode # Wait for service to stop before continuing Write-Host "`nWaiting for service to stop before continuing." -ForegroundColor Cyan $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $timeoutSecs = 60 while ($true) { Start-Sleep -Milliseconds 2500 $service = Get-Service -Name $restServerServiceName -ErrorAction SilentlyContinue if ($service -eq $null) { Write-Host "... service not found with name '$restServerServiceName'; assuming it was successfully deleted." -ForegroundColor Cyan break; } if ($service -ne $null -and $service.Status -eq 'Stopped') { Write-Host '... service stopped!' -ForegroundColor Cyan break; } if ($stopwatch.Elapsed.TotalSeconds -gt $timeoutSecs) { Test-LastExitCode -ExitCode 1 -Message "`n$restServerServiceName service never stopped after $timeoutSecs seconds; giving up." -ExitScriptIfBadErrorCode } Write-Host 'Still waiting for service to stop ...' -ForegroundColor Cyan } # Delete installation directory Write-Host "`nDeleting installation directory" -ForegroundColor Cyan Remove-Item -Path $restServerInstallPath -Recurse -Force if ($restServerProtocol -eq 'http' -or $restServerProtocol -eq 'both') { # Unregister URL with Windows Write-Host "`nUnregistering HTTP URL with Windows" -ForegroundColor Cyan $null = netsh http delete urlacl url="http://localhost:$restServerHttpPort/" Test-LastExitCode -ExitCode $LASTEXITCODE -Message "Failed to unregister HTTP URL with Windows." } if ($restServerProtocol -eq 'https' -or $restServerProtocol -eq 'both') { # Unregister URL with Windows Write-Host "`nUnregistering HTTPS URL with Windows" -ForegroundColor Cyan $null = netsh http delete urlacl url="https://localhost:$restServerHttpsPort/" Test-LastExitCode -ExitCode $LASTEXITCODE -Message "Failed to unregister HTTPS URL with Windows." $null = netsh http delete sslcert ipport="0.0.0.0:$restServerHttpsPort" # Delete certificate if ($restServerThumbprint -ne $null) { Write-Host "`nDeleting HTTPS certificate" -ForegroundColor Cyan dir Cert:\LocalMachine -Recurse | ? Thumbprint -Match $restServerThumbprint | Remove-Item } else { Write-Host "`nNOT deleting HTTPS certificate" -ForegroundColor Cyan } } # Delete Windows registry entries if (Test-Path -Path $restServerRegistryPath) { Write-Host "`nDeleting Windows registry entries" -ForegroundColor Cyan Remove-Item -Path $restServerRegistryPath -Recurse } # Remove any existing firewall rules if (-not $runningInContainer) { $fwRules = Get-NetFirewallRule | Where-Object { ($_.DisplayName).StartsWith('QLogic PowerShell Cmdlets REST Server') } foreach ($fwRule in $fwRules) { Remove-NetFirewallRule -DisplayName $fwRule.DisplayName } } Write-Host "`nSuccessfully uninstalled FastLinq PowerKit REST Server." -ForegroundColor Green } else { Write-Host 'Could not uninstall REST server because it does not seem to be installed.' -ForegroundColor Red } |