Powershell - Process List with arguments - powershell

I am trying to find a way to list processes with;
PID
Process Name
CPU Usage
Execution Path
Port Number (TCP and UDP)
Description
and export it in a csv file.
Is it possible? If not, can this list be configured to search the process name as "like process_name" ?
For example, list multiple process names (as I specify) with other arguments.
So far, I've found this one but it doesn't include the port numbers;
Get-Process | select id, processname,cpu,path,description | where {$_.path -like "*postgre*"} | Export-Csv -Path C:\temp\process.csv -Delimiter ',' -NoTypeInformation
Thanks.

Here's a new function I whipped together called Get-ProcessPlus. It supports calling with process name(s) or process id(s) or without any parameters (will return all processes).
Example of output:
ProcessName : NVIDIA Web Helper
Id : 10184
Description : NVIDIA Web Helper Service
Path : C:\Program Files (x86)\NVIDIA Corporation\NvNode\NVIDIA Web Helper.exe
CPU usage (s) : 0,59375
TCP Addresses : 127.0.0.1
TCP Ports : 13549
UDP Addresses : 127.0.0.1
UDP Ports : 10010
Either run this code in ISE or VSCode, save it and dot source it (eg. . c:\path\to\Get-ProcessPlus.ps1 or maybe add it to your profile.
Then just call it with Get-ProcessPlus. Using a parameter name is optional, just providing one or more process ids or names will work, eg. Get-ProcessPlus chrome,firefox or Get-ProcessPlus 1044,894,432.
Finally, here's the code:
function Get-ProcessPlus {
[CmdletBinding(DefaultParameterSetName = 'Default')]
param (
[Parameter(ParameterSetName='ProcessName',Position = 0)]
[string[]]
$Name,
[Parameter(ParameterSetName='PID',Position = 0)]
[int[]]
$Id
)
# Check which parameter set is in use and get our processes
switch ($PSCmdlet.ParameterSetName) {
'ProcessName' {
$AllProcesses = Get-Process -Name $Name
break
}
'PID' {
$AllProcesses = Get-Process -Id $Id
break
}
default { $AllProcesses = Get-Process }
}
foreach ($Process in $AllProcesses) {
# Retrieve TCP and UDP Connection information for the current process (if any)
$UDPConnections = Get-NetUDPEndpoint -OwningProcess $Process.Id -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPConnections = Get-NetTCPConnection -OwningProcess $Process.Id -State Listen -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPPorts = $TCPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$UDPPorts = $UDPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$TCPAddresses = $TCPConnections.LocalAddress | Select-Object -Unique
$UDPAddresses = $UDPConnections.LocalAddress | Select-Object -Unique
# Collect and output all information about the current process
[PSCustomObject] #{
'ProcessName' = $Process.ProcessName
'Id' = $Process.Id
'Description' = $Process.Description
'Path' = $Process.Path
'CPU usage (s)' = $Process.CPU
'TCP Addresses' = $TCPAddresses
'TCP Ports' = $TCPPorts
'UDP Addresses' = $UDPAddresses
'UDP Ports' = $UDPPorts
}
}
}

Related

Modding a PowerShell Script Found on Stack Overflow

