Click here to Skip to main content
15,887,477 members
Articles / Programming Languages / F#
Tip/Trick

Parse quser.exe Results with Regex

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
5 Jan 2017CPOL1 min read 18.7K   4  
Parse quser.exe Results in Regex in any .NET language

Introduction

This is a (Unix LR) Regular Expression to parse results from quser.exe, in any .NET language (including C#, F# and VB.NET).

(?m)^\s?(?<username>[\w\/.\/_\-]{2,64})\s\s+(?<sessionname>\w?.{0,22})\s\s+(?<sessionid>\d{1,5})\s\s+(?<state>.{0,12})\s\s+(?<idletime>.{0,20})\s\s+(?<logontime>.{0,32})$

Background

A recent project required the ability to remotely disconnect users (using logoff.exe, which requires a remote SessionID, which you can get from quser.exe). At the time of writing, the only other quser parser I've found is written for Powershell, and I wanted to use it inside of a .NET\WPF application without having to reference Powershell\System.Management assembly.

Tested on Windows 10, Server 2012 and Server 2008 R2.

Using the Code

I created the following sample, including a simple interface declaration, to hold our data.

Note that I've removed the multi-line flag (?m) from the above regular expression, in favor of .NET's RegexOptions.MultiLine enumeration. Here is a module for querying and parsing quser data:

F# Example

F#
namespace Vivrant.Parsers
    module QUser =
        open System
        open System.Diagnostics
        open System.Text.RegularExpressions
        type IQUserInformation =
            abstract member Username:String with get
            abstract member SessionName:String with get
            abstract member SessionID:String with get
            abstract member State:String with get
            abstract member IdleTime:String with get
            abstract member LogonTime:DateTime with get
        let QueryUsers(serverName:string) =
            let args = String.Format(" /SERVER:{0}", serverName)
            let cmdQuser = new Process()
            cmdQuser.StartInfo.WorkingDirectory <- Environment.CurrentDirectory
            cmdQuser.StartInfo.FileName <- "lib\quser.exe"
            cmdQuser.StartInfo.Arguments <- args
            cmdQuser.StartInfo.UseShellExecute <- false
            cmdQuser.StartInfo.RedirectStandardOutput <- true
            cmdQuser.StartInfo.CreateNoWindow <- true
            cmdQuser.Start()
            |> ignore
            let stdOut = cmdQuser.StandardOutput.ReadToEnd()
            while(not <| cmdQuser.HasExited) do
                    cmdQuser.WaitForExit()
            stdOut
        let ParseQUserResults(stdOut) =
            let userResults = new ResizeArray<IQUserInformation>()
            let quserPattern = @"^\s?(?<username>[\w\/.\/_\-]{2,64})\s\s+(?<sessionname>\w?.{0,22})\s\s+(?<sessionid>\d{1,5})\s\s+(?<state>.{0,12})\s\s+(?<idletime>.{0,20})\s\s+(?<logontime>.{0,32})$"
            let regex = new Regex(quserPattern, RegexOptions.Multiline)
            let mutable result = regex.Match(stdOut)
            while result.Success do
                    let success, parsedLogonTime = DateTime.TryParse(result.Groups.["logontime"].Value.ToString().Trim())
                    userResults.Add
                        { new IQUserInformation with
                            member this.Username = result.Groups.["username"].Value.ToString().Trim()
                            member this.SessionName = result.Groups.["sessionname"].Value.ToString().Trim()
                            member this.SessionID = result.Groups.["sessionid"].Value.ToString().Trim()
                            member this.State = result.Groups.["state"].Value.ToString().Trim()
                            member this.IdleTime = result.Groups.["idletime"].Value.ToString().Trim()
                            member this.LogonTime =
                                match success with
                                | true -> parsedLogonTime
                                | false -> DateTime.MinValue }
                    result <- result.NextMatch()
            userResults

Now we can call it like this:

F#
module Sample =
    let userInfo = QUser.ParseQUserResults <| QUser.QueryUsers "myPC"
    do ( ) //do something with userInfo

Points of Interest

Depending on your architecture (ie 32bit vs 64bit Processor, OS and Project Build settings), your application may not be able to see the file c:\Windows\system32\quser.exe, because Windows virtualizes access to the System directory.

In order for your program to see `quser.exe`, you may need to have a copy of it OUTSIDE of the SYSTEM32 folder. Browse to it in Explorer, copy, and paste it somewhere else. For the sake of this example, I placed it in a subfolder of my project folder, "MyProject\lib", and set the build options to "copy always".

History

  • 2016-12-13: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Vivrant
United States United States
Software developer working with Emergency Medical Services (EMS), Emergency Response Services (ERS), Ambulance Billing, Computer-Aided Dispatch (CAD), Cloud-Based solutions and Cost-Recovery for First-Responders.

Comments and Discussions

 
-- There are no messages in this forum --