PS Script to uninstall Firefox from multiple locations - powershell

I am working on creating a script to uninstall Firefox from multiple locations. I have a script that I've created and it works to an extent. I have made changes to my original script based on the answer below plus some other changes
$LocalUsers = (Get-ChildItem -Path "C:\Users").name
# Uninstalling from Program Files
if (Test-Path "${env:ProgramFiles(x86)}\Mozilla Firefox\uninstall\helper.exe"){
Start-Process -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\uninstall\helper.exe" -ArgumentList '/S' -Verbose #-ErrorAction SilentlyContinue
}
if (Test-Path "${env:ProgramFiles}\Mozilla Firefox\uninstall\helper.exe"){
Start-Process -FilePath "${env:ProgramFiles}\Mozilla Firefox\uninstall\helper.exe" -ArgumentList '/S' -Verbose #-ErrorAction SilentlyContinue
}
# Uninstalling for each user
ForEach ($LocalUser in $LocalUsers){
$Userpath = "C:\Users\" + $LocalUser
if (Test-Path "$Userpath\AppData\Local\Mozilla Firefox\uninstall\helper.exe"){
Start-Process -FilePath "$Userpath\AppData\Local\Mozilla Firefox\uninstall\helper.exe" -ArgumentList '/S' -Verbose #-ErrorAction SilentlyContinue
}
Start-Sleep 20
# Remove shortcuts from appdata
Remove-Item -Path "$userpath\AppData\Local\Mozilla" -Force -Recurse -Verbose #-ErrorAction SilentlyContinue
Remove-Item -Path "$userpath\AppData\LocalLow\Mozilla" -Force -Recurse -Verbose #-ErrorAction SilentlyContinue
Remove-Item -Path "$userpath\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Firefox.lnk" -Force -Verbose #-ErrorAction SilentlyContinue
Remove-Item -Path "$userpath\desktop\firefox.lnk" -Force -Verbose #-ErrorAction SilentlyContinue
}
# Remove related registry keys
$pathToRemove = #(
'HKLM:\Software\Mozilla'
'HKLM:\SOFTWARE\mozilla.org'
'HKLM:\SOFTWARE\MozillaPlugins'
'HKLM:\SOFTWARE\WOW6432Node\Mozilla'
'HKLM:\SOFTWARE\WOW6432Node\mozilla.org'
'HKLM:\SOFTWARE\WOW6432Node\MozillaPlugins'
'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Firefox.lnk'
)
foreach($path in $pathToRemove) {
if(Test-Path $path) {
try {
Remove-Item $path -Recurse -Force -Verbose #-ErrorAction SilentlyContinue
}
catch {
Write-Warning $_.Exception.Message
}
}
}
The script has worked on some machines where it uninstalls the application, however, for others trace of it is being left behind in Windows Program Files. It is appearing as a dead link. I know it is a dead link because it is missing the Firefox logo. The strange thing is its points to %localappdata%\Mozilla Firefox\uninstall\helper.exe per the error
What the app should look like if installed (ignoring the version just a screenshot from online):

I'm assuming the problem is your chained if \ elseif \ else conditions, what could be happening is that if the first condition was $true you're only removing the first registry key and then exiting the chained conditions (this is by design):
# only results in 'hello if' and then exits the chained conditions
if($true) {
'hello if'
}
elseif($true) {
'hello elseif'
}
What you can do in this case is store all the paths in an array and then loop over them, testing if the path exists and, if it does, remove it:
$pathToRemove = #(
'HKLM:\Software\Mozilla'
'HKLM:\SOFTWARE\mozilla.org'
'HKLM:\SOFTWARE\MozillaPlugins'
'HKLM:\SOFTWARE\WOW6432Node\Mozilla'
'HKLM:\SOFTWARE\WOW6432Node\mozilla.org'
'HKLM:\SOFTWARE\WOW6432Node\MozillaPlugins'
'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Firefox.lnk'
)
foreach($path in $pathToRemove) {
if(Test-Path $path) {
try {
Write-Verbose "Attempting to remove: $path" -Verbose
Remove-Item $path -Recurse -Force
Write-Verbose "Successfully removed: $path" -Verbose
}
catch {
Write-Warning $_.Exception.Message
}
}
}

Related

Powershell Start-Process for Teams