I found this script Get-ProcessPlus by PMental here on Stack Overflow. With the help of zett42
and several others I manged to get it to run (very new to PS). Thanks guys, It had everything I was really looking for.
I opted too see if I could have the script add one more feature. I wanted it too return the commandline value of the process. I got it to partially work. With my modifications it still runs as default, and by Id, but no longer by name. I have done quite a bit of reading but still can not get it to work properly. Here is the code and my mods. Any help would be appreciated.
*$Command = Get-WmiObject Win32_Process | select name, CommandLine*
function Get-ProcessPlus {
[CmdletBinding(DefaultParameterSetName = 'Default')]
param (
[Parameter(ParameterSetName='ProcessName',Position = 0)]
[string[]]
$Name,
*[Parameter(ParameterSetName='CommandLine',Position = 0)]
[string[]]
$Command,*
[Parameter(ParameterSetName='PID',Position = 0)]
[int[]]
$Id
)
# Check which parameter set is in use and get our processes
switch ($PSCmdlet.ParameterSetName) {
'ProcessName' {
$AllProcesses = Get-Process -Name $Name
break
}
*'CommandLine' {
$AllProcesses = Get-Process -Name $Command
break
}*
'PID' {
$AllProcesses = Get-Process -Id $Id
break
}
default { $AllProcesses = Get-Process }
}
foreach ($Process in $AllProcesses) {
# Retrieve TCP and UDP Connection information for the current process (if any)
$UDPConnections = Get-NetUDPEndpoint -OwningProcess $Process.Id -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPConnections = Get-NetTCPConnection -OwningProcess $Process.Id -State Listen -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPPorts = $TCPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$UDPPorts = $UDPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$TCPAddresses = $TCPConnections.LocalAddress | Select-Object -Unique
$UDPAddresses = $UDPConnections.LocalAddress | Select-Object -Unique
# Collect and output all information about the current process
[PSCustomObject] #{
'ProcessName' = $Process.ProcessName
'Id' = $Process.Id
'Description' = $Process.Description
'Path' = $Process.Path
*'CommandLine' = $Process.Command*
'CPU usage (s)' = $Process.CPU
'TCP Addresses' = $TCPAddresses
'TCP Ports' = $TCPPorts
'UDP Addresses' = $UDPAddresses
'UDP Ports' = $UDPPorts
}
}
}
You need to match the Get-WMIObject output to the Get-Process Output. In your case, just replace this line:
'CommandLine' = $Process.Command
With this:
# Query WMI for process command line
'CommandLine' = Get-WmiObject -Query "
SELECT CommandLine from Win32_Process WHERE ProcessID = $($Process.ID)" |
# Select only the commandline property so we can display it
Select -ExpandProperty CommandLine
My output looks like so:
Get-ProcessPlus -Name notepad
ProcessName : notepad
Id : 10568
Description : Notepad
Path : C:\WINDOWS\system32\notepad.exe
CommandLine : "C:\WINDOWS\system32\notepad.exe" C:\temp\test.txt
CPU usage (s) : 0.390625

Why doesn't Get-NetFirewallRule show all information of the firewall rule?

I'm trying to find if a firewall rule already existing, with the same name, same configuration, like: localport.
So I use Get-NetFirewallRule to list all rules, but the rules returned do not contain the information of port, also some other information are missing. where can I find all the config of a rule. Below is the attributess returned:
Name
DisplayName
Description
DisplayGroup
Group
Enabled
Profile
Platform
Direction
Action
EdgeTraversalPolicy
LooseSourceMapping
LocalOnlyMapping
Owner
PrimaryStatus
Status
EnforcementStatus
PolicyStoreSource
PolicyStoreSourceType
What I don't think is understood by many, including me recently, is that the Get-NetFirewall*Filter commands provide a speedy shortcut to searching the firewall rules, like the -filter option does in other commands. If I were to do this, it would take a very long time:
Get-NetFirewallRule | Get-NetFirewallPortFilter |
Where LocalPort -eq 3389
While this is almost instant:
Get-NetFirewallPortFilter | Where LocalPort -eq 3389
And Get-NetFirewallPortFilter actually returns the name of the firewall rule in the InstanceID property, which isn't shown by default. That's why you can pipe Get-NetFirewallPortFilter back into Get-NetFirewallRule.
Get-NetFirewallPortFilter | Where LocalPort -eq 3389 |
Get-NetFirewallRule
Here's a function that gives netsh-like verbose output, with the ports, addresses, and applications:
function mynetsh {
param($displayname)
$rule = get-netfirewallrule -displayname $displayname
$address = $rule | Get-NetFirewallAddressFilter
$port = $rule | Get-NetFirewallPortFilter
$application = $rule | Get-NetFirewallApplicationFilter
[pscustomobject]#{
DisplayName = $rule.DisplayName
Description = $rule.Description
Enabled = $rule.Enabled
Direction = $rule.Direction
Profile = $rule.Profile
DisplayGroup = $rule.DisplayGroup
LocalAddress = $address.LocalAddress
RemoteAddress = $address.RemoteAddress
Protocol = $port.Protocol
LocalPort = $port.LocalPort
RemotePort = $port.RemotePort
EdgeTraversalPolicy = $rule.EdgeTraversalPolicy
Program = $application.Program
Action = $rule.Action
}
}
mynetsh 'Remote Desktop - User Mode (TCP-In)'
DisplayName : Remote Desktop - User Mode (TCP-In)
Description : Inbound rule for the Remote Desktop service to allow RDP traffic. [TCP 3389]
Enabled : False
Direction : Inbound
Profile : Any
DisplayGroup : Remote Desktop
LocalAddress : Any
RemoteAddress : Any
Protocol : TCP
LocalPort : 3389
RemotePort : Any
EdgeTraversalPolicy : Block
Program : %SystemRoot%\system32\svchost.exe
Action : Allow
In order to find the port numbers that are already in the firewall rules, you can use a different cmdlet Get-NetFirewallPortFilter.
(Info)
Use Get-NetFirewallRule to filter which subset of rules you want to look at and pipe it to the above cmdlet. eg.:
Get-NetFirewallRule -DisplayName "SQL Broker Service" | Get-NetFirewallPortFilter
Sounds like the property you are after is localport.
Use the below command to list all.
Get-NetFirewallRule| Where { $_.Enabled -eq $True } |
Format-Table -Property Name,
DisplayName,
DisplayGroup,
#{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
#{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
#{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
#{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
Enabled,
Profile,
Direction,
Action
The output is shown below
Use the Select-Object Cmdlet to Display all Properties
This will Display only the First one so you dont get flooded with text, feel free to delete the "-First 1" as needed
Get-NetFirewallRule | select -First 1 -Property *
However investigating that it does not seem like there is Information about the port, looking further into it - you would probably need to use Get-NetFirewallPortFilter and match them up by instanceid. If you need help with that I'll need a little more Information on what you are trying to accomplish.
If you use only the firewall cmdlets to get a list of object that include ports, programs etc., it's not an easy task, and it's very slow! Why not try the old school way, the netsh advfirewall firewall command suite. Below is my trying to get a list of objects that include all rule information.
$output = (netsh advfirewall firewall show rule name=all verbose | Out-String).Trim() -split '\r?\n\s*\r?\n'
$propertyNames = [System.Collections.Generic.List[string]]::new()
$objects = #( $(foreach($section in $output ) {
$obj = #{}
foreach( $line in ($section -split '\r?\n') ) {
if( $line -match '^\-+$' ) { continue }
$name, $value = $line -split ':\s*', 2
$name = $name -replace " ", ""
$obj.$name = $value
if($propertyNames -notcontains $name) {
$propertyNames.Add( $name )
}
}
$obj
}) | % {
foreach( $prop in $propertyNames ) {
if( $_.Keys -notcontains $prop ) {
$_.$prop = $null
}
}
[PSCustomObject]$_
})

