TerminalServicesManager().CurrentSession.ClientName - c#

I am trying to figure out what clients are connected to my machine using remote desktop.
I read about Cassia and the Cassia.TerminalServicesManager, but I can't wrap my mind around it...
I thought that Cassia.TerminalServicesManager().CurrentSession.ClientName would give me a name of the client, but what if there are more? I looked at the references, but I am still confused. Can someone help me out?
Thanks

It sounds like you're looking for something like this:
var manager = new TerminalServicesManager();
using (var server = manager.GetLocalServer())
{
server.Open();
foreach (var session in server.GetSessions())
{
if (session.ConnectionState == ConnectionState.Active)
{
Console.WriteLine(session.ClientName);
}
}
}
ITerminalServicesManager.CurrentSession returns the session in which the current process is running.

By default If you connect to a windows machine using remote desktop it kicks the local user off, if they log back in it kicks the remote user off. If you have enabled Concurrent Remote Desktop Sessions there can be multiple users connected at once. I am not familiar with Cassia but perhaps you could loop over all of the sessions calling Cassia.TerminalServicesManager().CurrentSession.ClientName each time?

Related

Connecting to Active Directory via .NET

I have a virtual machine with Active Directory that I want to connect to using .NET, I've already connected to an ubuntu machine running OpenLDAP but when connecting to AD it's not working smoothly.
The code I'm attempting to connect with is as follows:
var directoryEntry =
new DirectoryEntry("LDAP://192.168.1.1", #"EXAMPLE\Administrator", "Abc1234");
try
{
var test = directoryEntry.NativeObject;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
Watching the locals window the variable directoryEntry's Guid, name etc says "Function evaluation timed out".
Then when it arrives at the try block it simply says "The server is not operational".
I've also tried this code, and it fails at the "ldap.bind" telling me that "the ldap-server is unavailable".
using (var ldap = new LdapConnection("192.168.1.1:389"))
{
ldap.AuthType = AuthType.Basic;
ldap.SessionOptions.ProtocolVersion = 3;
ldap.Bind(new NetworkCredential(#"EXAMPLE\Administrator", "Abc1234"));
}
I know the server is up and running, I know that they have a connection (machines can ping each other) but I can't figure out why it isn't working. Can any of you see if there are any flaws in the code? (and yes I've googled all of the errors and various questions about connecting to AD before asking this question but none of the solutions have worked).
If you domain name is 'example.com' and let say you have an organization unit (OU) called 'users'. This works perfectly fine for me.
However the machine where this code runs, is added to the AD domain and it runs with an AD user account. If you do not have a machine added to the same domain which you are querying, you may try "Run as" option (Shift + Right Click) to launch the program or visual studio.
public static List<string> GetAllUsers()
{
List<string> users = new List<string>();
using (DirectoryEntry de = new DirectoryEntry("LDAP://OU=Users,DC=example,DC=local"))
{
using (DirectorySearcher ds = new DirectorySearcher(de))
{
ds.Filter = "objectClass=user";
SearchResultCollection src = ds.FindAll();
foreach (SearchResult sr in src)
{
using (DirectoryEntry user = new DirectoryEntry(sr.Path))
{
users.Add(new string(user.Properties["sAMAccountName"][0].ToString()));
}
}
}
}
return users;
}
I tested your code (with changed domain / password...) in my own Active Directory test environment, it works. If I use a wrong password intentionally for testing purpose, I get "invalid credentials". Fine.
"The server is not operational" will be returned if LDAP is completely unavailable. So it seems that e.g. port 389 is not reachable.
Firewall ?
LDAP SSL (port 636) ??
If you do not have a machine added to the same domain which you are querying, you may try "Run as" option (Shift + Right Click) to launch the program or visual studio.
Yes, this was my first idea too as I saw this question. However, it seems that you will get another error in this case.
What I suggest: install WireShark, the network analyzer and check what is sent over the wire (assuming your AD is running on another machine).
WireShark helped me more than often to diagnose errors with AD, login, SMB or other protocols.
PS:
The answer from Ravi M Patel is a nice example of searching, I almost do the same in my own code.
Problem solved. I had two network adapters and adapter 1 had dhcp and the static ip I was attempting to connect was running on adapter 2. I simply gave adapter 1 the static adress and was able to connect that way, seemingly the code connects via adapter 1 per default. And Thanks for all the answers guys :)

how to make autologin in windows form application when it connects on online database remotely

i am working on a windows form application in which i have to make an autologin window.i want that when user desktop connects with internet, Automatically login must be occur. My Desktop application is connected with online database.
Can Any body tell me that what is the procedure to do that.
Please help me i am stucked badly in that.
Thanks in Advance,
Take a look at the System.Net.NetworkInformation Namespace. In particular the NetworkChange class.
Example:
NetworkChange.NetworkAvailabilityChanged += (sender, networkAvailabilityEventArgs) =>
{
if (networkAvailabilityEventArgs.IsAvailable)
{
// Network is available
// Try to open a database connection
}
else
{
// Network is not available
// Stop trying to open a database connection, or clean up existing connections
}
};
edit
You can also call NetworkInterface.GetIsNetworkAvailable() to get the same information on-demand.
if (NetworkInterface.GetIsNetworkAvailable())
{
// Network is available
// Try to log on
}
else
{
// Network is not available
// Do nothing
}
Keep trying to connect to the database until you don't get any error (or at least you can reach the database).
You could also try telnet-ing the remote port, but you can't be sure there's one (if you use SQL Server it's possible you're using Named pipes or other protocols)

How to Programatically Start IIS 6.0 SMTP Virtual Server?

I would like to know how to programatically restart IIS 6.0 SMTP server.
The SMTP server I have setup crashes every now and then. I don't notice it for a couple days, but that is by far way too late to do anything about it.
I want to set up a scheduled task every 30 minutes or so to test if the SMTP server is running, and if its not, the Scheduled task with automatically start it back up.
I have found a way to check if the SMTP server is up and running, but I have not figured out how to restart the process if it crashes.
That way is posted here: Testing SMTP server is running via C#
Any help would be brilliant!
Thank you.
Im developing the Console application in C# to check if its running or not, so any code examples would be great too.
A ServiceController can help you, as it has start and stop methods. Look at the sample in the msdn page.
Another sample is taken from the ServiceControllerStatus Enumeration is nearly what you need (just replace the service name).
ServiceController sc = new ServiceController("Telnet");
Console.WriteLine("The Telnet service status is currently set to {0}",
sc.Status.ToString());
if ((sc.Status.Equals(ServiceControllerStatus.Stopped)) ||
(sc.Status.Equals(ServiceControllerStatus.StopPending)))
{
// Start the service if the current status is stopped.
Console.WriteLine("Starting the Telnet service...");
sc.Start();
}
else
{
// Stop the service if its status is not set to "Stopped".
Console.WriteLine("Stopping the Telnet service...");
sc.Stop();
}
// Refresh and display the current service status.
sc.Refresh();
Console.WriteLine("The Telnet service status is now set to {0}.",
sc.Status.ToString());
Maybe I'm missing something, or something changed, but when you install SMTP service on Windows 2012R2, there is no dedicated service for it. So, for recent version of Windows the advice above won't work.
Luckily there's a way to do it much easier. Powershell:
([ADSI]'IIS://LOCALHOST/SMTPSVC/1').Start() #to start
([ADSI]'IIS://LOCALHOST/SMTPSVC/1').Stop() #to ... you guess
The weirdest thing is that you control smtp service through AD, but it works.
And of course this should be run elevated.
If you have several virtual SMTP servers, you may need to identify your server by index or by some property (e.g. .ConnectionTimeout) first.
in c# you can write:
enum StatusVirtualServerSMTP
{
Started = 2,
Stopped = 4
}
DirectoryEntry dir = new DirectoryEntry("IIS://localhost/SMTPSVC/1");
if (Convert.ToInt32(dir.Properties["SERVERSTATE"].Value) == (int)StatusVirtualServerSMTP.Stopped)
{
dir.Properties["SERVERSTATE"].Value = (int)StatusVirtualServerSMTP.Started;
dir.CommitChanges();
}

WMI reports user logged in after logoff if a share was accessed during the session

I'm using WMI inside c# to get a list of users currently "logged in" to a machine:
ManagementScope ms = new ManagementScope(ManagementPath.DefaultPath);
var q = new SelectQuery("Win32_LoggedOnUser");
using (var query = new ManagementObjectSearcher(ms, q)) {
using (var results = query.Get()) {
foreach (var r in results) {
using (var o = new ManagementObject(r["Dependent"].ToString())) {
var logonType = o["LogonType"];
if (logonType == "2") {
// Interactive user is logged in, retrieve the name
using (var userObj = new ManagementObject(r["Antecedent"].ToString())) {
name = userObj["Name"].ToString();
}
}
...
This works great, but it seems that in some cases even after the user logs out, WMI still reports it as being logged in. One particular case is when that user accesses a network share during the session.
Is there anyway around this? Perhaps a way to test a session to see if it was created as a share or if it's active?
Any tips would be greatly appreciated.
Even though the user has logged off, because you accessed another computer's files remotely, the connection remains open for a period of time.
https://superuser.com/questions/173535/what-are-close-wait-and-time-wait-states
Look under Run > cmd > netstat -a. You should see a connection called microsoft-ds after you have established a connection through Windows Explorer to another computer. This is the service that Microsoft uses for file transfers, among other things. If you see a TIME_WAIT or CLOSE_WAIT, the connection is still open even if window you used to access the files is closed.
You can check this programmatically by using "handle.exe", a tool provided by Microsoft that is a part of Sysinternals, that will be able to provide information on which part of the hive is still active. This should include Registry Keys, ports, the works.
http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx
WMI may be reporting that the user is still logged in because a port or connection has not been closed that was initiated by that user. This type of thing has caused us a few headaches, so we use handle.exe to dump anything keeping the hive open for a user and then systematically kill/close all of it before we do any profile maintenance (as an automation).
Of course, rebooting the computer always works. =)

How can you read the count of an MSMQ on another machine?

My program is successfully using .NET's MessageQueue class to read from an MSMQ. The queue is user configurable, and is sometimes on the local machine, and sometimes on a remote machine. The user can specify the remote machine either by name or IP address, and the queue name (and I'm only using "Private" queues).
I want to display to the user how many messages remain in the Queue, but haven't found a way to do this. The MessageQueue class does not seem to have a Count (or similar) property to give this to me easily.
I've been able to use the PerformanceCounter and PerformanceCounterCategory classes to get the count - but this only seems to work for me on the local machine (although I'm not completely sure I'm using these classes correctly).
My question is how to read the Count (number of messages) from an MSMQ on a remote machine?
I use the following method for message counting (works for both local and remote queues),
var machineName = "mymachine01";
var formatName = "FormatName:DIRECT=OS:mymachine01\private$\ftpreceived":
try
{
var msmqManagement = new MSMQ.MSMQManagement();
msmqManagement.Init(machineName, null, formatName );
return (uint)msmqManagement.MessageCount;
}
catch (COMException ex)
{
// If queue is not active or does not exist.
if (ex.ErrorCode == -1072824316)
{
return 0;
}
throw;
}
Note: It returns 0 in the case the queue does not exist or is not active as the MSMQ Managment API considers this the same error.
Note: If the machine name value is null it will look at the queue on the local machine.
Note: If the machinename variable is different from the machinename part of the formatname, it will return a count of messages in the "Outgoing" message queue with the given format name on the machine specified by machinename.
Active means it has 1 or more messages in it, or it has had a message in it within the last N (Not sure how big N is :)) seconds, after that time the queue is considered inactive.
The most reliable solution for getting the count of messages in a local queue is to use the MSMQ APIs using P/Invoke. There's a nice article here: Counting the number of messages in a Message Queue in .NET.
I don't know if it works with remote queues, but I wouldn't rely on it. Generally, the only thing you should do with a remote queue is to send a message. Trying to read messages or properties from a remote queue should be avoided, if possible. "Send remote and read local" will always give you the best performance and avoid all kinds of problems (e.g., what if the remote machine isn't available?)
I am using WMI to get this information. The following is an example of the code that I am using to accomplish this.
var query = String.Format("select MessagesinQueue from Win32_PerfRawdata_MSMQ_MSMQQueue where name ='{0}'", path.Replace("\\", "\\\\"));
var selectQuery = new SelectQuery(query);
using (var searcher = new ManagementObjectSearcher(selectQuery))
using (var results = searcher.Get())
{
foreach (var result in results)
{
var messages = result["MessagesinQueue"].ToString();
return long.Parse(messages);
}
}
This may be a solution for you: http://jopinblog.wordpress.com/2008/03/12/counting-messages-in-an-msmq-messagequeue-from-c/
This might be overkill, but you could possibly put a WCF service on the same machine hosting your queue, so you'd be able to retrieve the count using the performance counters in the WCF service and expose that functionality through a method of that service.
I would like to say several things here.
Before I get to my own answer, I would like to comment John Opncar's solution (in Dr. Wily's Apprentice answer). His code does work on remote machines. I used his code in our project at work to watch the queues on a remote cluster server and it works very well.
So, if get "RemoteMachineNotAvailable" errors, please check your configurations. Are all machines in the same network or - not to forget - are the queue's security permissions on the remote machine set up to allow others to read them?
Do the users/ accounts have sufficient rights to read from other systems?
For example, we had to allow everyone on the clustered queues.
As far as I know the PerformanceCounters do indeed have problems to read message properties on remote machines. I tried to use them for queues in a Windows Server cluster environment, but was never able to get it working. I did some internet research at that time, but unfortunatelly I do not recall if this is due to security reasons or simply a bug. :-(
Now to the actual answer. If you do not like the Cursor-Method as described by John Opincar you could also use the MessageQueue.GetAllMessages() or MessageQueue.GetMessageEnumerator methods.
I never tried GetMessageEnumerator, but I can say that I would not recommend GetAllMessages().
We suffered from heavy performance issues when using it every second on a system with several queues that contain several thousands of messages.
The method takes a snapshot of all messages in the queue, which can cause heavy loads in memory and network.
The cursor-methodis still somewhat slow. But, at least in our production environment, it feels more snappy than with the GetAllMessages() solution.
If counting the messages in your scenario does not need to be as often as one second and you have less messages to count than we do, then working with GetAllMessages() or GetMessageEnumerator() might be a possible solution for you.
Finally, it always comes down to your own individual needs.

Categories