When I type Get-Process in PowerShell, I get this:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1056 15 2952 1844 49 124.29 580 csrss
1158 78 63620 42976 356 593.47 5784 explorer
Is there a way I can concatenate all the data from row 1 onto string 1, and row 2 onto string 2, etc.
For example:
$str1 = "csrss 580 124.29 49 ..."
$str2 = "explorer 5784 593.47 356 ..."
You can combine each line fairly easily using a foreach loop.
$processes = Get-Process
$processes | % {[string[]]$processLines += $_.ProcessName + "," + $_.Id}
$processLines
The above code will give you an array of strings for each process. You will have to decide what properties you want to include on each string. If you want to create separate variable names instead of using an array that would require a bit more work.
Related
I want to find out how many java PIDs are running in order to stop them, put the values into an array, run it inside a loop and kill each process
Therefore I use the command
$a=ps | Where-Object -Property ProcessName -EQ -Value 'Java'`
Which shows me the following result:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) **Id** ProcessName
------- ------ ----- ----- ----- ------ -- -----------
661 51 748504 421716 -282 **2008** java
331 22 358464 135808 -525 **14060** java
But I am stuck regarding how to extract the Id column values, in order to loop them later
Any help would be appreciated.
Many thanks
As Santiago Squarzon commented, you can directly pipe the output of Get-Process (alias ps) to Stop-Process:
ps Java | Stop-Process
In case you want to list the killed processes, you can use -PassThru:
ps Java | Stop-Process -PassThru
So in most cases you don't even need to write a loop.
If you still have a use case where you need to explicitly loop over the process IDs, you can do it as suggested by mclayton, using member-access enumeration:
$proc = ps Java
foreach( $pid in $proc.Id ) {
# do something with $pid
"PID: $pid"
}
# ...or even shorter:
(ps Java).Id.ForEach{
"PID: $_"
}
How can I format the output in a PowerShell script from this command? When I just type it in the console it sorts nicely, but in the script it just throw all in one row.
$diskpartitions = Get-Partition |Select PartitionNumber, DriveLetter, Size, DiskId | Sort-Object DiskId
Write-Host $diskpartitions
Write-Host converts any input given to it into the form of a string. A string has to take a nicely formatted PowerShell object and convert it into, well, a string.
You should use Write-Output instead, which will render your object as you have it.
PS>Write-output $diskpartitions
PartitionNumber DriveLetter Size DiskId
--------------- ----------- ---- ------
1 16777216 \\?\scsi#disk&ven_nvme&prod_samsung_ssd_960#5&17cb1da0&0&000000#{53f56307-b6…
2 C 499537713664 \\?\scsi#disk&ven_nvme&prod_samsung_ssd_960#5&17cb1da0&0&000000#{53f56307-b6…
3 550502400 \\?\scsi#disk&ven_nvme&prod_samsung_ssd_960#5&17cb1da0&0&000000#{53f56307-b6…
1 134217728 \\?\scsi#disk&ven_nvme&prod_samsung_ssd_960#7&1a97d747&0&000000#{53f56307-b6…
2 V 499971522560 \\?\scsi#disk&ven_nvme&prod_samsung_ssd_960#7&1a97d747&0&000000#{53f56307-b6…
1 W 1000202043392 \\?\scsi#disk&ven_samsung&prod_hd103sj#5&1bc941f&0&070000#{53f56307-b6bf-11d…
1 471859200 \\?\scsi#disk&ven_samsung&prod_ssd_850_pro_256g#5&1bc941f&0&010000#{53f56307…
2 103809024 \\?\scsi#disk&ven_samsung&prod_ssd_850_pro_256g#5&1bc941f&0&010000#{53f56307…
3 16777216 \\?\scsi#disk&ven_samsung&prod_ssd_850_pro_256g#5&1bc941f&0&010000#{53f56307…
4 D 255466668032 \\?\scsi#disk&ven_samsung&prod_ssd_850_pro_256g#5&1bc941f&0&010000#{53f56307…
1 G 1000202043392 \\?\scsi#disk&ven_samsung&prod_ssd_860_evo_1tb#5&1bc941f&0&060000#{53f56307-…
1 134217728 \\?\scsi#disk&ven_seagate&prod_backup+_hub_bk#8&2a5cdee5&0&000000#{53f56307-…
2 H 6001039245312 \\?\scsi#disk&ven_seagate&prod_backup+_hub_bk#8&2a5cdee5&0&000000#{53f56307-…
Fun protip
Every line of PowerShell code has an implicit Write-Output call at the end. You can just echo out the contents of a variable by having the variable name by itself on a line, as an easy alternative.
PS> $diskpartitions
PartitionNumber DriveLetter Size DiskId
--------------- ----------- ---- ------
1 16777216 \\?\scsi#disk&ven_nvme&prod_sa
#...same content as before
This script is giving me the CPU for each node process. Which is great. But I need to know the PID for each process so that I can match specific process to CPU usage.
$ProcessName = "node"
$CpuCores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
$Samples = (Get-Counter "\Process($Processname*)\% Processor Time").CounterSamples
$Samples | Select InstanceName,#{Name="CPU %";Expression={[Decimal]::Round(($_.CookedValue / $CpuCores), 4)}}
I've searched everywhere I can think. I've tried PID, ID, ProcessID, InstanceID and many other variants.
Seems like it should be simple?
You are dot referencing specific properties and that's all you'll get back. Thus, you cannot ask for what is not supplied.
# Using variable squeezing to output results to the screen while assigning results to the variable.
($ProcessName = "dllhost")
($CpuCores = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors)
($Samples = (Get-Counter "\Process($Processname*)\% Processor Time").CounterSamples)
($Samples | Select InstanceName,#{Name="CPU %";Expression={[Decimal]::Round(($_.CookedValue / $CpuCores), 4)}})
# Results
<#
dllhost
8
Path InstanceName CookedValue
---- ------------ -----------
\\lab01\process(dllhost#2)\% processor time dllhost 0
\\lab01\process(dllhost#1)\% processor time dllhost 0
\\lab01\process(dllhost)\% processor time dllhost 0
dllhost
dllhost
dllhost
#>
Get-Process -Name 'dllhost'
# Results
<#
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
120 7 1580 6760 0.11 8612 2 dllhost
200 17 3620 11332 0.09 14176 0 dllhost
229 16 3984 12216 0.36 15940 2 dllhost
#>
Get-Counter -Counter "\Process($Processname*)\% Processor Time"
# Results
<#
Timestamp CounterSamples
--------- --------------
23-Nov-19 17:52:10 \\lab01\process(dllhost#2)\% processor time :
3.11758575755139
\\lab01\process(dllhost#1)\% processor time :
0
\\lab01\process(dllhost)\% processor time :
0
#>
So, you need to combine the above for a single result. There are differ ways to do this of course, For example:
Clear-Host
Get-Process -Name 'WUDFHost' |
ForEach {
[PSCustomObject]#{
'ProcessName' = $PSItem.ProcessName
'ProcessId' = $PSItem.Id
'Path' = $PSItem.Path
'Cookedvalue' = ((Get-Counter -Counter "\Process($($PSItem.Name))\% Processor Time").CounterSamples).CookedValue
}
}
# Results
<#
ProcessName ProcessId Path Cookedvalue
----------- --------- ---- -----------
WUDFHost 1100 C:\Windows\System32\WUDFHost.exe 21.8216373679803
WUDFHost 4020 C:\Windows\System32\WUDFHost.exe 6.23866621508705
WUDFHost 4644 C:\Windows\System32\WUDFHost.exe 9.36077443109706
WUDFHost 10280 C:\Windows\System32\WUDFHost.exe 3.11837874640775
#>
I was wondering if it was possible to call a parameter twice within a cmdlet, such as:
cmdlet-test -myCommand input1, input2 -myCommand input3, input 4
myCommand being the same command twice. Is that possible or will a user just have to write it all in one comma separated list?
If the user attempts to use the same parameter twice, they will receive an error.
get-process | select -first 2
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
201 16 3324 3456 109 0.17 9972 acrotray
409 16 3904 4948 101 0.97 10520 AdobeARM
Let's try it the conventional way:
get-process -pid 9972,10520
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
201 16 3324 3456 109 0.17 9972 acrotray
409 16 3904 4948 101 0.97 10520 AdobeARM
And your proposed method:
get-process -pid 9972 -pid 10520
Get-Process : Cannot bind parameter because parameter 'Id' is specified more than once. To provide multiple values to
parameters that can accept multiple values, use the array syntax. For example, "-parameter value1,value2,value3".
At line:1 char:23
+ get-process -pid 9972 -pid 10520
+ ~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Process], ParameterBindingException
+ FullyQualifiedErrorId : ParameterAlreadyBound,Microsoft.PowerShell.Commands.GetProcessCommand
For those who would like to separate a really long function argument into several lines, I suggest this approach:
# Just an example function
function PrintFileName {
param (
[Parameter(Mandatory = $true)] [System.String[]] $Files = #()
)
foreach ($File in $Files) {
Write-Host "${File}"
}
}
Then, the function call like this:
PrintFileName -Files C:\SomeDirectory\SomeFile.txt1,C:\SomeDirectory\SomeFile2.txt,`
C:\SomeDirectory\SomeFile2.txt,C:\SomeDirectory\SomeFile3.txt,`
C:\SomeDirectory\SomeFile4.txt,C:\SomeDirectory\SomeFile5.txt
Will output:
C:\SomeDirectory\SomeFile1.txt
C:\SomeDirectory\SomeFile2.txt
C:\SomeDirectory\SomeFile2.txt
C:\SomeDirectory\SomeFile3.txt
C:\SomeDirectory\SomeFile4.txt
C:\SomeDirectory\SomeFile5.txt
In Powershell, how can I create a mulitple records hashtable?
Like these:
> Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
> ------- ------ ----- ----- ----- ------ -- -----------
> 260 25 98568 109684 263 37.80 7896 AcroRd32
> 67 8 1236 3800 30 0.03 2052 atashost
> 122 7 1812 4496 29 0.08 1188 atiesrxx
> 126 10 16204 15936 49 7236 audiodg
> 170 21 12888 21352 106 0.14 5016 CallControl
It will be a list of objects in that case and not an hashtable. You can use New-Object to create a set of objects with those properties. Something like below:
$obj = new-object -type psobject
$obj | add-member -name Handles -MemberType NoteProperty -Value 123
and so on for each property. Look at new-object for simpler ways of doing the same.
If you already have a list of objects and want a few properties from them, use Select-Object
If your goal is to be able to utilize the Hashtables ability to use Key/Value pairs to easily lookup your data, like by the "ProcessName", then you can do this. Remember that Powershell is an Object Oriented shell. You can store objects within objects. Or in this case, Hashtables within Hashtables.
[hashtable] $ProcessDetails = #{Handles=260; NPM=25;
PM= 98568; WS=109684; VM=263; CPU=37.80; ID=7896}
$ProcessDetails
[hashtable] $Processes = #{}
$Processes.Add("AcroRd32", $ProcessDetails)
""
$Processes
""
# You can then use the various methods to extract the data.
$Processes.Get_Item("AcroRd32").ID
$Processes.AcroRd32.CPU
$Processes["AcroRd32"].VM
$Processes["AcroRd32"]["ws", "pm", "NPM", "Handles"]
Would output:
Name Value
---- -----
ID 7896
WS 109684
NPM 25
Handles 260
VM 263
PM 98568
CPU 37.8
AcroRd32 {ID, WS, NPM, Handles...}
7896
37.8
263
109684
98568
25
260
You could still create a New-Object to store you Processes details as the Hashtables Value. A PSObject has an advantage when sending output to a file, the screen, etc. But if you are doing data lookups for processing, then I like to stick with Hashtables.