0

I am creating a UI for our IT Department that shadow a user's session. First, you have to get the session ID using the following command.

        Process Process = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/K" + "qwinsta /server:" + ComputerName + " " + Username);
        startInfo.CreateNoWindow = false;
        startInfo.UseShellExecute = true;

        Process = Process.Start(startInfo);

And this is what you get out.

 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 console           mlynch                    8  Active

As of right now, this opens the command prompt for this command with the computer name and username you put into a couple of text boxes. You then take the session ID and input it into a 3rd text box and click the connect button. I am trying to bypass this step. Input the computer and username, click connect and it goes. I need to find a way to get the session ID and save it to a string, then reference that string in the next line of code.

        if (MouseControlCheck.Checked == true)
        {
        Process Process = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc.exe /shadow:" + SessionID + " /v " + ComputerName + " /control");
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;

        Process = Process.Start(startInfo);
        }
        else
        {
        Process Process = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc.exe /shadow:" + SessionID + " /v " + ComputerName);
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;

        Process = Process.Start(startInfo);
        }

How do I read the session ID to a string?

TLDR: I want to skip over console and mlynch and just get to the number under ID. This is not going to be used to get the local machine ID, I want the ID of a computer on the network.

Matt Lynch
  • 155
  • 1
  • 7
  • Found my answer here https://stackoverflow.com/questions/59274974/find-specific-text-in-richtextbox-and-set-it-to-a-string-c-sharp – Matt Lynch Dec 17 '19 at 17:05

4 Answers4

0

From MS site

You need to add RedirectStandardOutput = true and then Read Standardoutput.

string[] allLines;
using (Process process = new Process())
        {
            process.StartInfo.FileName = "ipconfig.exe";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();

            // Synchronously read the standard output of the spawned process. 
            StreamReader reader = process.StandardOutput;
            string output = reader.ReadToEnd();

            // Convert all text to string array
            allLines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

            // Write the redirected output to this application's window.
            Console.WriteLine(output);

            process.WaitForExit();
        }
Jawad
  • 11,028
  • 3
  • 24
  • 37
0

Based on this post, c# how to determine session id of specific logged in windows user, might be easier to just use windows api to get the user session info. This removes the need to call cmd and parse the output. I modified it slightly to get a specific user

class Program
{
    static void Main(string[] args)
    {

        // this code gets the users from localhost -
        // can change this to a remote hostname on the network
        Console.Write(UserLogins.GetUser("COMPUTER_NAME", "USER_NAME"));

        Console.ReadKey();

    }

    public class UserLogins
    {

        [DllImport("wtsapi32.dll")]
        static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName);

        [DllImport("wtsapi32.dll")]
        static extern void WTSCloseServer(IntPtr hServer);

        [DllImport("wtsapi32.dll")]
        static extern Int32 WTSEnumerateSessions(
            IntPtr hServer,
            [MarshalAs(UnmanagedType.U4)] Int32 Reserved,
            [MarshalAs(UnmanagedType.U4)] Int32 Version,
            ref IntPtr ppSessionInfo,
            [MarshalAs(UnmanagedType.U4)] ref Int32 pCount);

        [DllImport("wtsapi32.dll")]
        static extern void WTSFreeMemory(IntPtr pMemory);

        [DllImport("Wtsapi32.dll")]
        static extern bool WTSQuerySessionInformation(
            System.IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned);

        [StructLayout(LayoutKind.Sequential)]
        private struct WTS_SESSION_INFO
        {
            public Int32 SessionID;

            [MarshalAs(UnmanagedType.LPStr)]
            public String pWinStationName;

            public WTS_CONNECTSTATE_CLASS State;
        }