I use the following script to clear the cache of—and start—Teams.
It worked as expected for some time. Now I get some strange behaviours like:
When I close powershell, Teams closes too
Before I close PS there appear some errors
# start Teams
# Start-Process -File "C:\Program Files (x86)\Microsoft\Teams\current\Teams.exe" -ArgumentList '--processStart "Teams.exe"'
# Write-Host "Teams Process Sucessfully Started"
# Start-Sleep -Seconds 5
#Stop Teams process
Get-Process -ProcessName Teams -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 3
Write-Host "Teams Process Sucessfully Stopped"
#Clear Team Cache
try{
# Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams" | Remove-Item -Recurse -ErrorAction SilentlyContinue # Clear.all
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\blob_storage" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\databases" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\cache" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\gpucache" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\Indexeddb" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\Local Storage" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:APPDATA\"Microsoft\Teams\tmp" | Remove-Item -Recurse -ErrorAction SilentlyContinue
Write-Host "Teams Cache Cleaned"
}catch{
echo $_
}
#Remove Credential from Credential manager
$credential = cmdkey /list | ForEach-Object{if($_ -like "*Target:*" -and $_ -like "*msTeams*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}}
#Remove Reg.Key
$Regkeypath= "HKCU:\Software\Microsoft\Office\Teams"
$value = (Get-ItemProperty $Regkeypath).HomeUserUpn -eq $null
If ($value -eq $False)
{
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Office\Teams" -Name "HomeUserUpn"
Write-Host "The registry value Sucessfully removed"
}
Else { Write-Host "The registry value does not exist"}
#Get Desktop-config.json
$TeamsFolders = "$env:APPDATA\Microsoft\Teams"
try{
$SourceDesktopConfigFile = "$TeamsFolders\desktop-config.json"
$desktopConfig = (Get-Content -Path $SourceDesktopConfigFile | ConvertFrom-Json)
}
catch{ Write-Host "Failed to open Desktop-config.json" }
#Overwrite the desktop-config.json
Write-Host "Modify desktop-Config.Json"
try{
$desktopConfig.isLoggedOut = $true
$desktopConfig.upnWindowUserUpn =""; #The email used to sign in | also: whoami /upn
$desktopConfig.userUpn ="";
$desktopConfig.userOid ="";
$desktopConfig.userTid = "";
$desktopConfig.homeTenantId ="";
$desktopConfig.webAccountId="";
$desktopConfig | ConvertTo-Json -Compress | Set-Content -Path $SourceDesktopConfigFile -Force
}
catch{ Write-Host "Failed to overwrite desktop-config.json" }
Write-Host "Modify desktop-Config.Json - Finished"
#Delete the Cookies file. This is a fix for when the joining as anonymous, and prevents the last used guest name from being reused.
Get-ChildItem "$TeamsFolders\Cookies" | Remove-Item
#Lastly delete the storage.json, this corrects some error that MSTeams otherwise would have when logging in again.
Get-ChildItem "$TeamsFolders\storage.json" | Remove-Item
#Try to remove the Link School/Work account if there was one. It can be created if the first time you sign in, the user all
# $LocalPackagesFolder ="$env:LOCALAPPDATA\Packages"
# $AADBrokerFolder = Get-ChildItem -Path $LocalPackagesFolder -Recurse -Include "Microsoft.AAD.BrokerPlugin_*";
# $AADBrokerFolder = $AADBrokerFolder[0];
# Get-ChildItem "$AADBrokerFolder\AC\TokenBroker\Accounts" | Remove-Item -Recurse -Force
# Start-Sleep -Seconds 5
# start Teams
Start-Process -File "C:\Program Files (x86)\Microsoft\Teams\current\Teams.exe" -ArgumentList '--processStart "Teams.exe"'
# "$($env:USERProfile)\AppData\Local\Microsoft\Teams\Update.exe"
Start-Sleep -Seconds 3
Write-Host "Teams Process Sucessfully Started"
# Stop for testpurposes
pause
SIDENOTE
Teams is installed as per Microsoft recommendation for VDI setups.
(Citrix VDI/VDA, HDX Optimized)
It worked as expected for some time. Now I get some strange behaviours like:
When I close powershell, Teams closes too
Before I close PS there appear some errors
Screenshot of errors

Powershell - ForEach loop running twice on the same path instead of moving on next one

I am looking to move files from various paths to E:\backups\folder1\export, E:\Backups\folder2\backups, E:\backups\folder3\export and using below code...but strangely it runs twice on the same path and doesn't move to next path and duplicates the output too.
Cls
$date = Get-Date -Format "yyyMMdd_hhmmss"
#$sourcePath = "C:\Program Files\Atlassian\Application Data\JIRA\export\"
#$destPath = "E:\Backup\Jira\export"
$config = Import-Csv -Path 'E:\Backup\Scripts\Atlassian_Backups.csv'
#Write-Output $config
Start-Transcript -Path E:\Backup\Logs\Atlassian_backupMove.log
foreach ($item in $config)
{
Write-Host "Moving all files in '$($sourcePath)' to '$($destPath)'"
$fileList = #(Get-ChildItem -Path "$($sourcePath)" -File)
#Write-Output $fileList
if ($filelist.count -gt 0)
{
Write-host $filelist.Count
ForEach($file in $fileList)
{
try {
#Move-Item -Path $file.FullName -Destination ((Split-Path
$file.FullName).Replace("$($sourcePath)",$destPath)) -Force -ErrorAction Stop
Copy-Item -Path $file.FullName -Destination $destPath -Verbose -Force -ErrorAction Stop |
Format-table
}
catch{
Write-Warning "Unable to move '$($file.FullName)' to '$(((Split-Path
$file.FullName).Replace("$($sourcePath)",$destPath)))': $($_)"
return
}
}
}
}
Stop-Transcript
Rename-Item E:\Backup\Logs\Atlassian_backupMove.log
E:\Backup\Logs\Atlassian_backupMove_$date.log
write-host Log File has been created and renamed to Atlassian_backupMove_$date.log'
below was changed in my code and worked well.
{#Move-Item -Path $file.FullName -Destination ((Split-Path
$file.FullName).Replace("$($sourcePath)",$destPath)) -Force -ErrorAction Stop
Copy-Item -Path $file.FullName -Destination $item.destPath -Verbose -Force -
ErrorAction Stop | Format-table } catch{ Write-Warning "Unable to move
'$($file.FullName)' to '$(((Split-Path
$file.FullName).Replace("$($item.sourcePath)",$item.destPath)))': $($_)" return
}

