add string to calculated output in PowerShell - powershell

I am using a line of PowerShell to check RAM on a machine and it works great but I need to add a string to the output:
Get-CimInstance -class Win32_PhysicalMemory |
Measure-Object -Property capacity -Sum |
% {[Math]::Round(($_.sum / 1GB),2)}
This produces a result based on how much memory the machine has but I need to add "GB" to the end so the output is 16GB not just 16.
I have tried various things, none has worked. I guess I am struggling to understand how to add a string to the output of a calculated property.

(a) Use an expandable string (string interpolation):
Get-CimInstance -class Win32_PhysicalMemory |
Measure-Object -Property capacity -Sum |
% { "$([Math]::Round($_.sum / 1GB,2))GB" }
You can use $(...), the subexpression operator, to embed expressions and even multiple statements in a double-quoted string.
(b) Alternatively, use .NET string formatting via the -f operator:
Get-CimInstance -class Win32_PhysicalMemory |
Measure-Object -Property capacity -Sum |
% { '{0:G2}GB' -f ($_.sum / 1GB) }
The format string on the LHS must contain a placeholder for each RHS argument, starting with {0}; optionally, formatting instructions can be embedded in each placeholder, which in this case performs the desired rounding and displays up to 2 decimal places (G2).
The -f operator uses .NET's String.Format() method behind the scenes.
Important:
Method (a) always uses the invariant culture, in which . is the decimal mark.
Method (b) is culture-sensitive, so it uses the current culture's decimal mark (use Get-Culture to determine the current culture).

You can use the .ToString() Method and then add the GB
(Get-CimInstance -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)}).ToString() + " GB"
hope its helps

Related

PowerShell - How do you do math on two columns in a Select-Object Expression?

I'm trying to come up with a percent column by dividing two columns in a select-object. This is what I'm using:
Get-DbaDbLogSpace -SqlInstance serverName |
Select-Object ComputerName, InstanceName, SqlInstance, Database, LogSize,
LogSpaceUsed, LogSpaceUsedPercent,
#{Name="PercentFree"; Expression={($_.LogSpaceUsed / $_.LogSize)}} |
Format-Table
This returns an 'OB' on the expression column (see pic below). How do I do math with two columns in a Select-Object expression please?
If doing this a different way outside of a Select-Object would be better, I'm open to it.
This is what the data looks like for the above code:
Thanks for the help.
The operands of your calculation appear to be strings with byte multipliers (e.g. 38.99 MB), so you'll have to transform them to numbers in order to perform division on them.
Here's a simplified example:
Note: I'm using Invoke-Expression to transform the strings to numbers, relying on PowerShell's support for byte-multiplier suffixes such as mb in number literals (e.g., 1mb - note that there must be no space before the suffix). While Invoke-Expression (iex) should generally be avoided, it is safe to use if you trust that the relevant property values only ever contain strings such as '38.99 MB'.
[pscustomobject] #{
Database = 'db1'
LogSize = '11 MB'
LogSpaceUsed = '3 MB'
} |
Format-Table Database, LogSize, LogSpaceUsed,
#{
Name = "PercentFree"
Expression = {
'{0:P2}' -f ((Invoke-Expression ($_.LogSpaceUsed -replace ' ')) /
(Invoke-Expression ($_.LogSize -replace ' ')))
}
}
Note that I'm passing the properties, including the calculated one directly to Format-Table - no need for an intermediary Select-Object call. Note that the calculated property outputs the percentage as a formatted string, using the -f operator, so that the number of decimal places can be controlled.
Output:
Database LogSize LogSpaceUsed PercentFree
-------- ------- ------------ -----------
db1 11 MB 3 MB 27.27%
Thanks to #mklement0, this is what works.
Get-DbaDbLogSpace -SQLInstance servername | Format-Table Database, LogSize, LogSpaceUsed,
#{
Name = "PercentFree"
Expression = {
'{0:P2}' -f ((Invoke-Expression ($_.LogSpaceUsed -replace ' ')) /
(Invoke-Expression ($_.LogSize -replace ' ')))
}
}

How do we grep for a value and store it in a variable in powershell?

