我正在尝试获取与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
}
也无法在正确的表格中输出。你能帮帮我吗?谢谢。
答案 0 :(得分:3)
首先,您需要使用一次使用Get-WMIObject(gwmi)的数据。
当您使用GWMI进行多次调用时,您每次都会有效地获取另一个数据快照,并为每个属性使用不同的样本。你最终会得到一张适合立体派毕加索画作的数据表...它不会对齐或代表整个列表。还需要花费更多的时间来重新获取进程列表,然后从每个不同的列表中仅获取一个属性,因此值得花时间修改单个数据集,尤其是如果你最终在一个编译任务数据库的大规模远程操作脚本中重新利用你的脚本。
有多种方法可以仅以PS自定义对象的形式获取所需的属性。我使用哈希表来使代码简单易用,并使代码更有效 - 您已经执行了为哈希表执行的verbage,格式为:
$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)
您可以打包属性哈希表并一次创建自定义对象:
$taskObject = New-Object -TypeName PSObject -Property $taskProps
然后将其存储在带
的arraylist中$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
使用格式命令更改输出视图:
Windows PowerShell:自定义对象的多种方式:
我还建议检查Out-GridView,因为它会创建一个数据的GUI表,您可以调整大小并轻松点击。
重要的是使用GWMI一次。最好在单个变量中捕获原始信息,然后在foreach语句中对数据集执行Select-String / where / if / manipulation和format操作。
这是示例的干净副本,带有我的选择别名。
$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
答案 1 :(得分: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
答案 2 :(得分:0)
以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
答案 3 :(得分:0)
答案很好,但它们提供的信息与任务管理器不同。例如,您无法获取流程下的子流程名称。