Powershell killing processes - what's wrong with my string? - powershell

I know that working code is
Get-Process firefo* | Stop-Process
But my first guess was
Get-Process | findstr firefox | Stop-Process
It didn't work.
Stop-Process : The input object cannot be bound to any parameters for the command
either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
At line:1 char:33
+ Get-Process | findstr firefox | Stop-Process
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: ( 1379 317... :PSObject) [Stop-Process], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.StopProcessCommand
I understand that string
1342 306 1228412 1279864 -1671 ...71,42 35912 firefox
is bad for process killing, but why?
PS C:\Users\adamg> Get-Process firefo*
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1342 306 1228412 1279864 -1671 ...71,42 35912 firefox
The above works just fine, even with column headers in reply.

findstr is a commandline utility that produces string output. Get-Process outputs Process objects, which is what Stop-Process expects as input. It could also handle a list of process IDs, but it can't parse the formatted string from findstr.
In PowerShell you normally wouldn't use findstr anyway. Use a Where-Object filter instead:
Get-Process | Where-Object { $_.ProcessName -like '*firefox*' } | Stop-Process

Related

Extract the values of a column and put them into an array

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: $_"
}

Using Powershell called from a bat file, Need to get owner/user of a windows process, but owner isn't showing up

I need to get the path and owner of certain processes on a remote computer and use a batch file to get it. So far, I've come up with something that gives me the path, but not the owner:
powershell -command "Get-WmiObject -Class win32_process -ComputerName myserver.mydomain.local -Filter 'name like """"%%myprocess%%""""' | select path,GetOwner"
For that, GetOwner is blank.
How can I get this to work or accomplish the same objective with another PS query or batch command?
GetOwner() is a method. User is a property returned by getowner() that is probably what you want.
set myprocess=powershell
powershell "Get-WmiObject win32_process -computername myserver.mydomain.local | where name -match %myprocess% | select path,#{n='Owner';e={$_.getowner().user}}"
Path Owner
---- -----
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe admin
Or you can use get-process. EDIT: Hmm looks like -computername and -includeusername can't go together. I can test it with "%computername%" but not "localhost".
powershell "get-process -computername %computername% -includeusername *%myprocess%* | select path,username"
Get-Process : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ get-process -computername DESKTOP-JQ7B7TZ -includeusername *powershel ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Process], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.GetProcessCommand
If remote powershell were working:
powershell "invoke-command myserver.mydomain.local { get-process -includeusername *%myprocess%* | select path,username }"
Path : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
UserName : DESKTOP-JQ7B7TZ\admin
PSComputerName : myserver.mydomain.local
RunspaceId : b1bc87a7-1c21-4f91-a238-bbb68978ea6c

output not a trimmed value and causing the output error

I have written few powershell command to perform some auditing on HyperV Clusters. The command works fine, But can anyone help me to trim the output, so that I can collect what I need ?
##Audit-CreatingDC
$AuditDC = Invoke-Command -ComputerName $ComputerName {Get-ChildItem -Path HKLM:\cluster\resources -recurse | get-itemproperty -name CreatingDC -erroraction 'silentlycontinue'}| ft CreatingDC,PSComputerName
####Audit-iSCSI
#Show which hosts are not communicating to the storage with the ‘-s’ and where there are duplicated targets:
$AuditISCSI = Invoke-Command -ComputerName $ComputerName { get-iscsisession } | FT PSComputerName, InitiatorPortalAddress, IsConnected -autosize
######Discover checkdsk errors - "Scan Needed". Execute using txt of one node from each cluster.
$AuditCHKDSK = Invoke-Command -ComputerName $ComputerName { get-volume | Where-Object –FilterScript { $_.HealthStatus -eq "Scan Needed" }} | FT PSComputerName, FileSystem, HealthStatus -autosize
And the output for each is below
CreatingDC PSComputerName
---------- --------------
\\dc-sc-02.oim.corp.com slcoc037
PSComputerName InitiatorPortalAddress IsConnected
-------------- ---------------------- -----------
slcoc037 10.214.61.107 True
PSComputerName FileSystem HealthStatus
-------------- ---------- ------------
slcoc037 CSVFS 1
But I need the output for above in this format
\\dc-sc-02.oim.corp.com
10.241.81.107
CSVFS 1
Can anyone help me to trim these 3 commands ?
You probably already know that almost all powershell outputs are objects. Objects have properties. Displaying a particular property would use the syntax $Object.Propertyname. In your case, CreatingDC is a property of the $AuditDC Variable object. Applying that logic, all you need to do is, display it like this:
$AuditDC.CreatingDC
$AuditISCSI.InitiatorPortalAddress
$AuditCHKDSK.FileSystem

How to get the process start time in PowerShell

How do I get the process start time in PowerShell?
I tried this in the PowerShell prompt:
(Get-Process MyProcessName).StartTime.ToString('yyyyMMdd')
And this is the error I got:
(Get-Process MyProcessName).StartTime.ToString('yyyyMMdd')
You cannot call a method on a null-valued expression.
At line:1 char:1
+ (Get-Process MyProcessName).StartTime.ToString('yyyyMMdd_h ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
But when I do Get-Process MyProcess, I see my process:
> Get-Process MyProcess
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
2906 132 81136 79132 889 20656 myprocess
And when I do 'Get-Date -format 'yyyyMMdd', it returns '20151207', so I think the date format is correct.
As a one-liner you could use:
Get-Process ProcessName | select starttime
Do it like this:
(Get-Date (Get-Process explorer).StartTime).ToString('yyyyMMdd')
Run as admin:
Get-Process | select name, starttime | findstr your_process_name_here
It looks like you're not inputting the process name correctly ("MyProcessName" vs. "MyProcess"). You have
(Get-Process MyProcessName).StartTime.ToString('yyyyMMdd')
But it should be
(Get-Process MyProcess).StartTime.ToString('yyyyMMdd')
per your examples.
if you want to get the start time of a specific process use the following substituting "process name" with its name:
Get-Process ProcessName | select Name, StartTime
or to get all running processes' start times
Get-Process | select Name, StartTime

Reusing powershell cmdlet parameters

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