更简单的方法来解析和查询用户'在PowerShell中

时间:2016-08-29 17:48:36

标签: powershell parsing scripting server powershell-v3.0

我目前在PowerShell中有以下查询:

query user /server:$server

返回输出:

USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME  
svc_chthost                               2  Disc         1:05  8/16/2016 12:01 PM  
myusername                rdp-tcp         3  Active          .  8/29/2016 11:29 AM

目前,我使用@(query user /server:$server).Count - 1作为值来表示登录的用户数量(我知道这不是很好)。但是现在我想获取USERNAMEIDLOGON TIME等信息,以便在我的脚本的其他部分中使用。

我的问题是围绕一种更简单的方法来解析上面的信息,或者更好地解决我的问题:统计和收集与登录用户相关的信息。

我发现其他似乎更好的解决方案,但我确信必须有一种更简单的方法来完成这项任务:

$ComputerName | Foreach-object { 
$Computer = $_ 
try 
    {
        $processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer -EA "Stop") 
            if ($processinfo) 
            {     
                $processinfo | Foreach-Object {$_.GetOwner().User} |  
                Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} | 
                Sort-Object -Unique | 
                ForEach-Object { New-Object psobject -Property @{Computer=$Computer;LoggedOn=$_} } |  
                Select-Object Computer,LoggedOn 
            }#If 
    } 
catch 
    { 

    }

8 个答案:

答案 0 :(得分:2)

用于收集信息。

基于https://ss64.com/nt/query-user.html

$result  = &quser
$result -replace '\s{2,}', ',' | ConvertFrom-Csv

答案 1 :(得分:1)

评论中有很多引用,并且仍然可以获得更多这个问题的答案,因为它应该有一个更简单的解决方案!

    foreach ($s in $servers) #For Each Server
{
    foreach($ServerLine in @(query user /server:$s) -split "\n") #Each Server Line
    {
        #USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME

        $Parsed_Server = $ServerLine -split '\s+'

        $Parsed_Server[1] #USERNAME
        $Parsed_Server[2] #SESSIONNAME
        $Parsed_Server[3] #ID
        $Parsed_Server[4] #STATE
        $Parsed_Server[5] #IDLE TIME
        $Parsed_Server[6] #LOGON TIME
    }
}

这个解决方案现在解决了这个问题,有点草率。

有关更多功能的更深入的解决方案,请查看原始问题的评论:)

答案 2 :(得分:0)

老问题,但似乎可行的解决方案:

(query user) -split "\n" -replace '\s\s+', ';' | convertfrom-csv -Delimiter ';'

与上面的答案一样,这会将输出分成几行,但是用分号替换了多个空格字符(\ s \ s +),然后使用分号将csv的输出转换为分隔符。

出现多个空格的原因是列标题中有空格(空闲时间,登录时间),因此只有一个空格时,它将试图将其解释为多列。从命令的输出来看,好像它们始终始终在项目之间保留至少2个空格,并且登录时间列在字段中也有空格。

答案 3 :(得分:0)

pip install somemodule

答案 4 :(得分:0)

我自己的专栏文章。我不确定ID列可以向左延伸多少。不确定结局有多宽。事实证明这很棘手。也许这样更好:Convert fixed width txt file to CSV / set-content or out-file -append?

# q.ps1
# USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
# js1111                rdp-tcp#20        136  Active          .  6/20/2020 4:26 PM
# jx111                                   175  Disc            .  6/23/2020 1:26 PM
# sm1111                rdp-tcp#126        17  Active          .  6/23/2020 1:13 PM
#
# di111111              rdp-tcp#64        189  Active         33  7/1/2020 9:50 AM
# kp111                 rdp-tcp#45        253  Active       1:07  7/1/2020 9:43 AM
#                                                                                     
#0, 1-22, 23-40, 41-45, 46-53, 54-64, 65-80/82

$q = quser 2>$null | select -skip 1
$q | foreach { 
  $result = $_ -match '.(.{22})(.{18})(.{5})(.{8})(.{11})(.{16,18})' 

  [pscustomobject] @{
    USERNAME = $matches[1].trim()
    SESSIONNAME = $matches[2].trim()
    ID = [int]$matches[3].trim()
    STATE = $matches[4].trim()
    IdleTime = $matches[5].trim()
    LogonTime = [datetime]$matches[6].trim()
  }

  if (! $matches) {$_}

}

调用命令示例。如果您正在使用鳄梨调味酱,那就很好了。

