Cannot uninstall application using Powershell - powershell

I am trying to upgrade an application using an .msp file but every time I run the script I get a message saying the product I'm trying to upgrade from does not exist. My thought was there might be a bug in the original MSI so I decided to uninstall the application and a full install to the new version. When I run the script to Uninstall it works on some machines but not on others. When I try to uninstall using powershell it fails. When I use MSIEXEC /X I get the following message
"This action is only valid for products that are currently installed".
Next I decided to try and repair using MSIEXEC /fa and I get this:
"This installation package cannot be opened. Verify that the package exists and that you can access it, or contat the application vendor to verify tat this is a valid Winds Installer package"
The strange thing is I can uninstall the application with no problems from Add\Remove programs with not issues and install the upgrade. The problem with this is that I have over 3000 users. From SCCM, I tried to supercede the old version to uninstall before installing the new version and that also failed. Any help you guys can provide would be helpful. The application is Taxprep Forms 2021.1.0 upgrading to 2021.2.0. i have added 2 of the scripts I tried.
For this script I tried doing a repair first then uninstall. I also tried using both product code and app name:
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Bypass
$uninstall32 = gci “HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\” | foreach { gp $_.PSPath } | ? { $_ -match “Taxprep Forms 2021” } | select UninstallString
$uninstall64 = gci “HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\” | foreach { gp $_.PSPath } | ? { $_ -match “Taxprep Forms 2021” } | select UninstallString
if ($uninstall64) {
$uninstall64 = $uninstall64.UninstallString -Replace “msiexec.exe”,”” -Replace “/I”,”” -Replace “/X”,””
$uninstall64 = $uninstall64.Trim()
Write "Repairing Old install..."
Start-Process "msiexec.exe" -arg "/fa $uninstall64" -Wait
Write “Uninstalling…”
start-process “msiexec.exe” -arg “/X$uninstall64 /qb” -Wait}
if ($uninstall32) {
$uninstall32 = $uninstall32.UninstallString -Replace “msiexec.exe”,”” -Replace “/I”,”” -Replace “/X”,””
$uninstall32 = $uninstall32.Trim()
Write "Repairing Old install..."
Start-Process "msiexec.exe" -arg "/fa $uninstall32" -Wait
Write “Uninstalling…”
start-process “msiexec.exe” -arg “/X$uninstall32 /qb” -Wait}
I also tried:
Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Bypass -Force
$DisplayName = "Taxprep Forms 2021"
$TaxprepCheck = (Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where { $_.DisplayName -eq $DisplayName}) -ne $null
$PublicUser = "C:\Users\Public\CCH\Taxprep Forms 2021\"
$UnInstallCheck = "C:\Users\Public\CCH\Taxprep Forms 2021\Forms2021Uninstall.txt"
$Uninstalled = "C:\Logs\TaxprepForms2021.1.0Uninstalled.txt"
$TaxprepVer = Get-WmiObject -Class Win32_Product | Where-Object{$_.Name -eq $DisplayName}
If(-Not $TaxprepCheck)
{
New-Item $Uninstalled -Force -ErrorAction Stop
Set-Content $Uninstalled "Taxprep Forms 2021.1.0 is not installed"
}
else
{
$TaxprepVer.Uninstall()
New-Item $Uninstalled -Force -ErrorAction Stop
Set-Content $Uninstalled "Taxprep Forms 2021.1.0 is successfully Uninstalled"
}
If (Test-Path -Path $PublicUser)
{
New-Item $UnInstallCheck -Force -ErrorAction Stop
Set-Content $UnInstallCheck "Taxprep Forms 2021.1.0 Uninstalled"
}
Else
{
New-Item -ItemType "directory" -Path $PublicUser
New-Item $UnInstallCheck -Force -ErrorAction Stop
Set-Content $UnInstallCheck "Taxprep Forms 2021.1.0 Uninstalled"
}
I have verified that the application is installed. It's in the registry. These scripts work on some computer and not on others. The machines it doesnt work on I have to uninstall the application through add\remove.

