I wanted a quick way to get a list of user sessions on our VDI servers.
My exact goal was to get a list of users that were a day away from being forced off the system and sending them an email.
TLDR: I ended up making this into a module: QuserObject.
Walkthrough
Anyway, down to business.
We can use Quser to get the information.
Keep in mind that you can easily target a different computer: quser /SERVER:servername
.
1 2 3 4 5 6 |
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME admin.xxxxxxxx 2 Disc 15+15:12 7/20/2017 1:19 PM admin.xxxxx rdp-tcp#54 3 Active 1:39 7/21/2017 5:35 AM xxxxxxxx 4 Disc 6+04:10 7/21/2017 9:25 AM >vertigoray console 5 Active . 8/9/2017 4:40 PM |
This is good information, but it would be so much better if it was an object.
Since it’s already a nice grid, let’s treat it as a CSV:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<span class=""nf"">PS</span> <span class=""err"">></span> <span class=""p"">(</span><span class=""nf"">quser</span><span class=""p"">)</span> <span class=""o"">-replace</span> <span class=""s1"">'s{2,}'</span><span class=""p"">,</span> <span class=""s1"">','</span> <span class=""o"">|</span> <span class=""nf"">ConvertFrom-Csv</span> <span class=""nf"">USERNAME</span> <span class=""p"">:</span> <span class=""nx"">admin.xxxxxxxx</span> <span class=""nf"">SESSIONNAME</span> <span class=""p"">:</span> <span class=""nx"">2</span> <span class=""nf"">ID</span> <span class=""p"">:</span> <span class=""nx"">Disc</span> <span class=""nf"">STATE</span> <span class=""p"">:</span> <span class=""nx"">15</span><span class=""o"">+</span><span class=""nx"">15:12</span> <span class=""nf"">IDLE</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nx"">7/20/2017</span> <span class=""nx"">1:19</span> <span class=""nx"">PM</span> <span class=""nf"">LOGON</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nf"">USERNAME</span> <span class=""p"">:</span> <span class=""nx"">admin.xxxxx</span> <span class=""nf"">SESSIONNAME</span> <span class=""p"">:</span> <span class=""nx"">rdp-tcp</span><span class=""c"">#54</span> <span class=""nf"">ID</span> <span class=""p"">:</span> <span class=""nx"">3</span> <span class=""nf"">STATE</span> <span class=""p"">:</span> <span class=""nx"">Active</span> <span class=""nf"">IDLE</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nx"">1:39</span> <span class=""nf"">LOGON</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nx"">7/21/2017</span> <span class=""nx"">5:35</span> <span class=""nx"">AM</span> <span class=""nf"">USERNAME</span> <span class=""p"">:</span> <span class=""nx"">xxxxxxxx</span> <span class=""nf"">SESSIONNAME</span> <span class=""p"">:</span> <span class=""nx"">4</span> <span class=""nf"">ID</span> <span class=""p"">:</span> <span class=""nx"">Disc</span> <span class=""nf"">STATE</span> <span class=""p"">:</span> <span class=""nx"">6</span><span class=""o"">+</span><span class=""nx"">04:10</span> <span class=""nf"">IDLE</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nx"">7/21/2017</span> <span class=""nx"">9:25</span> <span class=""nx"">AM</span> <span class=""nf"">LOGON</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nf"">USERNAME</span> <span class=""p"">:</span> <span class=""err"">></span><span class=""nx"">vertigoray</span> <span class=""nf"">SESSIONNAME</span> <span class=""p"">:</span> <span class=""nx"">console</span> <span class=""nf"">ID</span> <span class=""p"">:</span> <span class=""nx"">5</span> <span class=""nf"">STATE</span> <span class=""p"">:</span> <span class=""nx"">Active</span> <span class=""nf"">IDLE</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""o"">.</span> <span class=""nf"">LOGON</span> <span class=""nx"">TIME</span> <span class=""p"">:</span> <span class=""nx"">8/9/2017</span> <span class=""nx"">4:40</span> <span class=""nx"">PM</span> |
Beautifully simple, right?!
I originally posted this on stackoverflow because I just wanted a list of users.
Now, let’s get rid of that >
on my entry, and fix those disconnected session columns.
This part gets a little more complicated.
1 2 3 4 5 6 7 8 |
<span class=""p"">(((</span><span class=""nf"">quser</span><span class=""p"">)</span> <span class=""o"">-replace</span> <span class=""s1"">'^>'</span><span class=""p"">,</span> <span class=""s1"">''</span><span class=""p"">)</span> <span class=""o"">-replace</span> <span class=""s1"">'s{2,}'</span><span class=""p"">,</span> <span class=""s1"">','</span><span class=""p"">)</span><span class=""o"">.</span><span class=""nf"">Trim</span><span class=""p"">()</span> <span class=""o"">|</span> <span class=""nf"">ForEach-Object</span> <span class=""p"">{</span> <span class=""kr"">if</span> <span class=""p"">(</span><span class=""bp"">$_</span><span class=""o"">.</span><span class=""nf"">Split</span><span class=""p"">(</span><span class=""s1"">','</span><span class=""p"">)</span><span class=""o"">.</span><span class=""nf"">Count</span> <span class=""o"">-eq</span> <span class=""mi"">5</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nf"">Write-Output</span> <span class=""p"">(</span><span class=""bp"">$_</span> <span class=""o"">-replace</span> <span class=""s1"">'(^[^,]+)'</span><span class=""p"">,</span> <span class=""s1"">'$1,'</span><span class=""p"">)</span> <span class=""p"">}</span> <span class=""kr"">else</span> <span class=""p"">{</span> <span class=""nf"">Write-Output</span> <span class=""bp"">$_</span> <span class=""p"">}</span> <span class=""p"">}</span> <span class=""o"">|</span> <span class=""nf"">ConvertFrom-Csv</span> |
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
USERNAME : admin.xxxxxxxx SESSIONNAME : ID : 2 STATE : Disc IDLE TIME : 15+15:12 LOGON TIME : 7/20/2017 1:19 PM USERNAME : admin.xxxxx SESSIONNAME : rdp-tcp#54 ID : 3 STATE : Active IDLE TIME : 1:39 LOGON TIME : 7/21/2017 5:35 AM USERNAME : xxxxxxxx SESSIONNAME : ID : 4 STATE : Disc IDLE TIME : 6+04:10 LOGON TIME : 7/21/2017 9:25 AM USERNAME : vertigoray SESSIONNAME : console ID : 5 STATE : Active IDLE TIME : . LOGON TIME : 8/9/2017 4:40 PM |
Last things to do:
- Change the idle
.
to a$null
. - Type cast everything appropriately.
- Change the property names to PascalCase.
Here’s the code for that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<span class=""nv"">$</span><span class=""nn"">script</span><span class=""p"">:</span><span class=""nv"">headerRowProcessed</span> <span class=""o"">=</span> <span class=""bp"">$false</span> <span class=""p"">(((</span><span class=""nf"">quser</span><span class=""p"">)</span> <span class=""o"">-replace</span> <span class=""s1"">'^>'</span><span class=""p"">,</span> <span class=""s1"">''</span><span class=""p"">)</span> <span class=""o"">-replace</span> <span class=""s1"">'s{2,}'</span><span class=""p"">,</span> <span class=""s1"">','</span><span class=""p"">)</span><span class=""o"">.</span><span class=""nf"">Trim</span><span class=""p"">()</span> <span class=""o"">|</span> <span class=""nf"">ForEach-Object</span> <span class=""p"">{</span> <span class=""kr"">if</span> <span class=""p"">(</span><span class=""bp"">$_</span><span class=""o"">.</span><span class=""nf"">Split</span><span class=""p"">(</span><span class=""s1"">','</span><span class=""p"">)</span><span class=""o"">.</span><span class=""nf"">Count</span> <span class=""o"">-eq</span> <span class=""mi"">5</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nf"">Write-Output</span> <span class=""p"">(</span><span class=""bp"">$_</span> <span class=""o"">-replace</span> <span class=""s1"">'(^[^,]+)'</span><span class=""p"">,</span> <span class=""s1"">'$1,'</span><span class=""p"">)</span> <span class=""p"">}</span> <span class=""kr"">else</span> <span class=""p"">{</span> <span class=""nf"">Write-Output</span> <span class=""bp"">$_</span> <span class=""p"">}</span> <span class=""p"">}</span> <span class=""o"">|</span> <span class=""nf"">ForEach-Object</span> <span class=""p"">{</span> <span class=""nv"">$rowParts</span> <span class=""o"">=</span> <span class=""bp"">$_</span><span class=""o"">.</span><span class=""nf"">Split</span><span class=""p"">(</span><span class=""s1"">','</span><span class=""p"">)</span> <span class=""kr"">if</span> <span class=""p"">(</span><span class=""o"">-not</span> <span class=""nv"">$</span><span class=""nn"">script</span><span class=""p"">:</span><span class=""nv"">headerRowProcessed</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""p"">[</span><span class=""no"">System.Collections.</span><span class=""kt"">ArrayList</span><span class=""p"">]</span> <span class=""nv"">$parts</span> <span class=""o"">=</span> <span class=""p"">@()</span> <span class=""kr"">foreach</span> <span class=""p"">(</span><span class=""nv"">$part</span> <span class=""kr"">in</span> <span class=""nv"">$rowParts</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nv"">$parts</span><span class=""o"">.</span><span class=""nf"">Add</span><span class=""p"">((</span><span class=""nf"">Get-Culture</span><span class=""p"">)</span><span class=""o"">.</span><span class=""nf"">TextInfo</span><span class=""o"">.</span><span class=""nf"">ToTitleCase</span><span class=""p"">(</span><span class=""nv"">$part</span><span class=""o"">.</span><span class=""nf"">ToLower</span><span class=""p"">())</span><span class=""o"">.</span><span class=""nf"">Replace</span><span class=""p"">(</span><span class=""s1"">' '</span><span class=""p"">,</span> <span class=""s1"">''</span><span class=""p"">))</span> <span class=""o"">|</span> <span class=""nf"">Out-Null</span> <span class=""p"">}</span> <span class=""nf"">Write-Output</span> <span class=""p"">(</span><span class=""nv"">$parts</span> <span class=""o"">-join</span> <span class=""s1"">','</span><span class=""p"">)</span> <span class=""nv"">$</span><span class=""nn"">script</span><span class=""p"">:</span><span class=""nv"">headerRowProcessed</span> <span class=""o"">=</span> <span class=""bp"">$true</span> <span class=""p"">}</span> <span class=""kr"">else</span> <span class=""p"">{</span> <span class=""p"">[</span><span class=""kt"">int</span><span class=""p"">]</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">2</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">2</span><span class=""p"">]</span> <span class=""kr"">if</span> <span class=""p"">(</span><span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">3</span><span class=""p"">]</span> <span class=""o"">-eq</span> <span class=""s1"">'Disc'</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">3</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""s1"">'Disconnected'</span> <span class=""p"">}</span> <span class=""kr"">if</span> <span class=""p"">(</span><span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">4</span><span class=""p"">]</span> <span class=""o"">-eq</span> <span class=""s1"">'.'</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">4</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""bp"">$null</span> <span class=""p"">}</span> <span class=""kr"">else</span> <span class=""p"">{</span> <span class=""nv"">$parts</span> <span class=""o"">=</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">4</span><span class=""p"">]</span><span class=""o"">.</span><span class=""nf"">Split</span><span class=""p"">(</span><span class=""s1"">'+:'</span><span class=""p"">)</span> <span class=""nv"">$now</span> <span class=""o"">=</span> <span class=""nf"">Get-Date</span> <span class=""nx"">if</span> <span class=""p"">(</span><span class=""nv"">$parts</span><span class=""o"">.</span><span class=""nf"">Count</span> <span class=""o"">-eq</span> <span class=""mi"">3</span><span class=""p"">)</span> <span class=""p"">{</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">4</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""nv"">$now</span><span class=""o"">.</span><span class=""nf"">AddDays</span><span class=""p"">(</span><span class=""nt"">-1</span> <span class=""o"">*</span> <span class=""nv"">$parts</span><span class=""p"">[</span><span class=""mi"">0</span><span class=""p"">])</span><span class=""o"">.</span><span class=""nf"">AddMinutes</span><span class=""p"">(</span><span class=""nt"">-1</span> <span class=""o"">*</span> <span class=""nv"">$parts</span><span class=""p"">[</span><span class=""mi"">1</span><span class=""p"">])</span><span class=""o"">.</span><span class=""nf"">AddSeconds</span><span class=""p"">(</span><span class=""nt"">-1</span> <span class=""o"">*</span> <span class=""nv"">$parts</span><span class=""p"">[</span><span class=""mi"">2</span><span class=""p"">])</span> <span class=""p"">}</span> <span class=""kr"">else</span> <span class=""p"">{</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">4</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""nv"">$now</span><span class=""o"">.</span><span class=""nf"">AddMinutes</span><span class=""p"">(</span><span class=""nt"">-1</span> <span class=""o"">*</span> <span class=""nv"">$parts</span><span class=""p"">[</span><span class=""mi"">0</span><span class=""p"">])</span><span class=""o"">.</span><span class=""nf"">AddSeconds</span><span class=""p"">(</span><span class=""nt"">-1</span> <span class=""o"">*</span> <span class=""nv"">$parts</span><span class=""p"">[</span><span class=""mi"">1</span><span class=""p"">])</span> <span class=""p"">}</span> <span class=""p"">}</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">5</span><span class=""p"">]</span> <span class=""o"">=</span> <span class=""nf"">Get-Date</span> <span class=""nv"">$rowParts</span><span class=""p"">[</span><span class=""mi"">5</span><span class=""p"">]</span> <span class=""nf"">Write-Output</span> <span class=""p"">(</span><span class=""nv"">$rowParts</span> <span class=""o"">-join</span> <span class=""s1"">','</span><span class=""p"">)</span> <span class=""p"">}</span> <span class=""p"">}</span> <span class=""o"">|</span> <span class=""nf"">ConvertFrom-Csv</span> |
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Username : admin.xxxxxxxx Sessionname : Id : 2 State : Disconnected IdleTime : 07/25/2017 16:24:48 LogonTime : 07/20/2017 13:19:00 Username : admin.xxxxx Sessionname : rdp-tcp#54 Id : 3 State : Active IdleTime : 08/09/2017 16:38:21 LogonTime : 07/21/2017 05:35:00 Username : xxxxxxxx Sessionname : Id : 4 State : Disconnected IdleTime : 08/03/2017 16:35:50 LogonTime : 07/21/2017 09:25:00 Username : vertigoray Sessionname : console Id : 5 State : Active IdleTime : LogonTime : 08/09/2017 16:40:00 |
Conclusion
I bit more complex, but still beautiful, right?I’ll have to turn that into a module for ease of use.
I ended up making this into a module: QuserObject.