I faced to an issue and need your remarks and recommendations about Windows Update with powershell.
Basically i use module PSWindowsUpdate which works well and automate WU by script.
My situation is the following (see screenshot):
From User interface, we see that an update is on pending install
However command Get-WUList indicates that there is no KB candidate (whatever the state)
How can retrieve the KB with state 'Pendint install' and of course install them with powershell ?
Thanks
This code will show Pending updates:
Clear-Host
$TStr = ""
$fmtUpds =
#{Expression={&{
Switch ($_.MsrcSeverity) {
1 {"Critical"}
2 {"Important"}
3 {"Moderate"}
4 {"Low"}
5 {"Unspecified"}
Default {"Other"}
}}};Label="`nSeverity";Width=9},
#{Expression={"{0:N1} MB" -f ($_.Size / 1MB)};
Label="`n Size";
Width=8; Align="Right"},
#{Expression={$_.BrowseOnly};Label="Browse`nOnly";
Width=6; Align="Left"},
#{Expression={$_.IsDownLoaded};Label="Down`nloaded";
Width=6; Align="Left"},
#{Expression={$_.RebootRequired};Label="Reboot`nReq.";
Width=6; Align="Left"},
#{Expression={$_.Title};Label="`nDescription";Align="Left"}
Try {
$PU = get-windowsUpdate -ErrorAction Stop |
Where-Object {$_.IsHidden -eq $False} |
Format-Table -Property $fmtUpds -Wrap |
Out-String
If ($PU -eq "") { $PU = "`tNo Pending Updates Found!" |
Out-String}
}
Catch {$PU = "`n`tRequires Administrative privledges to report"}
Try {
$HU = get-windowsUpdate -ErrorAction Stop |
Where-Object {$_.IsHidden -eq $True} |
Format-Table -Property $fmtUpds -Wrap |
Out-String
If ($HU -eq "") { $HU = "`tNo Hidden Updates Found!`n" |
Out-String}
}
Catch {$HU =
"`n`tRequires Administrative privileges to report`n"}
$TStr += ("`nPending Updates:" | Out-String) +
($PU | Out-String) +
("`nHidden Updates: " | Out-String) +
($HU | Out-String)
$TStr
Sample Output:
Pending Updates:
Browse Down Reboot
Severity Size Only loaded Req. Description
--------- -------- ------ ------ ------ ------------
Other 5.0 MB False False False Dell. - Firmware - 0.1.0.23
Other 0.5 MB False False False Intel - SoftwareComponent -
1.41.2021.121
Other 16.0 MB False False False Intel - SoftwareComponent - 1.63.1155.1
Other 47.0 MB False False False Intel - SoftwareComponent - 2130.1.16.1
Other 5.0 MB False False False SAMSUNG Electronics Co., Ltd. - Modem
- 2.19.1.0
Other 5.0 MB False False False SAMSUNG Electronics Co., Ltd. - USB -
2.19.1.0
Hidden Updates:
No Hidden Updates Found!
PS>
Related
I'm trying to use PowerShell to tell me when my computer is on battery or AC Power.
I want my script to send me a windows notification when my laptop's charger unplugs.
For the moment, I try to use a recursive fonction to test my battery status every 5 seconds but it doesn't work...
Please, be indulgent about my level, I didn't know anything about PowerShell 3 hours ago... And the last time I coded something was a long time ago !
Function Test-IsOnBattery
{
$battery = Get-WmiObject Win32_Battery
If ($battery.BatteryStatus -eq 2) {
Write-Host "PC sur secteur."
Start-Sleep -Seconds 5
return Test-IsOnBattery
}
Else {
Write-Host "PC sur batterie."
New-BurntToastNotification -Text "Battery Notification" , "Batterie plus sur secteur !"
}
}
Nathan,
Here's a script you can use that you can run from a Scheduled Task, rather than a loop, and have it start on boot up and repeat every so many minutes.
<#+---------------------------------------------------------------------------+
| PowerShell Pgm: BatteryStatus.ps1 |
| Programmed By : The Computer Mentor |
| aka : RetiredGeek # askWoody.com & StackOverFlow.com |
| Created : 06 Mar 2013 |
| Last Updated : 23 Jan 2023 | |
| Current Ver. : 6.0 |
+---------------------------------------------------------------------------+
#>
Clear-Host
Add-Type -AssemblyName "System.Windows.Forms"
$StatusMsg = {
[Windows.Forms.MessageBox]::Show($Message, $Title,
[Windows.Forms.MessageBoxButtons]::OK ,
[Windows.Forms.MessageBoxIcon]::Information)}
$Message = ""
$Title = "Battery Status:"
<#+-----------------------------------------------------+
| BatterStatus Values |
|Other (1) The battery is discharging. |
|Unknown (2) The system has access to AC so no |
| battery is being discharged. However, |
| the battery is not necessarily charging.|
|Fully Charged (3) |
|Low (4) |
|Critical (5) |
|Charging (6) |
|Charging and High (7) |
|Charging and Low (8) |
|Charging and Critical (9) |
|Undefined (10) |
|Partially Charged (11) |
+-----------------------------------------------------|#>
$GWArgs = #{ Class = "Win32_Battery"
ComputerName = "LocalHost"
}
$MyBattery = Get-CIMInstance #GWArgs
If ($Null -eq $MyBattery) {
$Message = "No Battery Present"
}
Else {
$BatteryRemaining = [Int]$MyBattery.EstimatedChargeRemaining
if(($BatteryRemaining -lt 30) -and
$($MyBattery.BatteryStatus) -eq 1) {
$Message = "Battery Low...Please Charge Me!"
}
Elseif(($BatteryRemaining -gt 90) -and
$($MyBattery.BatteryStatus) -ne 1) {
$Message =
"Battery CHARGED above 90%...Please Unplug Me!"
}
} #End Else
if($Message -ne "") {
$Null = & $StatusMsg
}
<#
+----------------------------------------------------------+
| Notes: |
| 1. To call as a scheduled task do the following in the |
| Action Pane |
| A. Action: Start a Program |
| B. Program/script: powershell.exe |
| D. Set the Trigger run At Logon and then repeat |
| every few minutes. |
+----------------------------------------------------------+
#>
If you want to use Toast msgs. just replace that logic where I have my $StatusMgs lines.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want to filter some information from physical disk. Then, write it to a file as an output file.
This is my phsicaldisk looks like:
When I try this
$GetPhysicalDisk = Get-PhysicalDisk |
Select-Object DeviceID, FriendlyName, MediaType, BusType, Size |
Format-Table
DeviceID FriendlyName MediaType BusType Size
-------- ------------ --------- ------- ----
4 SanDisk Ultra USB 3.0 Unspecified USB 61505273856
2 TOSHIBA DT01ACA100 HDD RAID 1000204886016
0 INTEL SSDSC2BF180A4H SED SSD RAID 180045766656
1 INTEL SSDSC2BF180A4H SSD RAID 180045766656
6 INTEL OPTANE SSD NVMe 15733161984
5 SAMSUNG SSD NVMe 512060514304
I want to filter those information. I want to exclude disk with BusType="USB", MediaType="Unspecified", "Bustype=NVMe with size less than 64GB".
After I filter it, I have to arrange it from the first priority, like this
1st Priority = "BusType=NVMe and MediaType=SSD"
2nd Priority = "BusType=RAID and MediaType=SSD"
3rd Priority = "BusType=RAID and MediaType=HDD"
I tried this
$GetSSDHDD = Get-PhysicalDisk |
Select-Object DeviceID, FriendlyName, MediaType, BusType, Size |
Where-Object -FilterScript {$_.MediaType -eq "Unspecified"} {$_.BusType -eq "USB"} {$_.MediaType -eq "NVMe" -and $_.Size -lt 61505273856 }
$Report = $GetSSDHDD | Out-File .\Output -Force
My expectation result of output file is like this
DeviceID FriendlyName MediaType BusType Size Priority
-------- ------------ --------- ------- ---- --------
2 TOSHIBA DT01ACA100 HDD RAID 1000204886016 4
0 INTEL SSDSC2BF180A4H SED SSD RAID 180045766656 3
1 INTEL SSDSC2BF180A4H SSD RAID 180045766656 2
5 SAMSUNG SSD NVMe 512060514304 1
###Updated
$prio = #{
'NVMe/SSD' = 1
'SATA/SSD' = 2
'SATA/HDD' = 3
'RAID/SSD' = 4
'RAID/HDD' = 5
}
Get-PhysicalDisk |
Select-Object DeviceID, FriendlyName, MediaType, BusType, Size |
Group-Object { '{0}/{1}' -f $_.BusType, $_.MediaType}, {$_.BusType -eq "RAID", $_.Size -lt 181045766656} |
Where-Object { $prio.Contains($_.Name) } |
Sort-Object { $prio[$_.Name] } |
Select-Object -Expand Group |
Export-Csv 'Report.csv' -NoType
Build a hashtable with your priorities (so you can use a numeric sort order):
$prio = #{
'SSD/NVMe' = 1
'SSD/RAID' = 2
'HDD/RAID' = 3
}
Then group your results by the combination of media type and bus type, filter out groups that don't appear in the priorities. Finally sort by priority and expand the groups.
Get-PhysicalDisk |
Select-Object DeviceID, FriendlyName, MediaType, BusType, Size |
Group-Object { '{0}/{1}' -f $_.MediaType, $_.BusType } |
Where-Object { $prio.Contains($_.Name) } |
Sort-Object { $prio[$_.Name] } |
Select-Object -Expand Group |
Export-Csv 'output.csv' -NoType
If I put together all the information from Q & A & comments,
simulate your disks
1st apply your restrictions with a 'Where-Object'
insert the Priority with a calculated property
## Q:\Test\2019\08\14\SO_57491415.ps1
# simulate Get-PhysicalDisk
$GetPhysicalDisk = #"
DeviceID,FriendlyName,MediaType,BusType,Size
4,SanDisk Ultra USB 3.0,Unspecified,USB,61505273856
2,TOSHIBA DT01ACA100,HDD,RAID,1000204886016
0,INTEL SSDSC2BF180A4H SED,SSD,RAID,180045766656
1,INTEL SSDSC2BF180A4H,SSD,RAID,180045766656
5,SAMSUNG,SSD,NVMe,512060514304
6,INTEL OPTANE,SSD,NVMe,15733161984
"# -split '\r?\n' | ConvertFrom-Csv
$prio = #{
'NVMe/SSD' = 1
'SATA/SSD' = 2
'SATA/HDD' = 3
'RAID/SSD' = 4
'RAID/HDD' = 5
}
$GetPhysicalDisk |
Where-Object {($_.BusType -ne 'USB') -and
($_.MediaType -ne 'Unspecified') -and
!(($_.BusType -eq 'NVMe') -and
([int64]$_.Size) -lt 64GB) } |
Select-Object DeviceID, FriendlyName, MediaType, BusType, Size,
#{n='Priority';e={$prio[('{0}/{1}' -f $_.BusType, $_.MediaType)]}}|
Format-Table -Auto
I get this output:
> Q:\Test\2019\08\14\SO_57491415.ps1
DeviceID FriendlyName MediaType BusType Size Priority
-------- ------------ --------- ------- ---- --------
2 TOSHIBA DT01ACA100 HDD RAID 1000204886016 5
0 INTEL SSDSC2BF180A4H SED SSD RAID 180045766656 4
1 INTEL SSDSC2BF180A4H SSD RAID 180045766656 4
5 SAMSUNG SSD NVMe 512060514304 1
Consider the following PowerShell script:
Get-Process |
Select-Object #{Name='ID';Expression={$_.Id}}, #{Name='Process Name';Expression={$_.Name}},
#{Name='WS';Expression={"{0:N1}" -f($_.WorkingSet/1MB)}},
#{Name='Private';Expression={"{0:N1}" -f($_.PrivateMemorySize/1MB)}},
#{Name='Virtual';Expression={"{0:N1}" -f($_.VirtualMemorySize/1MB)}} | Sort-Object WS |
Format-Table -AutoSize
It seemingly runs without issues. However, as I go through the results, I can see that the sorting of the "Working Set" object is not working as expected (notice how the process orders "106.8" before "11.7", as if it was sorting first by the first digit and then by the second, and so on):
ID Process Name WS Private Virtual
-- ------------ -- ------- -------
1156 svchost 1.9 1.5 73.2
628 svchost 10.5 15.4 148.7
116 svchost 10.8 4.5 119.4
660 chrome 106.8 163.8 601.0
5708 svchost 11.7 5.1 115.3
Any thoughts as to how I could fix this?
I have also tried sorting by "WorkingSet", as in:
Sort-Object WorkingSet
This ends up not sorting the results at all, though.
You should put Sort-Object before Select-object.
Get-Process | Sort-Object WS
This will give you desired output.
You can keep a property in num for sort and remove after, like this :
Get-Process | %{
[pscustomobject]#{
ID=$_.Id
'Process Name'=$_.Name
WS="{0:N1}" -f ($_.WorkingSet/1MB)
Private="{0:N1}" -f ($_.PrivateMemorySize/1MB)
Virtual="{0:N1}" -f ($_.VirtualMemorySize/1MB)
WSNum=$_.WorkingSet
}
} | Sort WSNum | select * -ExcludeProperty WSNum | ft -AutoSize
You can keep your variable in decimal with a round like it:
Get-Process | %{
[pscustomobject]#{
ID=$_.Id
'Process Name'=$_.Name
WS=[math]::Round($_.WorkingSet/1MB, 1)
Private=[math]::Round($_.PrivateMemorySize/1MB, 1)
Virtual=[math]::Round($_.VirtualMemorySize/1MB, 1)
}
} | Sort WS | ft -AutoSize
Writing a Posh 2.0 compliant script (a requirement), I need to get details of services using the registry base.
However when I search for a specific service using the exact name (and thus using -eq or -like), the results are incorrect while with -like using wildcards, this works as intended. How could we explain this?
PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "*OpenVpnService*" }
PS > $services[0]
Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
SKC VC Name Property
--- -- ---- --------
0 8 OpenVpnService {Type, Start, ErrorControl, ImagePath...}
PS > "'$($services[0].PsChildName)'"
'OpenVpnService'
PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -eq "OpenVpnService" }
PS > $services[0]
SKC VC Name Property
--- -- ---- --------
0 8
PS > "'$($services[0].PsChildName)'"
''
PS > [array]$services=Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "OpenVpnService" }
PS > $services[0]
SKC VC Name Property
--- -- ---- --------
0 8
PS > "'$($services[0].PsChildName)'"
''
UPDATE: Since I need a complete Posh 2.0 compliant machine, I have a brand new VM with Windows 7 SP1 Ultimate installed without any updates. Why without any updates? Because by updating the machine, I would get a more recent .NET version and Posh patches. I tested on a Windows 10 machine fully up to date and this is working flawlessly, the Windows 7 test machine also succeed as long as you do not store the output to an array.
After a few hours trying to debug the situation and narrowing the issue, I have been able to determine what was causing the issue.
The array initialization/casting was failing. Simply surrounding the content that needed to be casted by the array subexpression operator #( ) solved the issue.
It seems like the way arrays are handled has changed on more recent PowerShell versions (5.1 on Windows 10, and PowerShell 2.0 on a not updated Windows 7), especially with PowerShell 3.0 which introduced changes in collections and dictionaries
PS > [array]$services=#(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "*OpenVpnService*" })
PS > $services[0]
Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
SKC VC Name Property
--- -- ---- --------
0 8 OpenVpnService {Type, Start, ErrorControl, ImagePath...}
PS > "'$($services[0].PsChildName)'"
'OpenVpnService'
PS > [array]$services=#(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -eq "OpenVpnService" })
PS > $services[0]
Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
SKC VC Name Property
--- -- ---- --------
0 8 OpenVpnService {Type, Start, ErrorControl, ImagePath...}
PS > "'$($services[0].PsChildName)'"
'OpenVpnService'
PS > [array]$services=#(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.PsChildName -like "OpenVpnService" })
PS > $services[0]
Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
SKC VC Name Property
--- -- ---- --------
0 8 OpenVpnService {Type, Start, ErrorControl, ImagePath...}
PS > "'$($services[0].PsChildName)'"
'OpenVpnService'
If you know the service name already, you can do this:
$serviceName = "WinRM"
# registry
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
[bool](Get-ItemProperty -Path $regPath -Name DelayedAutoStart -ErrorAction 0)
# WMI
(Get-WmiObject Win32_Service |
Where-Object { $_.Name -eq $serviceName }).DelayedAutoStart
# result = True
$serviceName = "spooler"
# registry
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
[bool](Get-ItemProperty -Path $regPath -Name DelayedAutoStart -ErrorAction 0)
# WMI
(Get-WmiObject Win32_Service |
Where-Object { $_.Name -eq $serviceName }).DelayedAutoStart
# result = False
Ref. http://powershell.com/cs/blogs/tips/archive/2013/04/16/documenting-cpu-load-for-running-processes.aspx
This PowerShell code runs great locally, but when changing it to remote computer, it does not work.. I would also think it be helpful to add not only CPU Usage, but memory as well.
$CPUPercent = #{
Name = 'CPUPercent'
Expression = {
$TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds
[Math]::Round( ($_.CPU * 100 / $TotalSec), 2)
}
}
Get-Process -computername RemoteServer |
Select-Object -Property Name, CPU, $CPUPercent, Description |
Sort-Object -Property CPUPercent -Descending |
Select-Object -First 4
And, shows for the results:
Name CPU
CPUPercent Description
---- --- ---------- ----------- svchost
sysedge
svchost
svchost
Changing it back to local run, we see:
Name
CPU CPUPercent Description
---- --- ---------- -----------
powershell_ise 5.578125 0.51 Windows PowerShell ISE
Application 2634.765625 0.24 Some Agent Executable
svchost 1926.96875 0.18 Generic Host Process for Win32 Services
mcshield 1903.875 0.17 McAfee On-Access Scanner service