Script Help

Ask your PowerShell-related questions, including questions on cmdlet development!
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
User avatar
localpct
Posts: 353
Last visit: Mon Sep 27, 2021 5:48 am

Script Help

Post by localpct »

We are looking at gathering battery information. I'm unsure how to change this script to report back each pc in the table, and not each PC individually

here is our script
  1. $Computers = get-content 'C:\computers.txt'
  2.  
  3. foreach($c in $Computers){
  4. Invoke-Command -ComputerName $c -ScriptBlock {
  5. $batteryClass = Get-WmiObject -Namespace root\WMI -Class MSBatteryClass
  6. if (!$batteryClass) {'this device has no physical battery.'; break}
  7. $batteryData = foreach ($entry in $batteryClass) {
  8.     if ($entry.UniqueID) {$entry | select UniqueID, InstanceName}
  9. }
  10.  
  11. # find data based on the UniqueID of the battery:
  12. foreach ($entry in Get-wmiobject Win32_battery) {
  13.     $battery = @($batteryData).where{$_.UniqueID -eq $entry.DeviceID}
  14.     $attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
  15.     foreach ($a in $attribs.name) {
  16.         $battery | Add-Member -Name "Win32_battery.$a" -Value $entry.$a -MemberType NoteProperty
  17.     }
  18. }
  19.  
  20. # find data based on the InstanceName of the battery:
  21. foreach ($class in $batteryClass.__CLASS | select -Unique) {
  22.     $classData = Get-WmiObject -Namespace root\WMI -Class $class
  23.     foreach ($entry in $classData) {
  24.         $battery = @($batteryData).where{$_.InstanceName -eq $entry.InstanceName}
  25.         $attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
  26.         foreach ($a in $attribs.name) {
  27.             $battery | Add-Member -Name "$class.$a" -Value $entry.$a -MemberType NoteProperty
  28.         }
  29.     }
  30. }
  31.  
  32. $battery | Select-Object Win32_battery.SystemName, Win32_battery.EstimatedRunTime, Win32_battery.EstimatedChargeRemaining, BatteryFullChargedCapacity.FullChargedCapacity, BatteryRuntime.EstimatedRuntime, BatteryStaticData.DesignedCapacity, BatteryStatus.RemainingCapacity, BatteryStatus.ChargeRate | ForEach-Object {
  33. [pscustomobject]@{
  34. 'SystemName' = $battery.'Win32_battery.SystemName'
  35. 'Win32EstRunTime' = $battery.'Win32_battery.EstimatedRunTime'
  36. 'BattEstRunTime' = $battery.'BatteryRuntime.EstimatedRuntime'
  37. 'FullChargedCapacity' = $battery.'BatteryFullChargedCapacity.FullChargedCapacity'
  38. 'DesignedCapacity' = $battery.'BatteryStaticData.DesignedCapacity'
  39. 'RemainingCapacity' = $battery.'BatteryStatus.RemainingCapacity'
  40. 'ChargeRate' = $battery.'BatteryStatus.ChargeRate'
  41. 'ChargePercent' = $battery.'Win32_battery.EstimatedChargeRemaining'
  42. } | ft
  43.  
  44. }
  45.  
  46. }
  47. }
Snag_5473359.png
Snag_5473359.png (23.78 KiB) Viewed 6203 times
How do I make them appear like this
Snag_548004e.png
Snag_548004e.png (15.77 KiB) Viewed 6203 times

jvierra
Posts: 14932
Last visit: Fri Sep 24, 2021 2:50 pm
Answers: 14
Has voted: 3 times
Been upvoted: 11 times

Re: Script Help

Post by jvierra »

To do that the selector and formatter have to be outside of the data loop.

User avatar
localpct
Posts: 353
Last visit: Mon Sep 27, 2021 5:48 am

Re: Script Help

Post by localpct »