Ok so it seemed I may have caused my own issue. When I initially deployed the application in SCCM, I set the User experience to “Install as User”. The switch I used when calling msiexec was All Users = 2. I switched the install to “Install for System and set All Users = “”. I would need to deploy the msi and do a full install rather than an upgrade using the msp. Installing as User may have messed up the registry setting for the initial install.

Related

PowerShell Start-Process Not Starting when script called remotely

I am trying to remotely install Octopus Deploy Tentacle to a VM. I have a powershell script that I've written that handles this business for me. It works exactly as expected when I am physically logged into the machine, but when I am remotely executing it on the machine it doesn't run the installer. Every other part of the script works fine though.
The portion of the script that downloads and installs:
try{
$url = "https://octopus.com/downloads/latest/OctopusTentacle64"
$downloadPath = "$env:TEMP\octopus\"
if (Test-Path $downloadPath) {
Remove-Item -Path $downloadPath -Recurse -Force
}
New-Item -Type Directory -Path $downloadPath | Out-Null
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($url, "$downloadPath\Octopus.Tentacle.msi")
Start-Process -FilePath "$downloadPath\Octopus.Tentacle.msi" -ArgumentList "/passive" -Wait -verbose
Write-Output "Octopus Tentacle Installed."
} catch { throw "error downloading tentacle. try again later."}
I am using this to attempt to run the file remotely(edit, copied wrong line):
Invoke-Command -ComputerName $vmName -FilePath "\\$vmName\Installers\Install-Calamari.ps1" -Credential $creds -ArgumentList $deployTag, $envID
What am I missing?

Powershell Popup Box not showing when installing through SCCM