Resolve-DNSName for Windows 2008

I have a script working for Windows 2012 (PowerShell v4) but it has to work also for Windows 2008 (PowerShell v2), what is the equivalent of the cmdlet "Resolve-DNSName" for Windows 2008?
Resolve-DnsName -Name client01 -Server server01
I know it exists the same for nslookup and this is what I would like as a cmdlet (one-liner, with no input required from my part)
nslookup
server server01
client01
The following works for DNS resolution but is missing the -server parameter :
[Net.DNS]::GetHostEntry("MachineName")
Thanks
Unfortunately there isn't a way to do this natively in powershell prior to Version 4 in Windows 8.1 or Server 2012. There are .NET methods however:
https://stackoverflow.com/a/8227917/4292988
The simplest solution in powershell is to call nslookup, and cleanup the output
&nslookup.exe client01 server01
I removed select-string from the original sample, it left less to work with
The function you posted following mine doesnt work very well, and will never work in PowershellV2, [PSCustomObject] wasn't supported until v3. Furthermore if you send a dns query that would normally return a single address, it returns nothing. For queries with aliases, it returns the aliases where the ipaddress should be. Test Resolve-DnsName2008 -name www.stackoverflow.com -server 8.8.8.8.
The Following is a function that should do what your asking, at least for ipv4addresses:
function Resolve-DnsName2008
{
Param
(
[Parameter(Mandatory=$true)]
[string]$Name,
[string]$Server = '127.0.0.1'
)
Try
{
$nslookup = &nslookup.exe $Name $Server
$regexipv4 = "^(?:(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)$"
$name = #($nslookup | Where-Object { ( $_ -match "^(?:Name:*)") }).replace('Name:','').trim()
$deladdresstext = $nslookup -replace "^(?:^Address:|^Addresses:)",""
$Addresses = $deladdresstext.trim() | Where-Object { ( $_ -match "$regexipv4" ) }
$total = $Addresses.count
$AddressList = #()
for($i=1;$i -lt $total;$i++)
{
$AddressList += $Addresses[$i].trim()
}
$AddressList | %{
new-object -typename psobject -Property #{
Name = $name
IPAddress = $_
}
}
}
catch
{ }
}
I use this code to input FQDNs one per line and output respective IPs.
$Server = Get-Content servers.txt
$OutArray = #()
$output = foreach ($Server in $Server) {
$IP = [System.Net.Dns]::GetHostAddresses($Server)
$OutArray += $Server + " " + $IP.IPAddressToString
}
$OutArray | Out-File IPs.txt
The problem is that if I use :
&nslookup.exe client01 server01 | select-string "Name", "Addresses"
It will only display the first record, in my case I had 5 records found and only one displayed.
The solution I found works very well :
function Resolve-DNSName2008
{
Param
(
[string]$Name,
[string]$Server
)
$nslookup = &nslookup.exe $Name $Server
$name = [string]($nslookup | Select-String "Name")
$nameClean = ([regex]::match($name,'(?<=:)(.*\n?)').value).Trim()
$addresses = (([regex]::match($nslookup,'(?<=Addresses:)(.*\n?)').value).Trim()).Split(' ')
$addressesClean = $addresses.Split('',[System.StringSplitOptions]::RemoveEmptyEntries) | Sort-Object
$addressesClean | %{
[PSCustomObject]#{
Name = $nameClean
IPAddress = $_
}
}
}
Usage:
Resolve-DNSName2008 -Name server.domain.com -Server 10.0.0.0
Output:
Name IPAddress
---- ---------
server.domain.com 10.0.0.1
server.domain.com 10.0.0.2
server.domain.com 10.0.0.3
server.domain.com 10.0.0.4
server.domain.com 10.0.0.5

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation

