Get-WmiObject Win32_Product critical error - powershell

I have created a remote uninstaller, it has been working perfectly until I got to a pc which has too many MSI packages. Until the Get-WmiObject Win32_Product can finish searching and listing all the packages it gets a critical error with no explanation.
My guess is that it has a timeout timer but I have no idea how to modify it or if it is even possible.
the code I use :
$ComputerName = Read-Host -Prompt 'Input the computer name' # the name of the computer to remove the app from
Get-WmiObject Win32_Product -ComputerName $ComputerName | Select-Object -Property Name | Out-GridView -Title "All apps on destination Computer"
$Name = Read-Host -Prompt 'Input name of the application (has to be exact name)' #name of the application
$Application = Get-WmiObject Win32_Product -ComputerName $ComputerName | Where-Object {$_.Name -eq $Name} #choose the object, this will be the app that we will delete
if ($Application) {
$Application.Uninstall()
"The removal was successful"
}
else {
$Name + ' is not installed on ' + $ComputerName
}
Start-Sleep -Seconds 10
the error:
Get-WmiObject : Critical error
At line:5 char:1
+ Get-WmiObject Win32_Product -ComputerName $ComputerName | Select-Obje ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
the application asks the name of the computer that I want to uninstall an app form, lists all the packages in that computer, and I choose the one I want to delete, copy the name and paste it in the next field.
this error happens after I enter a name of the computer, also it takes a really long time to load, the error happens at 55 second mark from the moment it starts listing.
My idea is that the command has a timeout or a number of max
If anyone has any idea why I get this error or how to avoid it please help

Related

How to create Powershell custom error output?

I want to make a small PS script that checks the status of a service logon account against a server list.
What i need to do is, if a server is down, it shows a custom error message that tells me which server from the list is offline, instead of the default bulky red error message.
Here is what i came up with so far.
This is the RPC error powershell shows if something wrong with a server.
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At V:\HRG01\MPE_HRG01_Information-Technology\Share\ITSS-Core\Icinga Monitor Software\Service Check\Get-Service Log On.ps1:1 char:1
+ Get-WmiObject win32_service -ComputerName (Get-Content -path ".\serverlist.txt") ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
PS Exception
PS c:\> $Error[0].Exception.GetType().FullName
System.Runtime.InteropServices.COMException
I searched on the internet for a solution, and this is what i came up with at last, but of course not working.
$servers= Get-Content -path ".\serverlist.txt"
foreach ($server in $servers)
{
try {
Get-WmiObject win32_service -ComputerName $server |
Where-Object {$_.Name -eq "icinga2"} -ErrorAction Continue |
format-list -Property PSComputerName,Name,StartName
}
catch [System.Runtime.InteropServices.COMException]
{
Write-Host "ERROR: $Server connection error"
}
}
Tee-Object .\Results.txt -Append
Read-Host -Prompt "Press Enter to exit"
I'd really appreciate your help
The error is on Get-WmiObject not Where-Object. And you have to set error action to stop to catch terminating error.
$servers= Get-Content -path ".\serverlist.txt"
foreach ($server in $servers)
{
try {
Get-WmiObject win32_service -ComputerName $server -ErrorAction Stop |
Where-Object {$_.Name -eq "icinga2"} |
format-list -Property PSComputerName,Name,StartName
}
catch [System.Runtime.InteropServices.COMException]
{
Write-Host "ERROR: $Server connection error"
}
}
Tee-Object .\Results.txt -Append
Read-Host -Prompt "Press Enter to exit"

Powershell printer installation script