Not sure how to fix it but I think i have a hunch on why
I have a powershell script installs an applications but before it kicks off it shows a msgbox that simply displays a message to the user
The script works perfectly when I run it manually and even running it as the System account through psexec works as well
However when deploying this through SCCM - Software center, it installs without displaying the msgbox..
Now I think it might be because its not showing in the context of the current logged in user.. but I would of thought running it through Psexec as system would not work either...
Can anyone help? I have deployed it as an application through sccm using this script:
<#
.Date: 01-Jun-2016
.Ansys 16.2 Install Script
# Set up some Variables
$workingDirectory = (split-path $myinvocation.mycommand.path -parent)
# Display a warning message before installation begins
Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.Interaction]::MsgBox('Ansys 16.2 takes over 30 mins to install. Please do not log out or shutdown your computer during the installation. You can continue working as normal while it is being installed. Once complete you will see in Software Center say "installed" next to Ansys 16.2.', 'OKOnly,SystemModal,Exclamation', 'Warning')
# ***** Install Application ******
Start-Process -FilePath "$WorkingDirectory\ANSYS162_WINX64_Disk1\setup.exe" -ArgumentList "-silent -disablerss -licserverinfo `"::licensing-b`"" -Wait -ErrorAction SilentlyContinue
Start-Sleep -s 3
# ***** Delete Shortcut and unlicensed products *******
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\Uninstall ANSYS 16.2.lnk" -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ANSYS Icepak 16.2.lnk" -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\Aqwa" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ACP" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\ANSYS 16.2\ANSYS Client Licensing" -Recurse -Force -ErrorAction SilentlyContinue "#>
Make sure that you have checked "allow the user to interact with this program" option while deployment
click here to see how to set user interaction

Automate process of Disk Cleanup cleanmgr.exe without user intervention

I am developing a powershell script file which shall execute some disk cleanup without user intervention. The user shall not be able to configure anything.
When I run cleanmgr.exe /d c: sageset:1 a popup window appears to select files/folders to be cleaned(cleanup options).
This will create a registry entry containing the settings with the cleanup options and after this, you can run cleanmgr.exe /sagerun:1 which will actually execute the cleanup.
Is there a way to specify the cleanup options directly with powerhell/command line(without the need to manually select things to be deleted)?
The following Powershell script automates CleanMgr.exe. In this case, it removes temporary files and runs the Update Cleanup extension to purge superseded Service Pack Backup files (Windows 10 now does this automatically via a scheduled task). To automate other extensions, create a "StateFlags0001" property in the corresponding Registry key, as done in the New-ItemProperty lines. You will find the Registry key names in the "VolumeCaches" branch.
As far as being silent, this script attempts to start CleanMgr.exe in a hidden window. However, at some point CleanMgr spawns new processes which are visible and must be waited on separately.
Write-Host 'Clearing CleanMgr.exe automation settings.'
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' -Name StateFlags0001 -ErrorAction SilentlyContinue | Remove-ItemProperty -Name StateFlags0001 -ErrorAction SilentlyContinue
Write-Host 'Enabling Update Cleanup. This is done automatically in Windows 10 via a scheduled task.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Update Cleanup' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Enabling Temporary Files Cleanup.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Files' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Starting CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden -Wait
Write-Host 'Waiting for CleanMgr and DismHost processes. Second wait neccesary as CleanMgr.exe spins off separate processes.'
Get-Process -Name cleanmgr,dismhost -ErrorAction SilentlyContinue | Wait-Process
$UpdateCleanupSuccessful = $false
if (Test-Path $env:SystemRoot\Logs\CBS\DeepClean.log) {
$UpdateCleanupSuccessful = Select-String -Path $env:SystemRoot\Logs\CBS\DeepClean.log -Pattern 'Total size of superseded packages:' -Quiet
}
if ($UpdateCleanupSuccessful) {
Write-Host 'Rebooting to complete CleanMgr.exe Update Cleanup....'
SHUTDOWN.EXE /r /f /t 0 /c 'Rebooting to complete CleanMgr.exe Update Cleanup....'
}
The PowerShell logic provided below is dynamic and ready for use or automation with the sageset options all being selected and no user interaction being required. This was inspired by multiple answers and comments from this post.
Note: I've adjusted for my needs and used successfully without any issues on multiple remote and local Windows 10 systems in particular.
Run on Local System
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' ##-WindowStyle Hidden
Run on Remote System
$cred = Get-Credential "domain\administrator";
Invoke-Command -ComputerName "computer004" {
Process {
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden
}
} -AsJob -Credential $cred
Supporting Resources
cleanmgr
Invoke-Command
-AsJob
Run the command as a background job on a remote computer.
Use this parameter to run commands that take an extensive time to complete.
Get-Credential
Automate process of Disk Cleanup cleanmgr.exe without user intervention
Creating a Disk Cleanup Handler
You can use cleanmgr /verylowdisk to silently automate all the cleanup steps.
The only solution I found is to manually set the registry values like this:
...
#Set StateFlags0012 setting for each item in Windows 8.1 disk cleanup utility
if (-not (get-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -ErrorAction SilentlyContinue)) {
set-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\BranchCache' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Downloaded Program Files' -name StateFlags0012 -type DWORD -Value 2
...
see full example
I ran into the same issue. Researching the possible ways, I have found the following:
http://stealthpuppy.com/cleaning-up-and-reducing-the-size-of-your-master-image/
It shows how to create the sageset registry settings via cmd. You can then use the sagerun:# cmd. I have not tried it via script yet, but have validated that it works...
This script will get all the Volume Caches from the Registry, enable them to be cleaned and run the CLEANMGR.EXE for all caches.
$VolumeCachesRegDir = "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$CacheDirItemNames = Get-ItemProperty "$VolumeCachesRegDir\*" | select -ExpandProperty PSChildName
$CacheDirItemNames |
%{
$exists = Get-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name "StateFlags6553" -ErrorAction SilentlyContinue
If (($exists -ne $null) -and ($exists.Length -ne 0))
{
Set-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 2
}
else
{
New-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 0 -PropertyType DWord
}
}
Start-Sleep -Seconds 3
Write-Host 'Running CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:65535' -WindowStyle Hidden -PassThru
cls
Running CleanMgr.exe in a powershell script or by itself seems to work fine as long as you run it locally with an account that has local admin rights. But try running it remotely via any remote management tool or remote scripting command (Invoke-Command) and it does not run. You might see the process running on the remote system but it doesn't seem to cleanup anything and the process never ends. I would be interested if anyone has been able to get cleanmgr.exe to run remotely without any user interaction. E.G. ConfigMgr Right Click Tools, ConfigMgr App or PKG, Task Scheduler.

Uninstalling software on a remote client using powershell

I'm looking for a script that will help me uninstall a certain software on several clients in my network.
Right now i'm going through a list, access the client remotely, sign in with my administrator account and uninstalling the software before logging out and repeating the process. All of this is manually so i would like your help to write a powershell script that does these things for me.
Some Problems that might occur:
I can't log in remotely because i can't establish a connection to the client.
Another user might already be logged in on the client.
The software to be uninstalled is actually already uninstalled without my knowledge.
It's somewhere around 900 clients so a script would really help out.
Also, if it would be possible to, after the script is finished, to get a list of which clients that the software was uninstalled on and which clients it weren't would be great.
Questions written like this are likely to elicit 'What have you tried' type responses...
I would recommend using the Windows Installer Powershell Module Uninstall-MSIProduct.
I've described how to use this module remotely in this post: remote PCs using get-msiproductinfo, this example uses Get-MSIProductInfo but could be easily updated to use Uninstall-MSIProduct.
I've had a quick go at changing this to use Uninstall-MSIProduct, but haven't tested it.
[cmdletbinding()]
param
(
[parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipelineByPropertyName=$true)]
[string]
$computerName,
[string]
$productCode
)
begin
{
write-verbose "Starting: $($MyInvocation.MyCommand)"
$scriptFolder = Split-Path -Parent $MyInvocation.MyCommand.Path
$moduleName = "MSI"
$modulePath = Join-Path -Path $scriptFolder -ChildPath $moduleName
$remoteScript = {
param($targetPath,$productCode)
Import-Module $targetPath
uninstall-msiproduct -ProductCode $productCode
}
$delayedDelete = {
param($path)
Remove-Item -Path $path -Force -Recurse
}
}
process
{
$remotePath = "\\$computerName\c$\temp\$moduleName"
write-verbose "Copying module to $remotePath"
Copy-Item -Path $modulePath -Destination $remotePath -Recurse -Container -Force
write-verbose "Getting installed products"
Invoke-Command -ComputerName $computerName -ScriptBlock $remoteScript -ArgumentList "c:\temp\$moduleName", $productCode
write-verbose "Starting job to delete $remotePath"
Start-Job -ScriptBlock $delayedDelete -ArgumentList $remotePath | Out-Null
}
end
{
write-verbose "Complete: $($MyInvocation.MyCommand)"
}

Powershell in NonInteractive mode

I use Octopus for our deployments. I have a problem with one of the Powershell scripts to control the deployment:
# stops running processes
$processes = #("Notepad",
"Firefox")
foreach ($process in $processes)
{
$prc = Get-Process -Name $process -ErrorAction SilentlyContinue
if (-not($prc -eq $null))
{
Write-Host "Stopping " $prc.ProcessName
Stop-Process -InputObject $prc -ErrorAction SilentlyContinue
}
}
The programs I try to stop are not the ones you see in the script above, but they represent what I am trying to do. Now the problem I have with it, is that it works well on one server, but not on another. Where it does not work, I get the error message:
Stop-Process : Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
The script that works runs on Powershell 3.0, the one that does not work on Powershell 2.0. I cannot upgrade to Powershell 3.0 everywhere yet because the old servers run with Windows Server 2003. How can I make it work on PS 2.0?
Run with -Force:
Stop-Process -InputObject $prc -ErrorAction SilentlyContinue -Force
As C.B. suggested in the comment: -confirm:$false should also work. Rationale for this is as follows: -Confirm is a switch parameter. Switch parameters can only take arguments if you specify the parameter with a trailing colon and a value.
I just tried to use Remove-Item on the directory with children and got same message:
Remove-Item : PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.
In my case -Recurse key has helped.