$c = get-credential
icm comp1,comp2,comp3 q.ps1 -cr $c | ft


USERNAME SESSIONNAME  ID STATE IdleTime LogonTime            PSComputerName RunspaceId
-------- -----------  -- ----- -------- ---------            -------------- ----------
js1                  136 Disc  .        6/20/2020 4:26:00 PM comp1          a8e670cd-4f31-4fd0-8cab-8aa11ee75a73
js2                  137 Disc  .        6/20/2020 4:26:00 PM comp2          a8e670cd-4f31-4fd0-8cab-8aa11ee75a74
js3                  138 Disc  .        6/20/2020 4:26:00 PM comp3          a8e670cd-4f31-4fd0-8cab-8aa11ee75a75

答案 5 :(得分:0)

已编辑:看起来有人已经创建了一个实际上运行良好的脚本:https://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnUser-Gathers-7cbe93ea

不能相信,这么多年以后,仍然没有原生的PowerShell。

我已经整理了Tyler Dickson所做的事情,并确保结果以PSCustomObject的形式返回

$Servers = @("10.x.x.x", "10.y.y.y")
$Result = @()
foreach ($Server in $Servers) {
    $Lines = @(query user /server:$s) -split "\n"

    foreach($Line in $Lines) #Each Server Line
    {
        if ($Line -match "USERNAME\s+SESSIONNAME\s+ID\s+STATE\s+IDLE TIME\s+LOGON TIME") {
            continue  # If is the header then skip to next item in array
        }

        $Parsed_Server = $Line -split '\s+'
        $Result += [PSCustomObject]@{
            SERVER = $Server
            USERNAME = $Parsed_Server[1]
            SESSIONNAME = $Parsed_Server[2]
            ID = $Parsed_Server[3]
            STATE = $Parsed_Server[4]
            IDLE_TIME = $Parsed_Server[5]
            LOGON_TIME = $Parsed_Server[6]
        }
    }
}

$Result | Format-Table

示例输出:

SERVER     USERNAME     SESSIONNAME ID STATE  IDLE_TIME LOGON_TIME
------     --------     ----------- -- -----  --------- ----------
10.x.x.x   user01       rdp-tcp#13  6  Active .         28/06/2020
10.x.x.x   user02       rdp-tcp#35  11 Active 59        29/06/2020
10.y.y.y   user03       rdp-tcp#38  12 Active .         29/06/2020
10.y.y.y   user04       rdp-tcp#43  14 Active 5         29/06/2020

答案 6 :(得分:0)

$result = (&quser) -replace '\s{2,}', ',' | ConvertFrom-Csv | Select -ExpandProperty USERNAME
$loggedinuser = $result.Trim(">")

答案 7 :(得分:-1)

我进一步添加了上述代码以正确格式化并考虑了断开连接的用户

$HaSH = @()
foreach($ServerLine in @(query user) -split "\n")  {
    $Report = "" | Select-Object UserName, Session, ID, State, IdleTime, LogonTime
    $Parsed_Server = $ServerLine -split '\s+'
    if($Parsed_Server -like "USERNAME*") {
    Continue
    }
    $Report.UserName =  $Parsed_Server[1]
    $Report.Session = $Parsed_Server[2]
    $Report.ID = $Parsed_Server[3]
    $Report.State = $Parsed_Server[4]
    $Report.IdleTime = $Parsed_Server[5]
    $Report.LogonTime = $Parsed_Server[6]+" " +$Parsed_Server[7]+" "+$Parsed_Server[8]

    if($Parsed_Server[3] -eq "Disc") {
        $Report.Session = "None"
        $Report.ID = $Parsed_Server[2]
        $Report.State = $Parsed_Server[3]
        $Report.IdleTime = $Parsed_Server[4]
        $Report.LogonTime = $Parsed_Server[5]+" " +$Parsed_Server[6]+" "+$Parsed_Server[7]
    }

    if($Parsed_Server -like ">*") {
        $Parsed_Server=$Parsed_Server.Replace(">","")
        $Report.UserName =  $Parsed_Server[0]
        $Report.Session = $Parsed_Server[1]
        $Report.ID = $Parsed_Server[2]
        $Report.State = $Parsed_Server[3]
        $Report.IdleTime = $Parsed_Server[4]
        $Report.LogonTime = $Parsed_Server[5]+" " +$Parsed_Server[6]+" "+$Parsed_Server[7]
    }
    $HaSH+=$Report
}