I'm trying to create a login script that performs a few actions. I need it to complete the following.
Check and record the current default printer.
Delete all printers.
Install a specific list of printers.
Set the default printer back to what the default printer was previously.
I need to do this because we've made some printer name changes on the network and we want to re-map all of the printers with the new names and also install some additional printers. I currently have a batch file calling a .ps1 file. Here's the code from both files.
Login.bat
#echo off
powershell -command Set-ExecutionPolicy Unrestricted -force
Powershell -command " & '\\server\share\MyPSScript.ps1'"
Login.ps1
# Save current default printer.
Get-WmiObject -Query " SELECT * FROM Win32_Printer WHERE Default=$true" | foreach {$_.portname} -OutVariable CurDefPrinter
# Deletes all network printers.
Get-WmiObject Win32_Printer | where{$_.Network -eq ‘true‘} | foreach{$_.delete()}
# Maps all network printers.
add-printer -connectionname "\\server\ricoh"
add-printer -connectionname "\\server\hp"
# Set default printer
(Get-WmiObject -Class Win32_Printer -Filter "portame='$CurDefPrinter'").SetDefaultPrinter()
When I run this, I get this error.
C:\Temp\Scripts>Login.bat
C:\Temp\Scripts>REM #echo off
10.0.0.155
Get-WmiObject : Invalid query "select * from Win32_Printer where portame='10.0.0.155'"
At \\server\share\login.ps1:12 char:2
+ (Get-WmiObject -Class Win32_Printer -Filter "portame='$CurDefPrinter' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
You cannot call a method on a null-valued expression.
At \\server\share\Login.ps1:12 char:1
+ (Get-WmiObject -Class Win32_Printer -Filter "portame='$CurDefPrinter' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Any help would be greatly appreciated!
You spelled PortName wrong so nothing was being returned and you were calling a method on ($null)
(Get-WmiObject -Class Win32_Printer -Filter "portname='$CurDefPrinter'").SetDefaultPrinter()
If you dont need to use the Query and Filter option you can do it like this:
#to get the current default printer
$default = Get-WmiObject -Class Win32_Printer | Where-Object {$_.Default -eq "true"}
#to reset the default printer
$default.SetDefaultPrinter()
Atleast it works at my enviroment.

Permissions for using gwmi win32_ntlogevent instead of get-eventog?

The problem I have: get-eventlog works (I tested by doing "run as" on the PoSH ISE). Get-WMIObject win32_ntlogevent does not. It's a perm issue of some sort. Help please.
Background:
I've built a script that uses gwmi win32_ntlogevent to pull event logs. (I chose it because it was an order of magnitude faster than either get-winevent or get-eventlog, even with filters).
However, I cannot reach some other servers in my environment. So I had the Servers group add a credential to connect under, that has some sort of Log Reader right. (not sure what they added)
Get-Eventlog:
$server = "myserver"
get-eventlog -ComputerName $server -logname "application"
(above returns results)
Get-WMIObject win32_ntlogevent does not. Neither with
Get-WmiObject win32_ntlogevent -ComputerName $server
or
$time = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime('2015/05/01 5:00:00am')
$EventQuery = #"
select
Logfile, RecordNumber, Timegenerated, TimeWritten, EventCode, EventType, Type, Category, CategoryString, SourceName, InsertionStrings, ComputerName, User, Message
from Win32_NTlogEvent
where timewritten >='$time'
and LogFile = 'system'
"# #this line must be un-recessed
gwmi -computername $server -Query $EventQuery
Instead, I get:
gwmi : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
At line:10 char:1
+ gwmi -computername "myserver" -Query $EventQuery
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Thanks!

Invalid Namespace when automating Get-WMIObject

I am trying to automate the retrieval of OS architecture and when I do I get an Invalid Namespace error.
foreach($i in $hosts){
$ip = $i.name
Get-WmiObject -ComputerName $ip Win32_OperatingSystem
}
If I take Get-WmiObject -ComputerName $ip Win32_OperatingSystem and replace $ip with a legit IP it works perfectly. I even added Write-Host to the front of Get-WMIObject so it would display the entire command that would run. I ran the output from Write-Host and the command completes successfully.
Error:
Get-WmiObject : Invalid namespace
At line:4 char:18
+ Get-WmiObject <<<< -ComputerName $ip Win32_OperatingSystem
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
The $hosts variable is a PSCustomObject with two noteProperty fields. The first is name and the second is user. The name field holds an IP address of the system.
It turns out there were trailing whitespaces after the IPs. I used .trim() and now everything works just fine.

Error handling - PowerShell script

I have the following powershell script that cycles through a list of hostnames and changes the DNS settings for the active interfaces:
$servers = Get-Content C:\users\kevin.todd\desktop\serverlist.txt
foreach($server in $servers)
{
Write-Host "Connect to $server..."
$nics = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $server -ErrorAction Inquire | Where{$_.IPEnabled -eq "TRUE"}
$newDNS = "10.100.10.81","10.100.10.82"
foreach($nic in $nics)
{
Write-Host "`tExisting DNS Servers " $nic.DNSServerSearchOrder
$x = $nic.SetDNSServerSearchOrder($newDNS)
if($x.ReturnValue -eq 0)
{
Write-Host "`tSuccessfully Changed DNS Servers on " $server
}
else
{
Write-Host "`tFailed to Change DNS Servers on " $server
}
}
}
The problem is on some hosts I get the following error:
Get-WmiObject : The RPC server is unavailable. (Exception from
HRESULT: 0x800706BA) At C:\Documents and
Settings\user1\desktop\changednsserver.ps1:20 char:26
+ $nics = Get-WmiObject <<<< Win32_NetworkAdapterConfiguration
-ComputerName $server -ErrorAction Inquire | Where{ $_.IPEnabled -eq
"TRUE"}
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject],
COMException
+ FullyQualifiedErrorId :
GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Existing DNS Servers You cannot call a method on a null-valued
expression. At C:\Documents and
Settings\user1\desktop\changednsserver.ps1:30 char:42
+ $x = $nic.SetDNSServerSearchOrder <<<< ($newDNS)
+ CategoryInfo : InvalidOperation:
(SetDNSServerSearchOrder:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
And I'm asked the following question by Powershell:
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
[Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help
(default is "Y"):
I would like the script to just answer A - Yes to all and continue running the script. The problem is it just halts the script until I manually enter "A". How can I have it automatically answer and continue?
Well the short answer is to not tell it to stop in the first place:
$nics = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $server -ErrorAction Inquire | Where{$_.IPEnabled -eq "TRUE"}
Try:
$nics = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $server -ErrorAction SilentlyContinue | Where{$_.IPEnabled -eq "TRUE"}
If you need to see where Errors occur, you have also a possibility to define an error variable using the switch
-ErrorVariable $<variable>
If errors occur in a foreach loop, the Error variable will be an array of error messages you can later analyze by querying the defined error variable with an array index echo $<EVariable>[<index>]
it would be something like echo $MyErrorArray[0] to get the first occurred error in that array.
An elegant way would be to have all that added to a textbox/combobox for log purposes but the coice of error handling ananalyzing is yours.