Password policies are best😀 Sometimes they lead to account logouts when someone forgot to logout of session somewhere on the network though. それは、四半期に一度、報告のために使用する TS セッションかもしれませんし、サーバーに RDP したら、他の 2 人の管理者がログオフするのを忘れてロックされているのを発見したときの感覚を知っているかもしれませんね。 (とにかく、私はネットワーク上のどこかにあるユーザーセッションを探さなければなりませんでした。 最悪なのは、自分のパスワードが期限切れになったときです。 自分のアカウントがロックされてしまうのは嫌ですね。 そこで、パスワードを変更する前に、すべてのサーバーをチェックすることにした。 これを行うには複数の方法がありますが、私はもちろんPowerShellのルートを取ることが多いです。
Research
私が最初に使用した方法は TechNet gallery
のものです。 これは、サービスとして実行されているものまですべて見つけるのでクールですが、最も効率的な方法だとは思えません。
Google で調べてみると、自分のマシンに誰がログオンしているかをチェックするクリエイティブな方法がたくさん見つかりました。
これは素晴らしいです。出力は少し異なりますが、Get-CimInstance でも動作するようです。
learn-powershell.net/…/Quick-hit-find-currently-logged-on-users/ はもう少し古いアプローチで、少し荒っぽく、テンプレート ベースの解析で遊ばざるを得ないので、私はこれが好きです。
どの方法がより速いのかよく分からないので、モジュールで 3 つすべてを実装してテストしてみてはいかがでしょうか。
Pseudo code:Get-ActiveUser -ComputerName -Method Wanted output:Username ComputerName-------- ------------TestUser1 Svr3TestUser3 Svr3DonaldDuck Client2
GitHub リポジトリを設定するのに必要なすべての情報が揃いました。
github.com/mrhvid/Get-ActiveUser
コード
まず、私が興味を持っているパラメーターは ComputerName と Method です。
Param ( # Computer name, IP, Hostname ] $ComputerName, # Choose method, WMI, CIM or Query $Method )
私はすでに3種類の Method を考えているので、3種類の可能性を ValidateSet と設定しました。
Process { switch ($Method) { 'WMI' { } 'CIM' { } 'Query' { } } }
関数の処理部分では、パラメータで許可した 3 つの異なるメソッドのスイッチを使用するだけです。
WMI
My old solution is simple and works fine.
$WMI = Get-WmiObject -Class Win32_Process -ComputerName $ComputerName -ErrorAction Stop$ProcessUsers = $WMI.getowner().user | Select-Object -Unique
But now that I found Win32_LoggedOnUser it to do it this way is wrong.このようにすると、このソリューションはうまくいきます。
これはすべて正しいデータですが、文字列形式のようなので、少し操作する必要がありそうです。 これはいくらでもできる。
function Get-MyLoggedOnUsers { param($Computer) Get-WmiObject Win32_LoggedOnUser -ComputerName $Computer | Select Antecedent -Unique | %{"{0}{1}" -f $_.Antecedent.ToString().Split('"'), $_.Antecedent.ToString().Split('"')} }
Peter の前述のワンライナーは、私にはあまり読みやすいとは思えなかったので、ワンライナーとしてはいいのですが、できればもう少し読みやすくしてほしいです。
$WMI = (Get-WmiObject Win32_LoggedOnUser).Antecedent$ActiveUsers = @()foreach($User in $WMI) { $StartOfUsername = $User.LastIndexOf('=') + 2 $EndOfUsername = $User.Length - $User.LastIndexOf('=') -3 $ActiveUsers += $User.Substring($StartOfUsername,$EndOfUsername)}
This seams right 🙂 出力を $ActiveUsers 変数に保存して、CIM と Query で同じことをします
CIM
Lets try with CIM.SIM.SIM.Lots。
この方がずっと構造化されているように見えます。
CIMは結局わかりやすいワンライナーになりました😀
$ActiveUsers = (Get-CimInstance Win32_LoggedOnUser -ComputerName $ComputerName).antecedent.name | Select-Object -Unique
Query
Using the good ol’ Query.を使ってみました。exe を使用すると、以前説明したテンプレートベースの解析が非常に便利であることがわかりました。
$Template = @' USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME>{USER*:jonas} console 1 Active 1+00:27 24-08-2015 22:22 {USER*:test} 2 Disc 1+00:27 25-08-2015 08:26'@$Query = query.exe user$ActiveUsers = $Query | ConvertFrom-String -TemplateContent $Template | Select-Object -ExpandProperty User
Output
あとは、ユーザーをうまくフォーマットして出力する必要があるだけです。 ComputerNameとUserNameできれいなオブジェクトが欲しいです。
# Create nice output format$UsersComputersToOutput = @()foreach($User in $ActiveUsers) { $UsersComputersToOutput += New-Object psobject -Property @{ ComputerName=$ComputerName; UserName=$User } }}# output data$UsersComputersToOutput
Testing
さて、問題が発生しました。 私は自由に使える多くのテスト サーバーを持っていないので、これをテストすることはできません。 私のテストはすべて、私自身の Windows 10 ボックスに対して行われました。 クエリはローカルで実行したほうがずっと速いようですが、WMI/CIM はどのサービスが実行されているかをより完全に表示することができます。
出力から削除するとよいかもしれない標準サービス アカウントの束を実行させています。 また、これが有用であるためには、多くのマシンに対して実行する必要があります。
Get-ActiveUser と Start-Multithread の組み合わせは、先週の投稿から意図したように機能しているようです。
Start-Multithread -Script { param($C) Get-ActiveUser -ComputerName $C -Method Query } -ComputerName ::1,Localhost | Out-GridView
上記を Out-GridView にパイプすることは、本当に有用なことを達成する個人的に好きな方法です。 また、ネットワーク上のルージュ ユーザーをチェックする簡単な方法でもあります。
公開とフィードバック
コードは PowerShellGallery で公開されています。 これが実世界で動作するかどうか知りたいです🙂
# To install Get-ActiveUserInstall-Module Get-ActiveUser#To install Start-MultithreadInstall-Module Start-Multithread
これは WMF 5 + をインストールし、Windows 10 で箱から出しているときに動作するはずです。