        public enum WTS_INFO_CLASS
        {
            WTSInitialProgram,
            WTSApplicationName,
            WTSWorkingDirectory,
            WTSOEMId,
            WTSSessionId,
            WTSUserName,
            WTSWinStationName,
            WTSDomainName,
            WTSConnectState,
            WTSClientBuildNumber,
            WTSClientName,
            WTSClientDirectory,
            WTSClientProductId,
            WTSClientHardwareId,
            WTSClientAddress,
            WTSClientDisplay,
            WTSClientProtocolType
        }
        public enum WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }

        public static IntPtr OpenServer(String Name)
        {
            IntPtr server = WTSOpenServer(Name);
            return server;
        }
        public static void CloseServer(IntPtr ServerHandle)
        {
            WTSCloseServer(ServerHandle);
        }

        public static UserInfo GetUser(string server, string username)
        {
            return GetUsers(server).FirstOrDefault(c => c.User.Equals(username, StringComparison.InvariantCultureIgnoreCase));
        }

        public static IEnumerable<UserInfo> GetUsers(String ServerName)
        {
            IntPtr serverHandle = IntPtr.Zero;
            List<String> resultList = new List<string>();
            serverHandle = OpenServer(ServerName);

            try
            {
                IntPtr SessionInfoPtr = IntPtr.Zero;
                IntPtr userPtr = IntPtr.Zero;
                IntPtr domainPtr = IntPtr.Zero;
                Int32 sessionCount = 0;
                Int32 retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref SessionInfoPtr, ref sessionCount);
                Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
                Int32 currentSession = (int)SessionInfoPtr;
                uint bytes = 0;

                if (retVal != 0)
                {
                    for (int i = 0; i < sessionCount; i++)
                    {
                        WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO));
                        currentSession += dataSize;

                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);
                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);

                        yield return new UserInfo
                        {
                            Domain = Marshal.PtrToStringAnsi(domainPtr),
                            User = Marshal.PtrToStringAnsi(userPtr),
                            SessionID = si.SessionID
                        };

                        WTSFreeMemory(userPtr);
                        WTSFreeMemory(domainPtr);
                    }

                    WTSFreeMemory(SessionInfoPtr);
                }
            }
            finally
            {
                CloseServer(serverHandle);
            }
        }
    }
    public class UserInfo
    {
        public string Domain { get; set; }
        public string User { get; set; }

        public int SessionID { get; set; }

        public override string ToString()
        {
            return string.Format("{0}\\{1}: {2}", Domain, User, SessionID);
        }
    }
}
hawkstrider
  • 4,141
  • 16
  • 27
0

An alternative solution to your problem would be to use WMI to get the user information (even remotely), avoiding output redirection altogether:

using Microsoft.Management.Infrastructure;

string Namespace = @"root\cimv2";
string OSQuery = "SELECT * FROM Win32_OperatingSystem";
CimSession mySession = CimSession.Create("Computer_B");
IEnumerable<CimInstance> queryInstance = mySession.QueryInstances(Namespace, "WQL", OSQuery);
Mark McWhirter
  • 1,168
  • 3
  • 11
  • 28
0

I figured out what I had to do.

                Process GetSessionID = new Process();
                GetSessionID.StartInfo.FileName = "CMD.exe";
                GetSessionID.StartInfo.Arguments = "/C" + "for /f \"skip=1 tokens=3\" %1 in ('query user " + Username + "/server:" + ComputerName + "') do @echo %1";
                GetSessionID.StartInfo.RedirectStandardOutput = true;
                GetSessionID.StartInfo.UseShellExecute = false;
                GetSessionID.StartInfo.CreateNoWindow = true;
                GetSessionID.Start();
                SessionIDOutput = GetSessionID.StandardOutput.ReadToEnd();
                GetSessionID.WaitForExit();
                DoAllTheThingsTextBox.Text = SessionIDOutput;
                if (GetSessionID.HasExited == true)
                {
                    var digitArray = DoAllTheThingsTextBox.Text.Where(Char.IsDigit).ToArray();
                    SessionID = new String(digitArray);

                    if (MouseControlCheck.Checked == true)
                    {
                        Process Process = new Process();
                        ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc /shadow:" + SessionID + " /v " + ComputerName + " /control");
                        startInfo.CreateNoWindow = true;
                        startInfo.UseShellExecute = false;

                        Process = Process.Start(startInfo);
                    }
                    else
                    {
                        Process Process = new Process();
                        ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc /shadow:" + SessionID + " /v " + ComputerName);
                        startInfo.CreateNoWindow = true;
                        startInfo.UseShellExecute = false;

                        Process = Process.Start(startInfo);
                    }
                }
Matt Lynch
  • 155
  • 1
  • 7