I am new to powershell and writing a piece of script that will check for the size of the disk and calculate the free space. The code is as follows
$disk_space = Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object Size
$FreeSpace = Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object FreeSpace
$space_available = $disk_space - $FreeSpace
I am looking to have the variables calculated and print the space_available variable. The error I receive is as follows
InvalidOperation: Method invocation failed because [System.Management.Automation.PSObject] does not
contain a method named 'op_Subtraction'.
How can this be fixed?
You can't subtract a property with another property, you have to subtract the value of each property :) this is one way you can do what you want:
$disk_space = Get-CimInstance -ClassName Win32_LogicalDisk
$space_available = $disk_space.Size - $disk_space.FreeSpace
You can also then do:
[math]::Round($space_available / 1Gb,2)
To get the value in Gigabytes. Note 2 is the number of decimal points.

How do round memory size

I have this script line:
Get-WmiObject Win32_ComputerSystem | Select-Object TotalPhysicalMemory, #{Name="GB";Expression={$_.TotalPhysicalMemory/1GB}}
How to round this result 2 separate places after coma.
result at the moment is enter image description here
You can use the format string operator and specify the number of decimal places like this
Get-WmiObject Win32_ComputerSystem |
Select-Object TotalPhysicalMemory,
#{Name="GB";Expression={"{0:n2}" -f ($_.TotalPhysicalMemory/1GB)}}

How to get max CPU percentage from from 5 trials

I am new to Powershell and struggling with syntax.
I want to write a script which gives me max CPU usage by a process out of 5 attempts.
$properties=#(
#{Name="Process Name"; Expression = {$_.name}},
#{Name="CPU (%)"; Expression = {$_.PercentProcessorTime}},
#{Name="Memory (MB)"; Expression = {[Math]::Round(($_.workingSetPrivate / 1mb),2)}}
)
Get-WmiObject -class Win32_PerfFormattedData_PerfProc_Process | Select-Object $properties
I have to run the above process 5 times and pick the top process which has max CPU usage.
This should get you what you want (remember to also include your definition of $properties):
1 .. 5 |
ForEach-Object {
Get-WmiObject -class Win32_PerfFormattedData_PerfProc_Process
} | Where-Object Name -notin '_Total','Idle' |
Sort-Object -Property 'PercentProcessorTime' -Descending |
Select-Object -First 1 -Property $properties
1 .. 5 is the range operator, which generates the set of numbers 1,2,3,4,5. This is just a quick hack to run ForEach-Object 5 times.
Where-Object Name -notin '_Total','Idle' excludes some 'processes' that always have high values but are unlikely to be what you're looking for. Generally it is more efficient to update the call to Get-WmiObject to exclude these at that stage, but for clarity I went with this technique.
Sort-Object -Property 'PercentProcessorTime' -Descending takes all of the readings and sorts them in order from largest CPU value to lowest.
Select-Object -First 1 -Property $properties Selects just the first object in the sorted list (i.e. the one with the highest value). Note that it is better to do this last and not after each call to Get-WmiObject as it creates a new custom object for each WMI one returned, almost all of which we discard further along the line - it is more efficient to do this 'duplication' for only the final object we select.

Full output hidden on console