Capture the messages by cmdlets in PowerShell

I am running the below script. If the Copy-Item command is successfully completed, it does not show any messages such as how many files are copied. How do I capture this?
Note: I also need to capture the error message which the script is doing correctly.
$LogFile = "P:\users\Logname.log"
$msg = Copy-Item P:\Bkp_20130610\* P:\users -force -recurse -ErrorAction SilentlyContinue
if (-not $?)
{
msg1 = $Error[0].Exception.Message
Write-Host "Encountered error. Error Message is $msg1."
exit
}
$msg > $LogFile
Write-Host "Hello"
You can obtein a list of copied files in this way
$files = copy-item -path $from -destination $to -passthru
pipe it to | ? { -not $_.psiscontainer } if you are copying folder and you don't want them in the count
then use
$files.count
You can use the -Verbose switch with the Copy-Item cmdlet:
$msg=Copy-Item P:\Bkp_20130610\* P:\users -force -recurse -ErrorAction SilentlyContinue -Verbose

COPY-ITEM Passthru not working when encountering error

Within ISE, I've tried both the below. Neither is working. The only way is to clear $error and test after the copy attempt. Any suggestions?
$cpy = Copy-Item -Path "D:\~a\2K0NVK0.xt" -Destination "D:\~Bkup-F\2K0NVK10.txt" -Force -passthru -ErrorAction SilentlyContinue
if($cpy){ $cpy # only displays on successful copy }
Try{
Copy-Item -Path "D:\~a\2K0NVK0.xt" -Destination "D:\~Bkup-F\2K0NVK10.txt" -Force -ErrorAction SilentlyContinue
} Catch { write-host "Hit a bug!" # not being displayed }
A try/catch only works when ErrorAction is set to Stop.

Copying files from one source to multiple destinations in parallel

I'm attempting to write a microsoft powershell script which copies files from a single source to multiple destinations in parallel based on a config file. The config file is a CSV file which looks like this:
Server,Type
server1,Production
server2,Staging
My script is called with one argument (.\myscript.ps1 buildnumber) but it doesn't seem to actually do any deleting or copying of files.
I'm sure my copy-item and remove-item code works as I have tested them independently but I think its either an issue with how I am using script blocks or perhaps how I am using start-job.
Could anyone help me understand why this isn't working?
Thanks
Brad
<#
File Deployment Script
#>
#REQUIRES -Version 2
param($build)
$sourcepath = "\\server\software\$build\*"
$Config = import-csv -path C:\config\serverlist.txt
$scriptblock1 = {
$server = $args[0]
$destpath1 = "\\$server\share\Software Wizard\"
$destpath2 = "\\$server\share\Software Wizard V4.9XQA\"
remove-item "$destpath1\*" -recurse -force
remove-item "$destpath2\*" -recurse -force
copy-item $sourcepath -destination $destpath1 -recurse -force
copy-item $sourcepath -destination $destpath2 -recurse -force
}
$scriptblock2 = {
$server = $args[0]
$destpath = "\\$server\share\Software Wizard\"
#remove-item "$destpath\*" -recurse -force
copy-item $sourcepath -destination $destpath -recurse -force
}
foreach ($line in $Config) {
$server = $line.Server
$type = $line.Type
if ($type -match "Staging") {
Write-Host "Kicking job for $server off"
start-job -scriptblock $scriptblock2 -ArgumentList $server
}
if ($type -match "Production") {
Write-Host "Kicking job for $server off"
start-job -scriptblock $scriptblock2 -ArgumentList $server
}
}
Your script block doesn't have access to variables declared outside of it when it's called from start-job. So $scriptblock1 and $scriptblock2 can't see $sourcepath.
To elaborate on Jamey's answer, you can see that the $sourcepath variable declared in the caller scope is not available within the job by comparing the output of the two calls below:
$sourcepath = 'source path'
$scriptblock = { Write-Host "sourcepath = $sourcepath; args = $args" }
& $scriptblock 'server name'
Start-Job $scriptblock -ArgumentList 'server name' | Wait-Job | Receive-Job
To fix this, simply pass the outer variable as part of the argument list:
$scriptblock2 = {
param($sourcepath, $server)
$destpath = ...
Copy-Item $sourcepath -Destination $destpath -Recurse -Force
}
...
Start-Job -Scriptblock $scriptblock2 -ArgumentList $sourcepath,$server