Something tells me there is a better way
  1. $Computers = get-content 'assets.txt'
  2. $batteries = foreach($c in $Computers){
  3. Invoke-Command -ComputerName $c -ScriptBlock {
  4. $batteryClass = Get-WmiObject -Namespace root\WMI -Class MSBatteryClass
  5. if (!$batteryClass) {'this device has no physical battery.'; break}
  6. $batteryData = foreach ($entry in $batteryClass) {
  7.     if ($entry.UniqueID) {$entry | select UniqueID, InstanceName}
  8. }
  9.  
  10. # find data based on the UniqueID of the battery:
  11. foreach ($entry in Get-wmiobject Win32_battery) {
  12.     $battery = @($batteryData).where{$_.UniqueID -eq $entry.DeviceID}
  13.     $attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
  14.     foreach ($a in $attribs.name) {
  15.         $battery | Add-Member -Name "Win32_battery.$a" -Value $entry.$a -MemberType NoteProperty
  16.     }
  17. }
  18.  
  19. # find data based on the InstanceName of the battery:
  20. foreach ($class in $batteryClass.__CLASS | select -Unique) {
  21.     $classData = Get-WmiObject -Namespace root\WMI -Class $class
  22.     foreach ($entry in $classData) {
  23.         $battery = @($batteryData).where{$_.InstanceName -eq $entry.InstanceName}
  24.         $attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
  25.         foreach ($a in $attribs.name) {
  26.             $battery | Add-Member -Name "$class.$a" -Value $entry.$a -MemberType NoteProperty
  27.         }
  28.     }
  29. }
  30.  
  31.  
  32. $battery
  33. }
  34.  
  35. }
  36.  
  37.  
  38. $batteries = $batteries | Select-Object Win32_battery.SystemName,
  39. Win32_battery.EstimatedRunTime,
  40. Win32_battery.EstimatedChargeRemaining,
  41. BatteryFullChargedCapacity.FullChargedCapacity,
  42. BatteryRuntime.EstimatedRuntime,
  43. BatteryStaticData.DesignedCapacity,
  44. BatteryStatus.RemainingCapacity,
  45. BatteryStatus.ChargeRate
  46.  
  47. $batteries | ForEach-Object {
  48. [pscustomobject]@{
  49.  
  50. 'SystemName' = $_.'Win32_battery.SystemName'
  51. 'Win32EstRunTime' = $_.'Win32_battery.EstimatedRunTime'
  52. 'BattEstRunTime' = $_.'BatteryRuntime.EstimatedRuntime'
  53. 'FullChargedCapacity' = $_.'BatteryFullChargedCapacity.FullChargedCapacity'
  54. 'DesignedCapacity' = $_.'BatteryStaticData.DesignedCapacity'
  55. 'RemainingCapacity' = $_.'BatteryStatus.RemainingCapacity'
  56. 'ChargeRate' = $_.'BatteryStatus.ChargeRate'
  57. 'ChargePercent' = $_.'Win32_battery.EstimatedChargeRemaining'
  58. }
  59.  
  60. } | ft

jvierra
Posts: 14932
Last visit: Fri Sep 24, 2021 2:50 pm
Answers: 14
Has voted: 3 times
Been upvoted: 11 times

Re: Script Help

Post by jvierra »

I just told you the better way. YOu also don;t need to select and convert as the selector alreadyt does all of that. YOu are enumerating the results repeatedly when you don't need to enumerate anything. WHat most people who have not learned Power5Shell miss is that PowerShell is an enumerator although we call it a pipeline. All results returned are alreaed enumerated. Pass the enumeration in a pipeline and the forward commands process each enumerated result separtely.

The selector can be used to extract sub enumerated properties.

All of your code can be done in one simple pipeline with one selector which will increase performance and simlify the code.

My recommendation is to learn PowerShell beyond simple things you may have found on the Internet and found useful as copies that you could alter.

For me to unwind your code would take time and the point of a forum is to answer simple questions about the technology and not the redesign of poorly designed code.

Of course I though that if I used your code to demonstrate the issues and how to approach code design and how that would make things easier then I might do it but not until next week.

I can only say this, if it works then use it even if it isn't perfect. What works is useful but rethink it and try to make the code work in less steps as it will help you learn PowerShell and code design at a deeper level. Leverage what you know now to learn more and this is a good piece of code to start that.

We all have to start somewhere. We all then have to refine our skills. This code appears to be a good starter. In engineering we always build things quickly and then step back and consider design. Moving forward we consider simplification. The first rule of engineering is simplification of concept, question, design and build. Mostly we do this iteratively. Eventually good engineers start with simplification of the initial question then choose a design approach then write some code to test our ideas. Well experienced engineers do this in their heads for most questions.

First we need the tools in our toolbox and then experience with the tools so we can get experience with the concepts.

Your code shows many concepts that are used in a very complicated way which most would immediately see as needing simplfication.

In coding we would call this refactoring but I can also see it needs re-conceiving which usually indicates that the question has not been stated in its simplest form.

The simplest place for you to start is to restructure the code to eliminate all of the redundant loops. In mathematics we would do this by "combining like terms" which is the same in coding but called re-factoring.

Ouch! Too techical. Sorry. Start by compacting the loops. See what can be included in each earlier loop to eliminate later loops. Winner gets a prize.

User avatar
localpct
Posts: 353
Last visit: Mon Sep 27, 2021 5:48 am

Re: Script Help

Post by localpct »

Hello, this definitely helped me and I was able to reduce the redundant work

Trying to post my code but I get a 403 error

Locked