I don't get full output of the following code I made.
For Example:
DriveSpace : {174, 0, 98, 171...}
Notice the ellipses (...) after 171. It is skipping the rest of the output after that. You can run the following script to see my output.
#Start of script
$cpu = gwmi -Class Win32_Processor | Select-Object NumberOfCores,NumberOfLogicalProcessors
$memory = gwmi -class win32_physicalmemory | Select-Object {[math]::truncate($_.capacity / 1GB)}
$HostDescription= gwmi -Class Win32_OperatingSystem
$fqdn = "$env:computername.$env:userdnsdomain"
$OS = (gwmi Win32_OperatingSystem)
$OSarchitecture = (gwmi Win32_OperatingSystem)
$disk = gwmi Win32_LogicalDisk | Select-Object DeviceID, volumeName, {[math]::truncate($_.size / 1GB)}
$timezone = [System.TimeZone]::CurrentTimeZone
$fire = netsh advfirewall show publicprofile | select-string state
$firematch = $fire -match "off"
$slmgrResult = cscript c:\windows\system32\slmgr.vbs /dli | Select-string "License Status"
$activation = $slmgrResult -match "Licensed"
$apps = gp HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |Select DisplayName, DisplayVersion, Publisher, InstallDate
$network = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" | select-object IPAddress, DefaultIPGateway, DNSDomain, IPSubnet
$props = #{
NumberOfCores = $cpu.NumberOfCores
NumberOfLogicalProcessors = $cpu.NumberOfLogicalProcessors
Memory = $memory.{[math]::truncate($_.capacity / 1GB)}
HostDescription = $HostDescription.Description
FQDN = "$env:computername.$env:userdnsdomain"
OS = (gwmi Win32_OperatingSystem).Name
OSarchitecture = $OSarchitecture.OSArchitecture
DriveLetters = $disk.DeviceID
DriveLabels = $disk.volumeName
DriveSpace = $disk.{[math]::truncate($_.size / 1GB)}
timezone = [System.TimeZone]::CurrentTimeZone.StandardName
FirewallDisabled = $firematch
Licensed = $activation
Applications = $apps
IPAddress_Gateway_DNSDomain_subnet = $network.IPAddress, $network.DefaultIPGateway, $network.DNSDomain, $network.IPSubnet
}
New-Object PSObject -Property $props
#End of script
This is not an official answer as I think the OP needs to be clear on what output he is expecting. This is a start nonetheless
While I have not found official documentation to support this you are just seeing how PowerShell handles console output. Consider the following example which is a collection of varying sizes of arrays.
[pscustomobject]#{
data = "1","2","3","4","5"
}
Would produce the following list style output.
data : {1, 2, 3, 4...}
Notice the fifth element of the 5 property now has the ellipses. The data is still there. It has just been truncated on the console to make the output more terse and easier to read. In this case it seems folly to do so but with some objects complicated output PowerShell has to draw the line somewhere.
Prevent the ellipses
As PetSerAL pointed out you can just use the following line of code before your output.
$FormatEnumerationLimit=-1
If you look at about_Preference_Variables you will see that, by default, this is set to 4. That would support the output you are seeing. Set that value to something higher or -1 and see if it helps.
Other Potential Issues
Like in my comments I want to draw attention to the variable you created called $disk. The output is below. Note this is from my own machine and wont match yours. Still, you should get the picture
DeviceID volumeName [math]::truncate($_.size / 1GB)
-------- ---------- -------------------------------
C: 111
D: Data 499
E: Multimedia 1362
F: 0
G: CentOS 7 x86_64 3
M: Media 2794
Z: 0
Without any other information I can only assume that you want a series of free space values to display. Given that we could break those results out of the array by casting them to string. Also want to update the line that populates the variable.
$disk = gwmi Win32_LogicalDisk | Select-Object DeviceID, volumeName, #{Label="Size(GB)";Expression={[math]::truncate($_.size / 1GB)}}
Gives us the following in $disk`
DeviceID volumeName Size(GB)
-------- ---------- --------
C: 111
D: Data 499
E: Multimedia 1362
F: 0
G: CentOS 7 x86_64 3
M: Media 2794
Z: 0
Then when you build your hashtable you can cast the array to a single space delimited string like this:
DriveSpace = [string]($disk."Size(GB)")
Fairly sure there will be more questions to come from this but it is at least a start. Welcome to SO. It is always a good idea when possible to show us desired output in cases like this so we know what you are trying to achieve. Even if you think it is obvious.
Side notes
You have other properties other that $disk that might have the same issues like Applications which is a complex object. If you do have issues with those as well solving this one might get you in the right direction.
You have many calls to gwmi Win32_OperatingSystem. You should save the results of that into a variable that you can refer to whenever you need it. Right now you are losing time calling it and getting the same results. For example:
$wmiOS = gwmi Win32_OperatingSystem
This is the default formatting of Powershell at work, as provided by Out-Default. It is truncating the DriveSpace array to display in a table in your console, but the information is still there. For example, if you type:
$props.DriveSpace
... you will see the full array displayed. The default formatting behaves differently when it's handling a simple array as opposed to when it's handling a complex object like the $props one you've created.
See also:
How Powershell Outputting and Formatting REALLY works