Store output value in variable and do arithmetic operation in powershell - powershell

I am doing powershell script for getting memory value of some process in powershell also i need to divide the value by 1024 in order to convert KB/MB.
For example
PS >>$memory = Get-Process nginx | Select-Object WS | format-wide -Column 1
PS >>$memory
62541824
This value is in bytes. I need to convert this value into KB/MB. so I performed div operation after that.
PS >> $memory = $memory / 1024
Method invocation failed because [System.Object[]] doesn't contain a method named 'op_Division'.
At C:\script\tomcat-mem.ps1:3 char:13
+ $mem= $mem / <<<< 1024
+ CategoryInfo : InvalidOperation: (op_Division:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any one help me to resolve this error.

Because you're piping to format-wide, you're returning an object rather than a type that can be trivially cast to an int. The following would be more suitable:
$memory = Get-Process nginx | Select-Object -ExpandProperty WS
$memory / 1024
Proof:
$m = get-process explorer | select -expandproperty ws
$m.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
$m = get-process explorer | select ws | format-wide -Column 1
$m.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
You can see that the first version has been implicitly converted to an Int32, therefore it's possible to run a division operation on it.

Related

Powershell doesn't return key value in hashtable

PS C:\Users\kris> $hashx=#{}
PS C:\Users\kris> $(Get-CimInstance Win32_Process | Select-Object ProcessId, Name) | ForEach-Object { $hashx[$_.ProcessId]=$_.Name }
PS C:\Users\kris> $hashx
Name Value
---- -----
1292 svchost.exe
6032 StartMenuExperienceHost.exe
428 smss.exe
4736 powershell.exe
2580 svchost.exe
5628 explorer.exe
5164 taskhostw.exe
PS C:\Users\kris> $hashx['5164']
PS C:\Users\kris> $hashx.5164
PS C:\Users\kris> $hashx."5164"
PS C:\Users\kris> $hashx.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
Can anyone explain me what i do wrong? i'm beginner in powershell, and i don't understand why it returns null value by key?
Get-CimInstance Win32_Process returns ProcessId property as type System.UInt32. You will need to cast your key retrieval values to that type or convert the ProcessId values to System.Int32. The reason is by default the shell interprets unquoted or uncast whole numbers as System.Int32 provided the number is less than or equal to [int32]::maxvalue or System.Int64 otherwise.
In your case, you can simply use the syntax below if you don't mind working with Uint32:
$hashx[[uint32]5164]
Personally, I would convert the ProcessId value to System.Int32 (using accelerator [int]) when adding it to the hash table:
Get-CimInstance Win32_Process |
Select-Object ProcessId, Name | ForEach-Object {
$hashx[[int]$_.ProcessId] = $_.Name
}
# Now the keys can be accessed using Int32 numbers
$hashx[5164]
As an aside, you can discover property types yourself with the Get-Member command:
Get-CimInstance win32_Process |
Select -First 1 -Property ProcessId | Get-Member
TypeName: Selected.Microsoft.Management.Infrastructure.CimInstance
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
ProcessId NoteProperty uint32 ProcessId=0
Notice the definition of ProcessId shows type uint32.

Make the contents of a .md file the body of an email for outlook using powershell

I want to take the contents of an .md file and have it appear in the body of a generated email for outlook. I can generate the email just find but the body gives the following error and I have yet to find a work around.
Error:
The object does not support this method.
At line:6 char:1
+ $new.HTMLBody = $a
+ ~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Code:
$out= New-Object -comObject Outlook.Application
# $sign= Get-Content "C:\Users\Roaming\Microsoft\Signatures\sign.htm"
$recipient= "user#.com"
$new= $out.CreateItem(0)
$new.Subject = "Meeting details"
$a = Get-Content -Path "c:\temp\file.md"
$new.HTMLBody = $a
$new.Recipients.Add($recipient)
$new.save()
# $new.HTMLBody += $sign
$display= $new.GetInspector
$display.Display()
To get around the error message you posted, you need to read your file as a string rather than an array of strings. The reason is because $new.Body expects a string. By default, Get-Content returns an array with each line of a file being an element of that array. You can change this behavior with the -Raw switch, which will read the contents as one string.
$a = Get-Content -Path "c:\temp\file.md" -Raw
If the -Raw switch changes the newline formatting, you can always just join the default Get-Content array with newline characters of your choosing.
$a = Get-Content -Path "c:\temp\file.md"
$new.HTMLBody = $a -join "`r`n"
You can see the type differences in your original code using the GetType() method available to PowerShell objects.
$a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
$new.Body.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object

Trouble accessing members of select-string output when input is a system.array

I am calling restAPIs and some of them return multiple results, I am trying use Select-String to get the correct line in the Array, but it returns a matchinfo object with a value starting with #{... I can't get this value into a hashtable or object so I can extract a member from the string.
I tried converting the MatchInfo object to a string with out-string and then putting that result in a hashtable. Get following error:
Cannot convert the "
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
" value of type "System.String" to type "System.Collections.Hashtable".
Have a PSCustomObject with the following contents:
PS C:> $_expFilesRet
href export_files
---- ------------
/api/v1/user_identities/289362/export_files {#{id=352475;
href=/api/v1/exports/458234/export_files/3...
The export files method of the above is
PS C:\> $_ExpFilesRet.export_files.getType();
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
with the following value:
PS C:\> $_expFilesRet.export_files
id href export_id status
-- ---- --------- ------
352475 /api/v1/exports/458234/exp... 458234 Available
278697 /api/v1/exports/357459/exp... 357459 Available
Attempted the following
PS C:\> $_temp=$_ExpFilesRet.export_files | select-string -pattern $_postret.export_files.export_id
PS C:\> $_temp
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
PS C:\> $_temp=$_ExpFilesRet.export_files | select-string -pattern $_postret.export_files.export_id | out-str
ing -width 1000
PS C:\> $_temp
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
PS C:\> [hashtable]$_temp=$_temp
Cannot convert the "
#{id=352475; href=/api/v1/exports/458234/export_files/352475; export_id=458234; status=Available}
" value of type "System.String" to type "System.Collections.Hashtable".
At line:1 char:1
+ [hashtable]$_temp=$_temp
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
I am trying to get the value of ID (352475) from the resulting string in $_temp.
Use Where-Object rather than Select-String to filter objects:
$_temp = $_ExpFilesRet.export_files |Where-Object export_id -eq $_postret.export_files.export_id |Select -Expand id

PowerShell Convert output to hashtable array (data type conversion)

This a data type conversion issue.
I am trying to get the names of computers out of SCCM and feed it into SCCM Report. The report commandlet receives hashtable where the variable must be named "Computer Name". The value is the computer name.
ex. $computer = #{"Computer Name" = "MyComp01"}
Outputing Commandlet example (get computer names from SCCM) This works.
$unknownoutputtype = Get-CMDevice -CollectionName "My Collection Computers" | select #{N="Computer Name";E={$_.Name}}
--Output--
Computer Name
-------------
MyComp01
MyComp02
MyComp03
MyComp04
MyComp05
MyComp06
PS> $unknownoutputtype.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Recieving Commandlet example (process the query) This works:
$computer = #{"Computer Name" = "MyComp01"}
invoke-cmreport -ReportPath "Software - Companies and Products/Software registered in Add Remove Programs on a specific computer" -reportparameter $Computer -OutputFormat excel
I need the "Get-CMDevice" line to output as the type below.
PS> $Computer.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
My failed attempt
PS> Get-CMDevice -CollectionName "My Collection Computers" |select #{N="Computer Name";E={$_.Name}} | Foreach-object {invoke-cmreport -ReportPath "Software - Companies and Products/Software registered in Add Remove Programs on a specific computer" -SiteCode "MySite" -reportparameter $_ -OutputFormat Excel}
Error output:
Invoke-CMReport : Cannot bind parameter 'ReportParameter'. Cannot convert value "#{Computer Name=MyComp01}" to type "System.Collections.Hashtable". Error: "Cannot convert the "#{Computer Name=MyComp01}" value of type
"Selected.Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine.WqlResultObject" to type "System.Collections.Hashtable"."
At line:1 char:280
+ ... s on a specific computer" -SiteCode "{removed}" -reportparameter $_ -Output ...
+ ~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-CMReport], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ConfigurationManagement.Cmdlets.Reporting.Commands.InvokeReportCommand
Select-Object will always output a PSCustomObject, not a hashtable.
Just construct the hashtable inside the ForEach-Object body before calling Invoke-CMReport:
Get-CMDevice -CollectionName "My Collection Computers" |Select-Object -ExpandProperty Name | Foreach-object {
$ReportParameter = #{ 'Computer Name' = $_ }
invoke-cmreport -ReportPath "Software - Companies and Products/Software registered in Add Remove Programs on a specific computer" -SiteCode "MySite" -reportparameter $ReportParameter -OutputFormat Excel
}

Putting a specific Powershell Get-Counter Statistic into a variable

I'd like to pull a specific statistics from a _Total (the CounterSamples) into a variable, in order to further parse it.
This is what I've tried.
Trying to index with [1] gives error further below.
Looping didn't seem to get me very far either.
cls
$statToCollect = '\Process(_Total)\IO Data Operations/sec'
Get-Counter $statToCollect
Write-Host "================"
$saveStats = Get-Counter $statToCollect
$ctrSamples = $saveStats[1].CounterSamples
Write-Host "$ctrSamples"
Write-Host "$($saveStats)"
Write-Host "================"
$diskStats = Get-Counter $statToCollect
$diskStatsLoopCounter = 1
foreach ($diskStat in $diskStats)
{
if ($diskStatsLoopCounter -eq 1)
{
write-host "$($diskStat.CounterSamples)"
}
$diskStatsLoopCounter = $diskStatsLoopCounter + 1
}
Results:
Timestamp CounterSamples
--------- --------------
12/29/2014 9:27:49 AM \\mpcname\process(_total)\io data operations/sec :
970.6265098029
================
Unable to index into an object of type Microsoft.PowerShell.Commands.GetCounter.PerformanceCo
unterSampleSet.
At C:\Users\neal.walters\Documents\DiskUtil.ps1:6 char:26
+ $ctrSamples = $saveStats[ <<<< 1].CounterSamples
+ CategoryInfo : InvalidOperation: (1:Int32) [], RuntimeException
+ FullyQualifiedErrorId : CannotIndex
Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSampleSet
================
Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample
In your particular case $saveStats is only the one element.
PS C:\Users\mcameron> $saveStats.Count
1
Which is why this command would have returned null output as there is not a second.
PS C:\Users\mcameron> $saveStats[1]
Since there was only the one element either of the following options would have worked for this case.
PS C:\Users\mcameron> $saveStats[0]
PS C:\Users\mcameron> $saveStats
Also as for the line Write-Host "$($saveStats)" since $saveStats is an object and not a string it would not expand the way you expect. Pretty sure this occure because the ToString() is not overloaded to handle this so just the object type is outputted. Simply having $saveStats on its own would allow powershell to format it properly using its own built-in cmdlets.
PS C:\Users\mcameron> $saveStats
Timestamp CounterSamples
--------- --------------
12/29/2014 10:56:53 AM \\c3935\process(_total)\io data operations/sec :
27.7291444862573
Similar issue with the line write-host "$($diskStat.CounterSamples)" which has the same response as above.
As the other commenters and posters have said you most likely want one of the properties like CookedValue which can be easily converted to a string.
write-host "$($diskStat.CounterSamples.CookedValue)"
Using PowerShell version 4 on Windows 8.1:
Get-Counter returns a PerformanceCounterSampleSet and you can access the CounterSamples property to get an array of PerformanceCounterSample objects.
The particular property that you're interested in is CookedValue:
$statToCollect = '\Process(_Total)\IO Data Operations/sec'
$total = (Get-Counter $statToCollect).CounterSamples.CookedValue
This gets you the result as a double:
PS> $total
28.9450419770711
PS> $total.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType