Avatar of John500
John500Flag for United States of America

asked on 

How to get current user logged on remote machine using Terminal Services with C#

Greetings:

I need a C# routine that will return the current user logged to a given system name.  I've been told 'Terminal Services' is the way to go but I don't know how to implement it within C#.  Can this be done?  Does the C# application need to be running on the Terminal Server or can the C# application run such a query from an XP box and use the Terminal Server?

The reason a C# application is involved is because it serves as a 'Control Center' for many kinds of system(s) monitoring.  I  need to keep this requirement within the confines of the Control Center.

Help & thanks!
.NET ProgrammingMicrosoft Server OSC#

Avatar of undefined
Last Comment
John500
Avatar of BSonPosh
BSonPosh
Flag of United States of America image

I am not sure you understood what I mean by Terminal Services.

I meant use the Terminal Services Counters provided by WMI, and I think these will only be useful if you have the Remote Desktop enabled.

This is the class you can use to determin if you have an active session Win32_PerfFormattedData_TermService_TerminalServices...

Let me see what I can work out
Avatar of BSonPosh
BSonPosh
Flag of United States of America image

I got it... the easiest way I can find.

You can use GetOwner Method on Win32_Process.. here is  filter
"Select * from Win32_Process Where SessionID='0' AND name='Explorer.exe""
Avatar of John500
John500
Flag of United States of America image

ASKER

Alright!   Getting closer, I'm still having a little trouble with the code.  Can you get the code to compile or tell me what I'm missing below?  I tried to create a simple class first and build up later:

Thanks
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Management;
 
 
 
namespace GetUserInfo
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
           
            //Connection credentials to the remote computer - not needed if the logged in account has access 
            ConnectionOptions oConn = new ConnectionOptions(); 
            oConn.Username = "JohnDoe"; 
            oConn.Password = "JohnsPass"; 
 
            System.Management.ManagementScope oMs = new System.Management.ManagementScope("\\MachineX", oConn);     
 
            //get Fixed disk stats 
            System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3"); 
 
            //Execute the query  
            ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs,oQuery); 
 
            //Get the results
            ManagementObjectCollection oReturnCollection = oSearcher.Get();   
                      
            //loop through found drives and write out info 
            foreach( ManagementObject oReturn in oReturnCollection ) 
            { 
                // Disk name 
                Console.WriteLine("Name : " + oReturn["Name"].ToString()); 
                // Free Space in bytes 
                Console.WriteLine("FreeSpace: " + oReturn["FreeSpace"].ToString()); 
                // Size in bytes 
                Console.WriteLine("Size: " + oReturn["Size"].ToString()); 
            } 
 
            return;
 
        }
    }
}

Open in new window

Avatar of BSonPosh
BSonPosh
Flag of United States of America image

I dont write C#... I am a Powershell Guy, but it looks to me like you have the constructor wrong for System.Management.ManagementScope.

C#public ManagementScope(
    ManagementPath path,
    ConnectionOptions options
)

Path is not a string it is a http://msdn.microsoft.com/en-us/library/system.management.managementpath.aspx

Again... I am NOT a developer so I may be missing something.
Avatar of John500
John500
Flag of United States of America image

ASKER

Ok, I haven't forgot about this question but I still haven't had time to check out the link to respond.

... glad it's Friday over here....
Avatar of BSonPosh
BSonPosh
Flag of United States of America image

did you get this working?
Avatar of John500
John500
Flag of United States of America image

ASKER

No, I've been trying my best to move forward but there have been other priorities.  When you said, "Path is not a string...."   did you mean it was this:

 ManagementPath p =
            new ManagementPath(
            "\\\\ComputerName\\root" +
            "\\cimv2:Win32_LogicalDisk.DeviceID=\"C:\"");

Avatar of BSonPosh
BSonPosh
Flag of United States of America image

/shrug

I just know the constructor doesn't use String.
Avatar of John500
John500
Flag of United States of America image

ASKER

Ok!  I'm glad to say I was able to get this code to compile.  Now I'm having problems with the connection parameter.  Here's what I have:


System.Management.ManagementException was unhandled
  Message="Invalid parameter "
  Source="System.Management"
  StackTrace:
       at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
       at System.Management.ManagementPath.CreateWbemPath(String path)
       at System.Management.ManagementPath..ctor(String path)
       at System.Management.ManagementScope..ctor(String path, ConnectionOptions options)
       at GetUserInfo.Program.Main() in C:\test\C#\GetUser\program.cs:line 37
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()


using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Management;

namespace GetUserInfo
{
    static class Program
    {
        ///
        /// The main entry point for the application.
        ///
        [STAThread]
        static void Main()
        {
           

            //Connection credentials to the remote computer - not needed if the logged in account has access
            ConnectionOptions oConn = new ConnectionOptions();
            oConn.Username = "joeuser";         //  **********  WHO SHOULD THIS USER BE  ?? *************//
            oConn.Password = "123XYZ";

            System.Management.ManagementScope oMs = new System.Management.ManagementScope("SystemName", oConn);  // *** ERROR HERE  

            //get Fixed disk stats
            System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3");
           // get remote user once the connection issue is resolved
            System.Management.ObjectQuery oQuery2 = new System.Management.ObjectQuery("select * from Win32_Process where SessionID='0' AND name='Explorer.exe");
           

            //Execute the query  
            ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs,oQuery);

