Powershell -lt and -gt giving opposite of expected results [duplicate] - powershell

This question already has an answer here:
How can I store output from Format-Table for later use
(1 answer)
Closed 3 years ago.
In the below code, if I add a where-object, -lt & -gt are giving opposite of expected results.
I'm sure the reason is I'm stupid, but in what specific way am I messing up?
This part gives the expected results, where in my case, the single drive has %Free of 39.8
Get-WmiObject -Namespace root\cimv2 -Class win32_logicaldisk | where-object -Property drivetype -eq 3 |
format-table deviceid,
#{n='GB Capacity';e={$_.size/1gb}},
#{n='GB Free';e={$_.freespace/1gb}},
#{n='%Free';e={($_.freespace/$_.size)*100}}
But adding this
| where {$_.'%Free' -gt 10}
Results in no output. In fact
| where {$_.'%Free' -gt 0}
Produces no results. Instead I have to use
| where {$_.'%Free' -lt 0}
Powershell thinks %Free is a negative number, I guess?

The problem is that you are piping Format-Table to anything. You should never use that except to output to the screen. Using Format-Table outputs everything as a format object, not whatever was piped into it. Instead use Select-Object to get what you need.
Get-WmiObject -Namespace root\cimv2 -Class win32_logicaldisk | where-object -Property drivetype -eq 3 |
Select-Object deviceid,
#{n='GB Capacity';e={$_.size/1gb}},
#{n='GB Free';e={$_.freespace/1gb}},
#{n='%Free';e={($_.freespace/$_.size)*100}}

Related

Out-gridview does not sorting results

I have a script that I am trying to collect drive letters from a list of servers (as well as used space and free space) and then gridview the results out.
$servers = Get-Content "path.txt"
foreach ($server in $servers) {
Invoke-Command -ComputerName $server {Get-PSDrive | Where {$_.Free -gt 0}}
Select-Object -InputObject usedspace,freespace,root,pscomputername |
Sort-Object root -Descending | Out-Gridview
}
I can get it to display the drive information for each server on the list but gridview does not work. I have tried moving the brackets around (before and after gridview) as well as piping elements but have had no luck.
Can anyone advise me as to what I am doing wrong? I feel like it is something simple but all of the examples I am finding online do not use the foreach command which I think has to do with throwing it off.
Your Select-Object is missing pipeline input - pipe the Invoke-Command call's output to it.
Instead of -InputObject, use -Property:
Note: -InputObject is the parameter that facilitates pipeline input, and is usually not meant to be used directly.
As with Sort-Object, -Property is the first positional parameter, so you may omit -Property in the call below.
foreach ($server in Get-Content "path.txt") {
Invoke-Command -ComputerName $server { Get-PSDrive | Where { $_.Free -gt 0 } } |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview
}
Also note that -ComputerName can accept an array of computer names, which are then queried in parallel, so if you want to query all computers and then call Out-GridView only once, for the results from all targeted computers:
Invoke-Command -ComputerName (Get-Content "path.txt") {
Get-PSDrive | Where Free -gt 0
} |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview
To group the results by target computer, use
Sort-Object pscomputername, root -Descending
If you'd rather stick with your sequential, target-one-server-at-a-time approach, change from a foreach statement - which cannot be used directly as pipeline input - to a ForEach-Object call, which allows you to pipe to a single Out-GridView call:
Get-Content "path.txt" |
ForEach-Object {
Invoke-Command -ComputerName $_ { Get-PSDrive | Where Free -gt 0 }
} |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview

How to execute several cmdlets in powershell script?

