I'm trying to understand the .uninstall() method.
From this link it looks like the method .uninstall() only works when used with Get-WmiObject -Class Win32_Product. But this means it will consider 32-bit software only and not 64-bit software.
So I wrote this few lines in order to uninstall Erlang, which is 64-bit:
# Check if a Software ins installed
function Check_Program_Installed($programName) {
$x86_check = ((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall") |
Get-ItemProperty |
Where-Object {$_.DisplayName -like "*$programName*" } |
Select-Object -Property DisplayName, UninstallString) |
Format-Table
if (Test-Path 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') {
$x64_check = ((Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall") | Get-ItemProperty | Where-Object {$_.DisplayName -like "*$programName*" } | Select-Object -Property DisplayName, UninstallString) | Format-Table
}
if ($x86_check -and $x64_check -eq $null) {
Write-Host "$programName is not installed on this computer" -ForegroundColor Green
#continue
} elseif ($x86_check -or $x64_check -ne $null) {
Write-Host "On this computer is installed " -ForegroundColor Red
$x86_check
$x64_check
$x86_check.uninstall()
$x64_check.uninstall()
}
}
# Erlang check
Write-Host "Checking if Erlang exist " -NoNewline
Check_Program_Installed("Erlang")
Write-Host "The End: the script ends here" -ForegroundColor Yellow
but unfortunately it returns me the error:
You cannot call a method on a null-valued expression. At
C:\Users\Admin\Desktop\test.ps1:17 char:3
+ $x86_check.uninstall()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Method invocation failed because
[Microsoft.PowerShell.Commands.Internal. Format.FormatStartData] does
not contain a method named 'Uninstall'. At
C:\Users\Admin\Desktop\test.ps1:18 char:3
+ $x64_check.uninstall()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I believe the root cause it that there are DisplayName and UninstallString in the variable, right?
A way out I found is to use:
'"C:\Program Files\erl8.3\Uninstall.exe'" | cmd
in order to uninstall but this is not using the .uninstall() method which is what I want to use.
Is Microsoft saying that you can use .uninstall() only with 32-bit architecture and for 64-bit you need to find your own way out?
If so it's quite rudimentary
The reply is NO.
.uninstall() can only be used with Get-WmiObject -Class Win32_Product and therefore will only uninstall 32-bit programs.
Source 1
Source 2
Source 3
Source 4
Source 5
There might be an alternative way out uninstall both 32-bit and 64-bit program with:
Get-Package "*Erlang*"
At least finds the program but
Get-Package "*Erlang*" | Uninstall-Package -Force
won't uninstall
Related
This question already has answers here:
Check if a Registry Path Exists in Remote Machine
(4 answers)
Test if registry value exists
(13 answers)
Closed 3 months ago.
I've been trying to create a script that checks which applications are installed on a remote server. So far I've been able to get it working to do the job when everything is in place.
However, one of my servers are a bit broken and the "uninstall" registry key is missing from the registry.
So before doing Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" and Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" I want to check if the registry key is present and if that isn't the case, I wish to run Get-WmiObject -Query "select * from win32_product"
Currently when I run it on the machine that is missing the "Uninstall" registry key I get
Cannot find path 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' because it does not exist.
+ CategoryInfo : ObjectNotFound: (HKEY_LOCAL_MACH...rsion\Uninstall:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
+ PSComputerName : ServerName001
Current script:
# Change to computer you wish to search.
$ComputerName = "ServerName001"
$ScriptPath = Get-Location
$GetWmiObject_Win32Product = $ScriptPath.ToString() + $ComputerName + "_Get-WmiObject-win32_Product.csv"
$GetItemProperty = $ScriptPath.ToString() + $ComputerName + "_Get-ItemProperty.csv"
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
$directoryInfo64bit = Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Measure-Object
$directoryInfo32bit = Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Measure-Object
$Apps = #()
if($directoryInfo64bit.count -eq 0){
Write-Output "No 64bit Uninstall folder"
}else{
$Apps += Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
}
if($directoryInfo32bit.count -eq 0){
Write-Output "No 32bit Uninstall folder"
}else{
$Apps += Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
}
$Apps | Select-Object -Property DisplayName, Publisher, DisplayVersion, InstallDate, InstallLocation, PSComputerName
} | Export-Csv -Path $GetItemProperty -NoTypeInformation -Encoding utf8
Get-WmiObject -Query "select * from win32_product" -ComputerName $ComputerName | Select-Object -Property Name, Vendor, Version, PSComputerName | Export-Csv -Path $GetWmiObject_Win32Product -NoTypeInformation -Encoding utf8
Can anyone please tell me what is wrong with the following code. I am trying to clean up deleted accounts from AD.
Function Del-User() {
$To_Be_Deleted = (Get-ADObject -Filter 'isDeleted -eq $True -and -not (isRecycled -eq $true) -and name -ne "Deleted Objects" -and lastKnownParent -eq "CN=Users,DC=example,DC=local"'-includeDeletedObject).DistinguishedName
foreach ($d in $To_Be_Deleted) {
Remove-ADObject -Identity $d
}
}
Del-User
When I pipe the output directly to Remove-ADObject, it works, but when I try to use the function it doesn't work and I get the following error:
At C:\Users\administrator.example\Documents\del.ps1:18 char:9
+ Remove-ADObject -Identity $d
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (CN=user name...example,DC=local:ADObject) [Remove-ADObject], ADIdentityNotFoundException
+ FullyQualifiedErrorId : Directory object not found,Microsoft.ActiveDirectory.Management.Commands.RemoveADObject
Remove-ADObject : Directory object not found
I am currently trying to run a script that is as follows (to find and uninstall CCleaner):
Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -eq "CCleaner"} -OutVariable Results **{
& "$($Results.InstallLocation)\uninst.exe"
}
The error is:
Where-Object : A positional parameter cannot be found that accepts argument
& "$($Results.InstallLocation)\uninst.exe" /S
.At line:1 char:98
+ Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object <<<< {$_.DisplayName -eq "CCleaner"} -OutVariable Results {
+ CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WhereObjectCommand
The last part there seems to be a problem. I am sure this is because I am writing this in PS v3 but I'm running this as a PSSession on PC's running PS v2 or v1.
I think this is what you're after:
Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -eq "CCleaner"} | ForEach-Object { & "$($_.InstallLocation)\uninst.exe" }
Otherwise, you need to use a named parameter after "Results"
I'm attempting to create a script that cleans up temporary profiles on a 2008-R2 server.
Weird thing is I'm positive I had this working fine before our holiday, now the script doesn't work after said holiday :(.
The script:
$keys = ls "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*.bak"
foreach ($key in $keys){
$sid = $key.name | select-string -Pattern 'S-\d-\d+-(\d+-){1,14}\d+' | out-string
$sid = ($sid).Split('\')[6]
$sid = ($sid).Split('.')[0]
$profile = get-wmiobject win32_userprofile -computername localhost | where-object {$_.SID -eq $sid}
$profile.Delete()
}
If I run that, or any form of modification of that delete method, I get:
Exception calling "Delete" with "0" argument(s): ""
At C:\temp\remove_temp_profiles.ps1:7 char:18
($profile).Delete <<<< ()
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : DotNetMethodException
If I run a:
get-wmiobject win32_userprofile | get-member
I can see that the delete method is not there. It's supposedly "hidden" whatever that means.
Apart from the delete not working, the rest of the script works perfectly (regex is another battle haha!)
I've also instead attempted to use remove-wmiobject instead. However it causes errors with:
Remove-WmiObject :
At C:\temp\remove_temp_profiles.ps1:7 char:28
+ $profile | remove-wmiobject <<<<
+ CategoryInfo : InvalidOperation: (:) [Remove-WmiObject], COMException
+ FullyQualifiedErrorId : RemoveWMICOMException,Microsoft.PowerShell.Commands.RemoveWmiObject
I've spent ages and ages googling and trying different things, and all of the solutions appear to be "use the $variable.Delete() and it works fine". I don't know how to program (only basic scripting) so apologies for my newness.
This could be because the profile is still considered to be loaded. You can verify this by looking at the loaded property. You should also look at using the -Filter parameter instead of piping everything to Where-Object.
$keys = ls "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*.bak"
foreach ($key in $keys){
$sid = $key.name | select-string -Pattern 'S-\d-\d+-(\d+-){1,14}\d+' | out-string
$sid = ($sid).Split('\')[6]
$sid = ($sid).Split('.')[0]
$profile = get-wmiobject win32_userprofile -computername localhost -Filter "SID -eq '$sid' AND NOT Loaded='True'"
$profile.Delete()
}
If you just want to see if profiles are still loaded:
Get-WMIObject win32_userprofile -computername localhost -Filter "Loaded='True'" |
Select SID,LocalPath,Loaded
I am trying to get the OWNER of a process, code :
(Get-WmiObject -class win32_process | where{$_.ProcessName -eq 'explorer.exe'}).getowner() | Foreach-Object user | out-string**
This works great under win8 but in win7 I get this msg :
ForEach-Object : Cannot bind parameter 'Process'. Cannot convert the "user" val
ue of type "System.String" to type "System.Management.Automation.ScriptBlock".
At C:\Program Files (x86)\Advanced Monitoring Agent GP\scripts\9660.ps1:1 char:
108
+ (Get-WmiObject -class win32_process | where{$_.ProcessName -eq 'explorer.exe'
}).getowner() | Foreach-Object <<<< user | out-string
+ CategoryInfo : InvalidArgument: (:) [ForEach-Object], Parameter
BindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerSh
ell.Commands.ForEachObjectCommand
Help please! Thank you for the time.
Instead of foreach-object user, use select -expand user. This is equivalent to doing foreach-object { $_.user } which is probably what you meant to do. Improvements to flexibility in the grammar allow your first attempt in later versions of powershell.
The older version of Powershell won't work with the simplified syntax. This should work on either one:
(Get-WmiObject -class win32_process |
where{$_.ProcessName -eq 'explorer.exe'}).getowner() |
Foreach-Object { $_.user | out-string }
(Get-WmiObject -class win32_process | where{$_.ProcessName -eq 'explorer.exe'}).getowner() | select user
I had a similar problem but in my case, there was a non-printable character in my script that appeared after one of the }'s. ASCII code 03. I found that by opening the script in a binary editor (Textpad8). I deleted this character and it fixed the problem for me.