I am working towards writing a powershell script for uninstalling the current version 54.0.2840.99 m of Google Chrome from my machine but could not be able to do so. I am using the following piece of code in my script:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match “Google Chrome”}
$app.Uninstall()
The chrome is installed in my machine but the above code is not showing Google Chrome in the list. It is returning null value and it could not be able to uninstall.
Could you please tell me where i have been went wrong or any other alternative solution for uninstalling the Google Chrome via PowerShell?
Google Chrome doesn't use WMI when installing chrome. You can use the command below to find the version, and uninstall chrome using its setup package.
(Get-ItemProperty -path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome').version | ForEach-Object {& ${env:ProgramFiles(x86)}\Google\Chrome\Application\$_\Installer\setup.exe --uninstall --multi-install --chrome --system-level --force-uninstall}
I use this:
$GoogleChrome = [CimInstance](Get-CimInstance -ClassName Win32_Product | Where-Object {$_.Name -eq 'Google Chrome'})
If ($GoogleChrome -ne $null) {
Write-Host 'Uninstalling Google Chrome'$GoogleChrome.Version
Invoke-CimMethod -InputObject $GoogleChrome -MethodName 'Uninstall' | Out-Null
}
The search for the uninstaller takes longer than I would like, but it works for the 64-bit version of Google Chrome we use.
There might have been some changes with Chrome that gave me some trouble with the solutions above. This worked for me just recently, and it will work with some other software packages too. It also gives a good basis for confirming the package is no longer installed:
$target_computers='computer1','computer2','computer3'
$software_to_remove='chrome'
Get-PSSession | Remove-PSSession
$target_sessions=New-PSSession -ComputerName $target_computers
if ($software_to_remove -Like 'chrome') {
Invoke-Command -Session (Get-PSSession) -ScriptBlock{
$computer_name=$env:COMPUTERNAME
$chrome_installed_object=(Get-ItemProperty -path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome')
if ($chrome_installed_object -ne $null) {
$chrome_version=($chrome_installed_object | select-object -ExpandProperty Version)
$chrome_uninstaller_string=($chrome_installed_object | Select-Object -ExpandProperty UninstallString)
$chrome_uninstaller_full_string=($chrome_uninstaller_string+" --force-uninstall")
Write-Host "For $computer_name, we have found the following version of Chrome: $chrome_version"
Write-Host "Removing version $chrome_version"
Write-Host "This is the Chrome uninstall string we are using: $chrome_uninstaller_full_string"
cmd.exe /c $chrome_uninstaller_full_string
}
}
}
Invoke-Command -Session (Get-PSSession) -ScriptBlock{
param($software_to_remove)
$computer_name=$env:Computername
#Look at installed programs
Write-Host ("Looking for a package matching this pattern: "+$software_to_remove+" on server "+$computer_name)
$program_to_remove = $(Get-WmiObject -Class Win32_Product | Where-Object -Property Name -Like "*$software_to_remove*")
if (![string]::IsNullOrWhiteSpace($program_to_remove)) {
Write-Host "These programs have been located: $program_to_remove"
$oktoremove=$(Read-Host "OK to remove these programs (y or n)?")
If (!($oktoremove -eq 'y')) {
Write-Host 'Exiting the entire script on server $computer_name since you do not wish to take any further action now'
exit
}
$program_to_remove.Uninstall()
}
#Look at installed packages
$PackageToRemove=$(Get-Package -Provider Programs -IncludeWindowsInstaller | Where-Object -Property Name -Like "*$software_to_remove*")
$PackageToRemove_name=$(Get-Package -Provider Programs -IncludeWindowsInstaller | Where-Object -Property Name -Like "*$software_to_remove*" | Select-Object -ExpandProperty Name)
if (![string]::IsNullOrWhiteSpace($PackageToRemove)) {
Write-Host "$PackageToRemove_name"
$oktoremove=$(Read-Host "OK to remove software (y or n)?")
If (!($oktoremove -eq 'y')) {
Write-Host 'Exiting the entire script on server $computer_name since you do not wish to take any further action now'
exit
}
Uninstall-Package -Name $PackageToRemove -Verbose -Force
}
#Just in case the previous approach did not remove the package successfully, use the GUID this time
Get-Package -Provider Programs -IncludeWindowsInstaller | Where-Object -Property Name -Like "*$software_to_remove*" | Uninstall-Package
#Check again, just to make sure
$x86Path = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
$installedItemsX86 = Get-ItemProperty -Path $x86Path | Select-Object -Property PSChildName, DisplayName, DisplayVersion
$x64Path = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
$installedItemsX64 = Get-ItemProperty -Path $x64Path | Select-Object -Property PSChildName, DisplayName, DisplayVersion
$installedItems = $installedItemsX86 + $installedItemsX64
$installedItems | Where-Object -FilterScript { $null -ne $_.DisplayName } | Sort-Object -Property DisplayName | ft
} -ArgumentList($software_to_remove)
Related
I'm writing a script in PowerShell-ISE that allows me to ping a computer list and exports the pings associated with each computer as well as the OS version into a CSV. Below is what I got so far. I'm not exactly sure where to put the Test-Connection in here.
$good = "C:\Users\1521599002A\Desktop\good.csv"
$bad = "C:\Users\1521599002A\Desktop\bad.csv"
$Computers = Import-Csv -Path "C:\Users\1521599002A\Desktop\complist.txt" -Header "Name"
foreach ($Computer in $Computers) {
try {
Get-ADComputer -Identity $Computer.Name -Properties Name, operatingSystem |
Select Name, operatingSystem
Out-File -FilePath $good -InputObject "$Computer" -Append -Force
} catch {
$Computer.Name + " not in AD"
Out-File -FilePath $bad -InputObject "$Computer" -Append -Force
}
}
I have recently started my journey with Powershell. My IT manager thought it would be a good idea to give me projects to complete. I am understanding Powershell more and more but I have run into quite the road block and need some assistance. The ConvertTo-HTML at the end of my code works, as in I get the file I need in the specified directory. However, I cannot get data to show in the HTM file. Any suggestions? Again, this is my very first script I have attempted on my own.
$computers = Get-ADComputer -Filter {Name -like '[enternamehere]*'} | Select -Expand DNSHostName
foreach ($computer in $computers)
{
Invoke-Command -Computer $computer -scriptblock {
(Get-WmiObject -Class Win32_ComputerSystem -Property Name).Name
Get-ScheduledTask -TaskName *[entertasknamehere]* | Get-ScheduledTaskInfo
}
}
ConvertTo-Html | Out-file -FilePath "[enterfilepathhere]"
I'm trying to gather certificate extensions into a csv. The PowerShell commands seem to display just fine within PowerShell but when piped to a csv they display other types of data?
$cert = Get-ChildItem cert:\localmachine -Recurse
($cert.Extensions | Where-Object {$_.Oid.FriendlyName -eq "Key Usage"}).Format(1) | Export-Csv C:\Folder\File.csv
After searching the web I tried something different but still was unable to get the data to get captured and displayed as it does within PowerShell.
$cert=Get-ChildItem cert:\localmachine -Recurse
$sanExt=$cert.Extensions | Where-Object {$_.Oid.FriendlyName -match "subject alternative name"}
$sanObjs = new-object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
$altNamesStr=[System.Convert]::ToBase64String($sanExt.RawData)
$sanObjs.InitializeDecode(1, $altNamesStr)
Foreach ($SAN in $sanObjs.AlternativeNames) {$SAN.strValue}
$sanExt.Format(1) | Export-Csv C:\Folder\File.csv
For others looking to also gather the extension fields, this was my resolution:
$cert = Get-ChildItem cert:\localmachine -Recurse
($cert.Extensions | Where-Object {$_.Oid.FriendlyName -eq "Key Usage"}).Format(1) |
Select-Object -Property #{Name="Certificate";Expression={$_}} |
Export-csv -Path C:\Folder\file.csv`
I wrote a powershell script to compare the content of two folders:
$Dir1 ="d:\TEMP\Dir1"
$Dir2 ="d:\TEMP\Dir2"
function Test-Diff($Dir1, $Dir2) {
$fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
$fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
if($fileList1.Count -ne $fileList2.Count) {
Write-Host "Following files are different:"
Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property Name -PassThru | Format-Table FullName
return $false
}
return $true
}
$i = Test-Diff $Dir1 $Dir2
if($i) {
Write-Output "Test OK"
} else {
Write-Host "Test FAILED" -BackgroundColor Red
}
If I set a break point on Compare-Object, and I run this command in console, I get the list of differences. If I run the whole script, I don't get any output. Why?
I'm working in PowerGUI Script Editor, but I tried the normal ps console too.
EDIT:
The problem is the check on the end of the script.
$i = Test-Diff $Dir1 $Dir2
if($i) {
Write-Output "Test OK"
...
If I call Test-Diff without $i = check, it works!
Test-Diff returns with an array of objects and not with an expected bool value:
[DBG]: PS D:\>> $i | ForEach-Object { $_.GetType() } | Format-Table -Property Name
Name
----
FormatStartData
GroupStartData
FormatEntryData
GroupEndData
FormatEndData
Boolean
If I comment out the line with Compare-Object, the return value is a boolean value, as expected.
The question is: why?
I've found the answer here: http://martinzugec.blogspot.hu/2008/08/returning-values-from-fuctions-in.html
Functions like this:
Function bar {
[System.Collections.ArrayList]$MyVariable = #()
$MyVariable.Add("a")
$MyVariable.Add("b")
Return $MyVariable
}
uses a PowerShell way of returning objects: #(0,1,"a","b") and not #("a","b")
To make this function work as expected, you will need to redirect output to null:
Function bar {
[System.Collections.ArrayList]$MyVariable = #()
$MyVariable.Add("a") | Out-Null
$MyVariable.Add("b") | Out-Null
Return $MyVariable
}
In our case, the function has to be refactored as suggested by Koliat.
An alternative to adding Out-Null after every command but the last is doing this:
$i = (Test-Diff $Dir1 $Dir2 | select -last 1)
PowerShell functions always return the result of all the commands executed in the function as an Object[] (unless you pipe the command to Out-Null or store the result in a variable), but the expression following the return statement is always the last one, and can be extracted with select -last 1.
I have modified the bit of your script, to make it run the way you want it. I'm not exactly sure you would want to compare files only by the .Count property though, but its not within the scope of this question. If that wasn't what you were looking after, please comment and I'll try to edit this answer. Basically from what I understand you wanted to run a condition check after the function, while it can be easily implemented inside the function.
$Dir1 ="C:\Dir1"
$Dir2 ="C:\Users\a.pawlak\Desktop\Dir2"
function Test-Diff($Dir1,$Dir2)
{
$fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
$fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
if ($fileList1.Count -ne $fileList2.Count)
{
Write-Host "Following files are different:"
Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property FullName -PassThru | Format-Table FullName
Write-Host "Test FAILED" -BackgroundColor Red
}
else
{
return $true
Write-Output "Test OK"
}
}
Test-Diff $Dir1 $Dir2
If there is anything unclear, let me know
AlexP
My script keeps bugging me with the following exception
copy-item : Cannot find drive. A drive with the name 'F' does not exist.
At C:\Program Files (x86)\CA\ARCserve Backup\Templates\RB_Pre_Process.ps1:58 char:1
+ copy-item -Path $drive -Destination $DST_DRIVE -Recurse -ErrorAction Stop
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (F:String) [Copy-Item], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
This is what my script looks like. I am mounting an ISO image on drive F: and I have added a "start-slepp -s 5" command so i can verify the image get's mounted, which it does!
$BACKUP_PATH = "E:\00_BACKUP_DATA"
$DR_PATH = "E:\01_DR_DATA"
$ISO_IMAGE = "C:\Program Files (x86)\CA\ARCserve Backup\Templates\Winpe_x64.iso"
$DST_DRIVE = "E:\"
try {
New-EventLog -LogName Application -Source "RB_Pre_Process.ps1" -ErrorAction Stop
} catch [System.InvalidOperationException] {
Write-host $_
}
try {
Write-Host "Preparing RDX cartridge..."
# Query for disk object
$disk_number = (Get-Disk | Where-Object -Property FriendlyName -like "TANDBERG RDX*").Number
# Remove partitions
Get-Disk $disk_number | Clear-Disk -RemoveData -Confirm:$false | Out-Null
# Create new partition
New-Partition -DiskNumber $disk_number -UseMaximumSize | Out-Null
# Format partition
Format-Volume -DriveLetter E -FileSystem NTFS -NewFileSystemLabel "RDX_TAPE" -Confirm:$false | Out-Null
# Set partition as active
Set-Partition -DriveLetter E -IsActive:$true | Out-Null
} catch {
Write-Host $_
Write-EventLog -LogName Application -Source $MyInvocation.MyCommand.Name -EventID 2 -Message $_
}
try {
Write-Host "Creating folder structure..."
new-item -itemtype directory -Path $BACKUP_PATH -ErrorAction stop | Out-Null
new-item -itemtype directory -path $DR_PATH -ErrorAction stop | Out-Null
} catch {
Write-Host $_
Write-EventLog -LogName Application -Source $MyInvocation.MyCommand.Name -EventID 2 -Message $_
}
try {
Write-Host "Mounting ISO image..."
$image = Mount-DiskImage -ImagePath $ISO_IMAGE -PassThru -ErrorAction Stop
} catch [ParameterBindingException] {
Write-Host $_
Write-EventLog -LogName Application -Source $MyInvocation.MyCommand.Name -EventId 2 -Message $_
}
$drive = ($image | Get-Volume).DriveLetter
$drive += ":\*"
Start-Sleep -s 5
try {
Write-Host "Copying ISO content..."
copy-item -Path $drive -Destination $DST_DRIVE -Recurse -ErrorAction Stop
} catch {
Write-Host $_
Write-EventLog -LogName Application -Source $MyInvocation.MyCommand.Name -EventId 2 -Message $_
}
try {
Write-Host "Unmounting ISO image..."
Dismount-DiskImage -ImagePath $ISO_IMAGE -ErrorAction Stop
} catch [System.Exception] {
Write-Host $_
Write-EventLog -LogName Application -Source $MyInvocation.MyCommand.Name -EventId 2 -Message $_
}
So, what's going wrong here? Sometimes it works sometimes not...
I "solved" the issue... my script is working perfectly fine when it's getting started directly from the PowerShell prompt instead of the PowerShell ISE... So the IDE is the culprit.
it seems the mounted image can't be reached in powershell. I think it's a limitation of the provider. A possible workaround is issuing CMD command. You could replace
copy-item -Path $drive -Destination $DST_DRIVE -Recurse -ErrorAction Stop
with
& cmd /C "copy F:\* G:\dest\"
Here I just give an example, you may need to do further work to copy recursively..you could use the xcopy or robocopy which could handle recursive copy.