I have written this script to get some information about my Virtual Machine. When I execute this script the last two cmdlets (lines) don't execute, but when I execute them alone they run properly.
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, SystemName,
#{n='Size (GB)'; e={$_.Size / 1GB -as [int]}},
#{n='Freespace (GB)'; e={$_.Freespace / 1GB -as [int]}};
$TotalMemory = (Get-CimInstance Win32_OperatingSystem).TotalVisibleMemorySize / (1024*1024)
$UsedMemory = (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / (1024*1024)
$TotalMemory = [math]::Round($TotalMemory,2)
$UsedMemory = [math]::Round($UsedMemory,2)
$TotalMemory
$UsedMemory
Get-CimInstance Win32_Processor | Select-Object -Property NumberOfCores;
Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Sum | Select-Object Sum;
What is the problem?
Any comments would be appreciated.
This question has been asked a million times. Format-table is being implicitly run, and it doesn't handle different sets of columns well. All the objects are there. You can pipe the whole script to format-list. You can put get-date at the very beginning. A known object with a format file at the beginning fixes it. You can output more than 4 properties with the first object. I tried to ask for a warning to be added a while ago: format-table should at least warn when it doesn't display properties #7871
Looks like out-gridview has similar struggles: Not all properties displayed
This appears to be one of PowerShell's weird quirks. I am not sure why it happens, but if someone else does I will happily edit my answer to include it.
You will need to specifically tell it to write the output to the console. There are a couple ways of doing this.
The first, and probably messiest, would be to pass it as a parameter to Write-Host or Write-Output.
Write-Host (Get-CimInstance Win32_Processor | Select-Object -Property NumberOfCores)
Write-Host (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Sum | Select-Object Sum)
(Another way of doing this would be to assign them both to variables, and pass the variables to the cmdlet)
The second way would be to pipe it to Write-Host or Write-Output
Get-CimInstance Win32_Processor | Select-Object -Property NumberOfCores | Write-Host
Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Sum | Select-Object Sum | Write-Host
And finally, the third (and in my opinion cleanest) way would be to pipe it to a code block that references the property directly
Get-CimInstance Win32_Processor | %{$_.NumberOfCores}
Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Sum | %{$_.Sum}
Hope this helps!

Export Get-ADComputer to CSV [duplicate]

This question already has answers here:
How to get an object's property's value by property name?
(6 answers)
Closed 5 years ago.
I am working on a script which takes Hostnames from a CSV, Files them against Get-ADComputer and then saves certain Objects in certain columns of the original CSV.
While the solution seems like a basic Task (code below), my problem is, that the Output of Get-ADComputer always (you can see I played around with Out-String but also tried other formatting options) contains a lot of NewLine characters or other formatting issues which make the CSV confusing.
Clear-Host
Import-Module ActiveDirectory
$import = Import-Csv 'XXX' -Delimiter ';'
Foreach ($row in $import){
$hostname = $row.HOSTNAME
if($hostname.length -gt 3){
$computer = Get-ADComputer -Filter {Name -like $hostname} -Properties LastLogonDate, LastLogonTimeStamp
$row.AD_LastLogon.ToString() = $computer | Select-Object LastLogonDate | Select-Object -first 1 | FT -HideTableHeaders | Out-String
$row.AD_LLTimestamp = $computer | Select LastLogonTimestamp |Select-Object -first 1 | FT -HideTableHeaders | Out-String
}
}
$import | Export-Csv 'XXX' -Delimiter ';' -NoType
My question now is, if anyone could help with a method to get the bare string result of for example Get-ADComputer's LastLogonDate, without any formatting or headers included.
Thanks in advance!
Use the -ExpandProperty parameter of Select-Object to extract just the parameter you want. You can only specify one parameter to exapand at a time.
$row.AD_LastLogon = $computer | Select-Object -ExpandProperty LastLogonDate -First 1 | Out-String
$row.AD_LLTimestamp = $computer | Select-Object -ExpandProperty LastLogonTimestamp -First 1
I don't believe the -First 1 should be necessary. Get-ADComputer shouldn't be finding multiple computers with the same name.
Also, you shouldn't need to retrieve both LastLogonDate and LastLogonTimestamp. The former is the same value as the latter, just converted to a DateTime from the irritating NT Time Epoch that LastLogonTimestamp uses. Have you got a system that requires both?
Finally, just a note but this:
$row.AD_LastLogon.ToString() = $computer | [...]
It doesn't make sense. You can't assign a value to a method. I would be surprised if that didn't error or otherwise do nothing at all.

Can not get where-object & -gt to work together

I'm simply trying to filter out the variables of the "PeakWorkingSetSize" process so that the output will ONLY be greater than 5000. No matter what combination I try, the numbers won't filter. Please help.
get-wmiobject -class Win32_Process | where-object {$_.PeakWorkingSetSize -gt "5000"} | format-table -auto
FIXED thanks to #Matt!
I actually still don't know what the problem was. XD
Here is the code that works:
get-wmiobject -class Win32_Process | where-object {$_.PeakWorkingSetSize -gt "5000" | format-table -property Name,PeakWorkingSetSize -auto
There is nothing wrong with this query and it should run as you have it written. Format-Table would be making for some odd output size some of those properties do not translate to string very well. Your query and selecting some specific properties yields expected results for me. 5000 is a really low number though.
PS C:\Users\Matt> get-wmiobject -class Win32_Process | where-object {$_.PeakWorkingSetSize -gt "5000"} | select name,processid,peakworkingsetsize
name processid peakworkingsetsize
---- --------- ------------------
System 4 15588
csrss.exe 580 35412
csrss.exe 732 47356
services.exe 780 11820
winlogon.exe 812 8832
.... output truncated.....
If something is still wrong I think we need to see your expected output to understand what is wrong.

Why can't I loop through my disk size?

This is very simple code that I can't seem to make function properly
I want to find all the drives on my computer then, want to display their size.
$disks = gwmi win32_LogicalDisk | Where {$_.DriveType -eq "3"} | Select DeviceID
foreach ($i in $disks){
$i
gwmi win32_logicaldisk | Where {$_.DeviceID -eq "$i"} | Select Size
}
When displaying $i, the output is exactly as I need it I even used a Read-Host to check them one by one and every drive letter is displayed. Unfortunetly, the command to Select the size does not return anything.
Thanks for the help!
It would be more intuitive to me to iterate through disks themselves, not their IDs, i.e.
$disks = gwmi win32_LogicalDisk | Where {$_.DriveType -eq "3"}
foreach ($disk in $disks)
{
$disk.Size
}
$disk | Select Size also works, and, as Joey neatly complemented, whole thing is equivalent to
gwmi win32_LogicalDisk | Where {$_.DriveType -eq "3"} | Select -ExpandProperty Size
I don't know powershell really, but I figured I'd mess around with your script. Looks to me like the "$i" is wrong - instead use $i.DeviceID (without the quotes). Whole script that seems to work for me:
$disks = gwmi Win32_LogicalDisk | Where {$_.DriveType -eq "3"} | Select DeviceID
foreach ($i in $disks){
$i.DeviceID
gwmi Win32_LogicalDisk | Where {$_.DeviceID -eq $i.DeviceID} | Select Size
}
Another option would be to skip the iteration:
gwmi Win32_LogicalDisk | Where {$_.DriveType -eq "3"} | Select DeviceID, Size
Algorithmically I would recommend this based on execution -- the approach you are taking now iterates over all of the devices two times inside loops (basically O(n^2)). The "other option" above only iterates over them once.
Try to use server side filtering when ever you can using the Filter parameter instead of the Where-Object cmdlet (client side filtering), it performs faster. The latter gets ALL objects first and only then performs the filtering.
Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3 AND DeviceId='$($i):'" | Select-Object Size