I want to monitor python scripts in powershell. For that I am using Get-ProcessByName. I want to monitor individual python and JAVA scripts running and store its processId in a csv file according to individual script running. Get-ProcessByName lists all the the python or JAVA processes in the same row. How do I separate all the script names in different rows. What I am currently doing is-
$process = [System.Diagnostics.Process]
$outputTime = $process::GetProcessesByName($processName.ProcessName)[0].TotalProcessorTime.TotalMilliseconds
$name = ($process::GetProcessesByName($processName.ProcessName)[0]) | Select-Object -ExpandProperty ProcessName
$extra = Get-WmiObject -Class Win32_Process -Filter "name = '$name.exe'" | Select-Object -ExpandProperty CommandLine
Here in $extra I am getting names of all the python scripts.How do I seperate all the scripts
From my understanding Win32_Process already has all the information you need. You can use Select-Object and Calculated Properties to modify if required.
Get-WmiObject -Class Win32_Process |
Where-Object {$_.Name -eq 'python.exe'} |
Select-Object -Property Name,
#{Name = 'Script'
Expression = {$_.CommandLine -replace
'(.*)\\(?<py>.*\.py)|(.*)\ (?<py>.*\.py.*)',
'${py}'}
},
#{
Name = 'CpuTime'
Expression = {($_.KernalModeTime + $_.UserModeTime) / 10000000}
} |
Sort-Object -Property CpuTime -Descending
This would output something like
Name Script CpuTime
---- ------ -------
python.exe completion.py preview 1,65625
python.exe Untitled-1.py 0,015625
Of course this would work for java.exe or other, even multiple processes, as well. If you dont want to output the full CommandLine replace the first Calculated Property with CommandLine.
I would use this
Get-Process | where ProcessName -Match python
Related
I am having an issue with exporting results to a txt in Powershell.
I have 2 commands I need to run and when they are done, I am hoping to get something like this:
Name Version
---- -------
Mitel Connect 214.100.1252.0
Cylance Unified Agent 2.4.1070.1
Instead of this:
Name Version
---- -------
Mitel Connect 214.100.1252.0
Name Version
---- -------
Cylance Unified Agent 2.4.1070.1
Here is the code:
get-package 'Microsoft Edge','Mitel Connect', '*7-Zip*','*Cylance*','*Office Profession*','*Dameware*','Cisco AnyConnect Secure Mobility Client' | select name,version | Out-File "C:\temp\export.txt" -Append
Get-WmiObject -Class Win32_Product | where Name -eq "Manageengine AssetExplorer Agent" | select Name, Version | Out-File "C:\temp\export.txt" -Append
I have tried piping the code, google and nothing works,
Does anyone have any idea who to get the output?
If the output file only needs to record the output from these two commands:
Call (& ) them in sequence via a script block ({ ... })...
... pipe the output to a single Select-Object call ...
... which you can then pipe to a single Out-File call.
& {
Get-Package 'Microsoft Edge','Mitel Connect', '*7-Zip*','*Cylance*','*Office Profession*','*Dameware*','Cisco AnyConnect Secure Mobility Client'
Get-CimInstance -Class Win32_Product | Where-Object Name -eq "Manageengine AssetExplorer Agent"
} |
Select-Object Name, Version |
Out-File "C:\temp\export.txt"
That way, the output objects are formatted together, as a single table, by the single Out-File call.
(By contrast, if you call Out-File multiple times, you'll get a separate table in the file for each call, which is what you saw.)
Note, however, that the resulting file format is only meant for display purposes, as it uses the same rich formatting you'd see in the console (terminal) by default, which is meant for the human observer rather than programmatic processing.
For programmatic processing, consider a structured text format, such as CSV (Export-Csv), which also allows you to append to the file iteratively later.
Since you only get the name and version of these objects, pushing them into an array and then exporting the array would work as you intend it to. However, in case you try to add more properties in each select, this will not work. The objects in the array will preserve the structure of the 1st element added to it.
This is the code that managed to create the desired result.
$arr = #()
get-package 'Microsoft Edge' | select name, version | % { $arr += $_ }
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
The following 2 snippets show the undesired effect if you try to add properties in the select that don't exist in both structures.
$arr = #()
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Vendor, Version | % { $arr += $_ }
get-package 'Microsoft Edge' | select name,version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
This will have an empty Vendor prop for the "get-package" objects
$arr = #()
get-package 'Microsoft Edge' | select name,version | % { $arr += $_ }
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Vendor, Version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
This will disregard the "Vendor" property for all data from "Get-WmiObject" Command
I am storing the following query value in a variable:
$unquotedPaths = Get-WmiObject -Class Win32_Service | Select-Object -Property Name,DisplayName,PathName,StartMode | Select-String "auto"
The problem starts when i print that variable becouse the variable takes from the query an object which is formed by hashtables like in this output:
PS C:\Users\pc> Get-WmiObject -Class Win32_Service | Select-Object -Property Name,DisplayName,PathName,StartMode | Select-String "auto"
#{Name=AGMService; DisplayName=Adobe Genuine Monitor Service; PathName="C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGMService.exe"; StartMode=Auto}
#{Name=AGSService; DisplayName=Adobe Genuine Software Integrity Service; PathName="C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGSService.exe"; StartMode=Auto}
#{Name=asComSvc; DisplayName=ASUS Com Service; PathName=C:\Program Files (x86)\ASUS\AXSP\1.01.02\atkexComSvc.exe; StartMode=Auto}
#{Name=AudioEndpointBuilder; DisplayName=Compilador de extremo de audio de Windows; PathName=C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p; StartMode=Auto}
How i can get and output like this:
Name DisplayName PathName Startmode
---------- ------------- ------------ ------------
ExampleName ExampleDisplayName C:\Example Auto
Select-String is meant to search and match patterns among strings and files, If you need to filter an object you can use Where-Object:
$unquotedPaths = Get-WmiObject -Class Win32_Service |
Where-Object StartMode -EQ Auto |
Select-Object -Property Name,DisplayName,PathName,StartMode
If the filtering required more complex logic you would need to change from Comparison Statement to Script Block, for example:
$unquotedPaths = Get-WmiObject -Class Win32_Service | Where-Object {
$_.StartMode -eq 'Auto' -and $_.State -eq 'Running'
} | Select-Object -Property Name,DisplayName,PathName,StartMode
I'm trying to get the memory usage of process per user (like task manager), that info comes to Memory (Private working set) if we convert that values into MB we should get the memory usage, like in the users view in task manager...
Maybe i missing something, if someone know about this pls tell me.
And this is my script
Get-WmiObject Win32_Process | Sort-Object -Property privatememorysize -Descending |
Select processname, #{Name="Mem Usage(MB)";Expression={[math]::round($_.privatememorysize/ 1mb,2)}},#{Name="UserID";Expression={$_.getowner().Domain+"\"+$_.getowner().user}} | fl *
Try using WorkingSetSize instead of PrivateMemorySize.
Get-WmiObject Win32_Process | Sort-Object -Property WorkingSetSize -Descending |
Select processname, #{Name="Mem Usage(MB)";Expression={[math]::round($_.WorkingSetSize / 1mb,2)}},#{Name="UserID";Expression={$_.getowner().Domain+"\"+$_.getowner().user}} | FL
The issue is that the Win32_Process class doesn't have a property named 'privatememorysize'. Replacing that with 'privatepagecount' instead makes this work as expected.
Get-WmiObject Win32_Process | Sort-Object -Property privatepagecount -Descending |
Select processname, #{Name="Mem Usage(MB)";Expression={[math]::round($_.privatepagecount/ 1mb,2)}},#{Name="UserID";Expression={$_.getowner().Domain+"\"+$_.getowner().user}}
I see, that is not the same, so we have the issue here where the WMI object doesn't give private working set, and other methods that do include that don't have the user. So what we can do is use Get-Process to get each process and the private working set, and use Get-WMIObject to get the user associated with each object, and then match them up. Probably best to make a hashtable from one to reference, then use that to add the property to the other object. So, let's do that!
#Get WMI Process objects
$WMIProcs = Get-WmiObject Win32_Process
#Get Get-Process object
$GPProcs = Get-Process
#Convert Get-Process objects to a hashtable for easy lookup
$GPHT = #{}
$GPProcs | ForEach-Object {$GPHT.Add($_.ID.ToString(),$_)}
#Add PrivateWorkingSet and UserID to WMI objects
$WMIProcs|ForEach-Object{
$_ | Add-Member "Mem Usage(MB)" $([math]::round($GPHT[$_.ProcessId.ToString()].PrivateMemorySize64/1mb,2))
$_ | Add-Member "UserID" $($_.getowner().Domain+"\"+$_.getowner().user)
}
#Output to screen
$WMIProcs | Format-Table ProcessName, "Mem Usage(MB)", UserID
Get-Service *sql* | sort DisplayName | out-file c:/servicelist.txt
I have a one line PowerShell script to extract list of all services running on my local machine, now, in addition to displaying "Status", "Name" and "DisplayName" I also want to display "Path to executable"
I think you'll need to resort to WMI:
Get-WmiObject win32_service | ?{$_.Name -like '*sql*'} | select Name, DisplayName, State, PathName
Update
If you want to perform some manipulation on the selected data, you can use calculated properties as described here.
For example if you just wanted the text within quotes for the Pathname, you could split on double quotes and take the array item 1:
Get-WmiObject win32_service | ?{$_.Name -like '*sql*'} | select Name, DisplayName, #{Name="Path"; Expression={$_.PathName.split('"')[1]}} | Format-List
Get-CimInstance can also be used to achieve the same, see here for the difference between CIM and WMI.
Get-CimInstance win32_service | ?{$_.Name -like '*sql*'} | select Name, DisplayName, #{Name="Path"; Expression={$_.PathName.split('"')[1]}} | Format-List
Since Get-WmiObject have been deprecated in PowerShell Core, you can use
Get-CimInstance -ClassName win32_service | ?{$_.Name -match '^sql'} | Select Name, DisplayName, State, PathName >> C:\temp\sqlservices.txt
instead.
If you don't need to check against a regular expression you can also use the -Filter parameter:
Get-CimInstance -ClassName win32_service -Filter "Name like 'sql%'" | Select Name, DisplayName, State, PathName >> C:\temp\sqlservices.txt
A variant on the WMI Query that may be faster (I just had to do this for an SCCM Client)
$SQLService=(get-wmiobject -Query 'Select * from win32_service where Name like "*SQL*"') | Select-object Name, DisplayName, State, Pathname
The other trick is to trap for the multiple SQL results if you want the path names without the Double Quotes (so you can action upon them)
$SQLService | Select-Object Name, DisplayName, State, #{Name='PathName';Expression=$_.Pathname.replace('"','')}
The big advantage to using -query in the get-wmiobject (or get-ciminstance) is the speed of processing. The older example gets a full list and then filters, whilst the latter grabs a very direct list.
Just adding in two cents :)
Cheers all!
Sean
The Energized Tech
You can also use the Regular Expression pattern and dump the result to file.
Get-WmiObject win32_service | ?{$_.Name -match '^sql'} | select Name, DisplayName, State, PathName >> C:\temp\sqlservices.txt
I'm not comfortable with the accepted answer's use of Expression={$_.PathName.split('"')[1]}} because it doesn't handle the variants of quotes, spaces, and args that I see in the data.
Here's a clunky method that does.
function PathFromServicePathName($pathName) {
# input can have quotes, spaces, and args like any of these:
# C:\WINDOWS\system32\lsass.exe
# "C:\Program Files\Realtek\Audio\HDA\RtkAudioService64.exe"
# C:\WINDOWS\system32\svchost.exe -k netsvcs -p
# "C:\Program Files\Websense\Websense Endpoint\wepsvc.exe" -k ss
# if it starts with quote, return what's between first and second quotes
if ($pathName.StartsWith("`"")) {
$pathName = $pathName.Substring(1)
$index = $pathName.IndexOf("`"")
if ($index -gt -1) {
return $pathName.Substring(0, $index)
}
else {
# this should never happen... but whatever, return something
return $pathName
}
}
# else if it contains spaces, return what's before the first space
if ($pathName.Contains(" ")) {
$index = $pathName.IndexOf(" ")
return $pathName.Substring(0, $index)
}
# else it's a simple path
return $pathName
}
Get-WmiObject win32_service | select Name, DisplayName, #{Name="Path"; Expression={PathFromServicePathName $_.PathName}} | Format-List
A variant with Format-List with full path, results in file :
Get-WmiObject win32_service | Format-Table -Wrap -AutoSize -Property State,Name,PathName | out-file C:\servicelist.txt
I am trying to get a list of running processes and filter by two process names - can any one tell me how to get this working?
I've so far got it working and filtering out one process name:
$rn = Get-WMIObject Win32_Process -computer servername `
-credential mydomain\administrator -filter "Name='program1.exe'" |
select -expand path
$lst = Get-Content “C:\path\path2\List.txt”
Compare-Object $lst $rn
What I want it to do is filter two process names but nothing I've tried works. Any ideas?
Here's how to get a complete set of Process objects which match a list of process names you're interested in.
$ProcessNames = #( 'explorer.exe', 'notepad.exe' )
Get-WmiObject Win32_Process -Computer 'localhost' |
Where-Object { $ProcessNames -contains $_.Name } |
Select-Object ProcessID, Name, Path |
Format-Table -AutoSize
This example finds all processes, then filters that list by sending them to a pipeline filter that checks to see if the process name is contained in the list of interesting process names. The main benefit of using the pipeline this way is that you can easily access other attributes (such as ProcessID) of the returned processes.
ProcessID Name Path
--------- ---- ----
5832 explorer.exe C:\Windows\Explorer.EXE
4332 notepad.exe C:\Windows\system32\NOTEPAD.EXE
2732 notepad.exe C:\Windows\system32\notepad.exe
Use WQL operators like OR, AND, LIKE etc:
Get-WMIObject Win32_Process -computer servername -credential mydomain\administrator -filter "Name='program1.exe' OR Name='program2.exe'"
Create an array of the processes you're after:
$processes = #('winword.exe', 'notepad.exe', 'excel.exe') | `
% {
$rn = Get-WMIObject Win32_Process -computer servername -credential mydomain\admin -filter "Name='$_'" | select -expand path
#$lst = Get-Content “C:\path\path2\List.txt”
#Compare-Object $lst $rn
write-host $rn
}
I've commented out your compare so you can see how we are looping through the array clearly.
if I understood well try this:
$rn = Get-WMIObject Win32_Process -computer servername -credential mydomain\administrator -filter "Name='program1.exe OR Name='program2.exe'"
Compare-Object $rn[0].path $rn[1].path # if there are only one instance for process with name program1.exe and program2.exe