Where-Object clause fails when run as a workflow in PowerShell

I'm trying to extract static routes from all AD computer using the Get-NetRoute cmdlet. It works well when run outside a workflow, but as soon as I try to run the same code within a workflow it fails with the following exception:
System.Management.Automation.ParameterBindingException: Parameter set cannot be resolved using the specified named parameters.
I could trace this back to the Where-Object "?" filter. The "? {}" section in commented line of code makes it fail. Without that filter it works perfectly.
Code is here:
cd C:\Users\Public\Documents
workflow Get-StaticRoutes {
# Change the error action to 'stop' to get try/catch working
# Get-NetRoute -Protocol NetMgmt -AddressFamily IPv4 | ? { $_.DestinationPrefix -ne "0.0.0.0/0" } | % {
Get-NetRoute -Protocol NetMgmt -AddressFamily IPv4 | % {
[PSCustomObject] #{
ComputerName = $env:COMPUTERNAME
InterfaceName = $_.InterfaceAlias
InterfaceIndex = $_.InterfaceIndex
DestinationPrefix = $_.DestinationPrefix
NextHop = $_.NextHop
Comment = ""
}
}
}
# Get all computers from AD
$computers = Get-ADComputer -Filter * | % { $_.Name }
# Retrieve IP config
Get-StaticRoutes -PSComputerName $computers | Export-Csv ".\StaticRoutes.csv" -NoTypeInformation
I could filter after the workflow to fix this problem, but I would like to understand what I do wrong as this ParameterBindingException is rather obscure.
Thanks,
Olivier.
To run commands or expressions in a workflow that are valid in Windows PowerShell, but not valid in workflows, run the commands in an inlineScript activity. You can use also an inlineScript activity to run Windows PowerShell scripts (.ps1 files) in a workflow.
Try this ( not tested )
workflow Get-StaticRoutes
{
inlinescript { Get-NetRoute -Protocol NetMgmt -AddressFamily IPv4 |
? { $_.DestinationPrefix -ne "0.0.0.0/0" } |
% {
[PSCustomObject] #{
ComputerName = $env:COMPUTERNAME
InterfaceName = $_.InterfaceAlias
InterfaceIndex = $_.InterfaceIndex
DestinationPrefix = $_.DestinationPrefix
NextHop = $_.NextHop
Comment = ""
}
}
}
}
side note:
$env:computername outside the inlinescipt activity resolve to local
computer name. Inside the inlinescipt activity resolve to the remote
computer name.
the object returned by a workflow is a serialized object and not the object created in the inlinescript activity or workflow process ( this means, in simple terms, that you can't have object method but only the properties of the object )
Remember that with Workflows you need to use named parameters.
When you run something like this:
$a = $b | ?{$_.Name -eq "John"}
You're really running this:
$a = $b | where-object -FilterScript {$_.Name -eq "John"}
The latter works fine in a workflow without using those pesky inlinescripts.