            //Get the results
            ManagementObjectCollection oReturnCollection = oSearcher.Get();  
                     
            //loop through found drives and write out info
            foreach( ManagementObject oReturn in oReturnCollection )
            {
                // Disk name
                Console.WriteLine("Name : " + oReturn["Name"].ToString());
                // Free Space in bytes
                Console.WriteLine("FreeSpace: " + oReturn["FreeSpace"].ToString());
                // Size in bytes
                Console.WriteLine("Size: " + oReturn["Size"].ToString());
            }

            return;

        }
    }
}

Avatar of BSonPosh
BSonPosh
Flag of United States of America image

The user should be A local admin on the machine.

I assume you replace "SystemName" with the actual hostname.

As per the < http://msdn.microsoft.com/en-us/library/w7sx1w4f.aspx > The constructor wants The server and namespace.

###################################
Parameters
 Path
   Type: System..::.String
   The server and namespace for the ManagementScope.
 options
   Type: System.Management..::.ConnectionOptions
   A ConnectionOptions containing options for the connection.
Avatar of John500
John500
Flag of United States of America image

ASKER

Ok, making progress.  Here's the error I get on a remote system that I would normally have access too:

System.UnauthorizedAccessException was unhandled
  Message="Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
  Source="System.Management"
  StackTrace:
       at System.Management.ManagementScope.Initialize()
       at GetUserInfo.Program.Main() in C:\test\C#\GetUser\program.cs:line 30
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Management;
 
namespace GetUserInfo
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            
            //Connection credentials to the remote computer - not needed if the logged in account has access 
            ConnectionOptions Options = new ConnectionOptions(); 
            Options.Username = "JOEUSER";    		// ************ ADMIN FOR REMOTE MACHINE *************//
            Options.Password = "************";
            Options.Authority = "NTLMDOMAIN:ServerX";
 
            //System.Management.ManagementScope scope = new System.Management.ManagementScope("\\\\hbh8291", Options);
            //scope.Connect();
 
            ManagementScope scope = new ManagementScope("\\\\ServerX\\root\\cimv2", Options);  // ************* wHAT IS THE "\\root\\cimv2" ALL ABOUT ?
 
            scope.Connect();  // ******************  ERROR HERE  ***************** //
 
 
            //get Process objects 
            System.Management.ObjectQuery query = new System.Management.ObjectQuery("Select * from Win32_Process");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
 
            ManagementObjectCollection QueryCollection = searcher.Get();
            foreach (ManagementObject QueryResult in QueryCollection)
            { 
                //Name of process 
                Console.WriteLine(QueryResult["Name"].ToString().ToLower()); 
                //arg to send with method invoke to return user and domain - below is link to SDK doc on it 
                string[] o = new String[2];                 
                //Invoke the method and populate the o var with the user name and domain 
                QueryResult.InvokeMethod("GetOwner",(object[])o); 
                //write out user info that was returned 
                Console.WriteLine("User: " + o[1]+ "\\" + o[0]); 
                Console.WriteLine("PID: " + QueryResult["ProcessId"].ToString()); 
                //get priority 
                if(QueryResult["Priority"] != null) 
                    Console.WriteLine("Priority: " + QueryResult["Priority"].ToString()); 
                 
                /*get creation date - need managed code function to convert date - 
                if(QueryResult["CreationDate"] != null) 
                { 
                    //get datetime string and convert 
                    string s = QueryResult["CreationDate"].ToString();    
 
                    //see ToDateTime function in sample code 
                    DateTime dc = DateTime.ParseExact(s, "mmddyyyy hh:mm", System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat);
           
                    //write out creation date 
                    Console.WriteLine("CreationDate: " + dc.AddTicks(-TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks).ToLocalTime().ToString()); 
                } 
                */ 
                //this is the amount of memory used 
                if(QueryResult["WorkingSetSize"] != null) 
                { 
                    long mem = Convert.ToInt64(QueryResult["WorkingSetSize"].ToString()) / 1024; 
                    Console.WriteLine("Mem Usage: {0:#,###.##}Kb",mem); 
                } 
            }
            return;
        }
    }
}

Open in new window

Avatar of BSonPosh
BSonPosh
Flag of United States of America image

try domain\name format
Avatar of John500
John500
Flag of United States of America image

ASKER

You mean something like:

Options.Authority = "US\ServerX";

In other words, I thought the word 'NTLMDOMAIN' was a necessary reserved word for the connection.  Are you saying this is not the correct interpretation?

John
ASKER CERTIFIED SOLUTION
Avatar of BSonPosh
BSonPosh
Flag of United States of America image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of John500
John500
Flag of United States of America image

ASKER

Ok, sorry to be away so long on this one - bombarded by other issues.

I'll close this up soon

Avatar of John500
John500
Flag of United States of America image

ASKER

Sorry for the delay.  I still haven't had time to finish this but I left it hang too long.  Thanks again!
.NET Programming
.NET Programming

The .NET Framework is not specific to any one programming language; rather, it includes a library of functions that allows developers to rapidly build applications. Several supported languages include C#, VB.NET, C++ or ASP.NET.

137K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo