【问题标题】:Get list of processes same as in task manager in powershell console获取与PowerShell控制台中的任务管理器相同的进程列表
【发布时间】:2021-07-08 01:23:48
【问题描述】:

我正在尝试获取与 Windows 2008 服务器任务管理器中相同的进程列表

我什至无法从 WMI 对象中获取某些值,例如 CPU 时间、UAC 虚拟化、用户名(例如进程所有者)、用户对象、CPU 使用情况、所有内存列、句柄和线程。

这是我试图让它工作的一些代码

Clear-Host

$Processes = Get-Process
foreach ($Process in $Processes) {
$PIDN = $Process.Id
$NAMEProcess = $Process.Name
$NAME  = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).Name
$PATH  = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).Path
$CMD   = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).CommandLine

$OWNER = (Get-WmiObject win32_process | where {$_.Name -match $NAMEProcess}).getowner().user
$SESSIONID = (Get-WmiObject Win32_Process | where {$_.Name -match $NAMEProcess}).SessionId
$CPU = $Process.CPU
$WORKINGSET64 = $Process.WorkingSet64
$PEAKWORKINGSET64 = $Process.PeakWorkingSet64
$THREADS = $Process.Threads.Count
$HANDLES = $Process.Handles
$DESCRIPTION = $Process.Description

$obj = new-object psobject
$obj | add-member noteproperty "PID" ($PIDN)
$obj | add-member noteproperty "NAME" ($NAME)
$obj | add-member noteproperty "OWNER" ($OWNER)
$obj | add-member noteproperty "PATH" ($PATH)
$obj | add-member noteproperty "Command Line" ($CMD)
$obj | Add-Member noteproperty "SessionID" ($SESSIONID)
$obj | Add-Member noteproperty "CPU" ($CPU)
$obj | Add-Member noteproperty "WorkingSet64" ($WORKINGSET64)
$obj | Add-Member noteproperty "Peak Working Set64" ($PEAKWORKINGSET64)
$obj | Add-Member noteproperty "HANDLES" ($HANDLES)
$obj | Add-Member noteproperty "THREADS" ($THREADS)
$obj | Add-Member noteproperty "DESCRIPTION" ($DESCRIPTION)

write-output $obj | Format-Table
# $obj | Format-Table $PIDN, $NAME
}

也无法将其输出到正确的表中。你能帮我吗?谢谢。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    首先,您需要使用来自 Get-WMIObject (gwmi) 的单次使用的数据。

    当您使用 GWMI 进行多次调用时,您实际上是每次都拍摄另一个数据快照,并为每个属性使用不同的样本。你最终会得到一张适合立体派毕加索画作的数据表……它不会对齐或代表整个列表。一遍又一遍地重新捕获进程列表然后只从每个不同列表中获取一个属性也需要更多时间,因此花时间修改一组数据是值得的,尤其是如果您最终在编译任务数据库的大型远程操作脚本中重新调整脚本的用途。

    有多种方法可以仅以 PS 自定义对象的形式获取您想要的属性。我使用哈希表使代码简短易懂,并使代码高效—— 您已经执行了对哈希表执行的措辞,格式如下:

    $CPU = $Process.CPU
    $WORKINGSET64 = $Process.WorkingSet64
    $PEAKWORKINGSET64 = $Process.PeakWorkingSet64 
    $THREADS = $Process.Threads.Count
    $HANDLES = $Process.Handles
    $DESCRIPTION = $Process.Description
    

    所以,做吧

    $taskProps = @{
      'SID'=$task.SessionId
      'Name'=$task.ProcessName
      'PID'=$task.ProcessId
      # add more properties here.
    }
    

    而不是创建一个空白的自定义对象,然后多次“写入”它

    $obj = new-object psobject
    $obj | add-member noteproperty "PID" ($PIDN)
    $obj | add-member noteproperty "NAME" ($NAME)
    $obj | add-member noteproperty "OWNER" ($OWNER)
    $obj | add-member noteproperty "PATH" ($PATH)
    $obj | add-member noteproperty "Command Line" ($CMD)
    $obj | Add-Member noteproperty "SessionID" ($SESSIONID)
    $obj | Add-Member noteproperty "CPU" ($CPU)
    $obj | Add-Member noteproperty "WorkingSet64" ($WORKINGSET64)
    $obj | Add-Member noteproperty "Peak Working Set64" ($PEAKWORKINGSET64)
    $obj | Add-Member noteproperty "HANDLES" ($HANDLES)
    $obj | Add-Member noteproperty "THREADS" ($THREADS)
    $obj | Add-Member noteproperty "DESCRIPTION" ($DESCRIPTION)
    

    可以打包属性hashtable,一次性创建,自定义对象在最后:

    $taskObject = New-Object -TypeName PSObject -Property $taskProps
    

    然后将其存储在一个数组列表中

    $taskList += $taskObject
    

    你可以在这里看到我的例子:

    # Generates a collection of "System.Management.ManagementObject#root\cimv2\Win32_Process"
    # Only do this once. Every time gwmi is used, it makes another RPC call if used remotely.
    # If you do multiple GWMIs you'll be working with differing data samples.
    $taskSnapshot = Get-WMIObject -ComputerName [machine name] -Class Win32_Process
    
    # Initialize, nullify, and declare your list as an empty ArrayList.
    $taskList = @()
    
    # Begin formatting in prep of Format-Table or similar usage
    # This is where you'd define each property you want to see, manipulation, etc.
    foreach ($task in $taskSnapshot){
    
    # Create the hash table which will temporarily store all information for each task naming/assigning only
    # properties you want to display.
        $taskProps = @{
            'SID'=$task.SessionId
            'Name'=$task.ProcessName
            'PID'=$task.ProcessId
                 # additional properties here.
        }
    
    # "Packages" the new custom object in a variable that stores the object
        $taskObject = New-Object -TypeName PSObject -Property $taskProps
    
    # append (addition) operation on formerly defined arraylist to store
    # the packaged object to an arraylist.
        $taskList += $taskObject
    }
    
    # Displays the list of task "objects" in a table, other formatting options are available online.
    $taskList | Format-Table -AutoSize
    

    使用格式命令更改输出视图:

    https://technet.microsoft.com/en-us/library/dd347677.aspx

    Windows PowerShell:自定义对象的多种方式:

    https://technet.microsoft.com/en-us/magazine/hh750381.aspx

    我还建议检查 Out-GridView,因为它会创建一个数据的 GUI 表,您可以调整其大小并轻松点击。

    重要的部分是使用一次 GWMI。更好的做法是在单个变量中捕获原始信息,然后在 foreach 语句中对数据集执行 Select-String/where/if/manipulation 和格式化操作。

    这是示例的干净副本,带有我的选择别名。

    $taskSnapshot = gwmi -cn localhost -class win32_process
    $taskList = @()
    foreach ($task in $taskSnapshot){
        $taskProps = @{
            'SID'=$task.SessionId
            'Name'=$task.ProcessName
            'PID'=$task.ProcessId
        }
        $taskObject = New-Object -TypeName PSObject -Property $taskProps
        $taskList += $taskObject
    }
    
    $taskList | Out-GridView
    

    有人提到的另一件事是最小/最大工作集属性...

    你可以通过做查看Win32_Process的所有属性

    Get-WMIObject -Class Win32_Process | Get-Member
    

    gwmi -cl win32_process | gm
    

    【讨论】:

    • 亲爱的 Chris,非常感谢您的详细回答,这对我帮助很大
    【解决方案2】:

    您查看过性能计数器吗?

    Get-Counter "\Process(*)\Working Set - Private"
    Get-Counter "\Process(*)\Handle Count"
    

    有关 Get-Counter 使用的更多文档

    get-help get-counter -Full
    

    或转到:https://technet.microsoft.com/en-us/library/hh849685.aspx

    【讨论】:

    • 亲爱的 Nickolai,非常感谢 Get-Counter 的提示,它对我很有帮助,我使用了那里的一些数据
    【解决方案3】:

    以 Chris Kuperstein 的回答为基础:

    我不喜欢 PowerShell 根据 HashTable 中 Keys 集合的默认排序重新排列我的属性;我把我的财产放在一个不同的顺序是有原因的。为了解决这个问题,您可以使用属性集。值得注意的是,您绝对可以使用 Select-Object 来实现这一点。

    $taskObject = New-Object -TypeName PSObject -Property $taskProps
    
    $taskObject.PSObject.TypeNames.Insert(0, "xTask")
    $taskObject | Add-Member -MemberType ScriptMethod -Name "ToString" -Force -Value {
        Write-Output "Name: $($this.Name) [$($this.PID)] - CPU: $($this.CPU)"
    }
    $defaultDisplaySet = @('SID', 'PID', 'Name', 'CPU', 'Threads', 'Handles', 'WorkingSet64', 'Owner', 'Description', 'Path')
    $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet("DefaultDisplayPropertySet",[string[]]$defaultDisplaySet)
    $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
    $taskObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers
    

    【讨论】:

      猜你喜欢
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-08
      • 1970-01-01
      相关资源
      最近更新 更多