Getting the Current Session of the Current User

187 views
Skip to first unread message

Ibrahim Rafiq

unread,
Feb 22, 2012, 7:19:35 AM2/22/12
to Cassia Users
Hi All,

As a noob programmer, I have been tasked with developing a solution
which allows a program (be it console / form) to do a graceful logout
on a RDP session that has been disconnected. A little background:- we
have a database application running on 6 terminal servers where users
log into to access the application. Some users at the end of the day
will correctly logout of the terminal server by clicking Start ---->
LogOff.

Others will disconnect the session thus leaving the application
running which causes problems as their data can not be compacted on a
night when maintenance runs. I simply can not reset / logoff the
session through the Terminal Services Manager as it is not graceful
and also damages the datasets.

I have used Cassia so far to develop a solution which achieves a
graceful logout if the session is disconnected for over 5 minutes.

However, it only works on the first user that logged in to the server
out of the many hundreds that login.

Could someone please take a look at the code below and see where I am
going wrong. I need to extract the current session per user per
application running.

I think it is something to do with the foreach loop on
ITerminalServicesSession

Thanks,

<code>
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.DirectoryServices.AccountManagement;
using Cassia;

//
************************************************************************************************************************************//
//-------------------------------------------------------******CASSIA
DLL USED******--------------------------------------------------//
//http://code.google.com/p/
cassia// //
//http://www.opensource.org/licenses/mit-
license.php// //
//Open Source Initiative OSI - The MIT License
(MIT):Licensing //
//
************************************************************************************************************************************// //
//The MIT License
(MIT) //
//Copyright (c) <year> <copyright
holders> //
//
************************************************************************************************************************************//
//Permission is hereby granted, free of charge, to any person
obtaining a copy of this software
and //
//associated documentation files (the "Software"), to deal in the
Software without restriction, //
//including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, //
//and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, //
//subject to the following
conditions: //
//
************************************************************************************************************************************//
//The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the
Software. //
//
************************************************************************************************************************************//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, //
//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, //
//FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. //
//IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, //
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE //
//USE OR OTHER DEALINGS IN THE
SOFTWARE. //
//
************************************************************************************************************************************//


namespace Windows_Information
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

internal struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}

string sessionStatus = "";
Boolean keepLooping = true;
//System.Diagnostics.Process.;



public Form1()
{
InitializeComponent();
}


private void itsAllaboutTime(object sender, EventArgs e)
{
{
ITerminalServicesManager manager = new
TerminalServicesManager();

using (ITerminalServer server =
manager.GetLocalServer())
{
server.Open();

foreach (ITerminalServicesSession session in
server.GetSessions())


{

sessionStatus =
session.ConnectionState.ToString();


}
}
}

int systemSincelastEntry = Environment.TickCount;
int LastInputTicks = 0;
int idleTime = 0;

LASTINPUTINFO LastInputInfo = new LASTINPUTINFO();
LastInputInfo.cbSize =
(uint)Marshal.SizeOf(LastInputInfo);
LastInputInfo.dwTime = 0;

if (GetLastInputInfo(ref LastInputInfo))
{
LastInputTicks = (int)LastInputInfo.dwTime;
idleTime = systemSincelastEntry - LastInputTicks;
}

textBox3.Text = Convert.ToString(idleTime) + "
Millisecconds";
textBox4.Text = (sessionStatus);

while (keepLooping)
{
Application.DoEvents();

//System.Threading.Thread.Sleep(300001);

if (sessionStatus == "Active")
{
System.Threading.Thread.Sleep(300001);
keepLooping = true;

}


else if ((sessionStatus == "Disconnected") &&
(idleTime < 299999))
{
keepLooping = true;
}


else if ((sessionStatus == "Disconnected") &&
(idleTime >= 300000))
{
keepLooping = false;
}
}


//string strCmdText;
//strCmdText = "/C shutdown -l";
System.Diagnostics.Process.Start("shutdown", "/l");
Application.Exit();

}

}

}

</code>


















Robert Gijsen

unread,
Feb 22, 2012, 9:17:42 AM2/22/12
to Cassia Users
Not actually answering your question, but why don't you setup a
'logoff disconnected session' in your group-policy? That would do the
exactly same logoff as your tool does, so that should be graceful
enough.
For your program: I am not a C user (I only write in VB.NET) but are
you really sure you reset the keepLooping variable after you logged of
a session? Also you should be able to trace step-by-step in your
programming-interface, allowing you to find the cause more specificly.

Ibrahim Rafiq

unread,
Feb 22, 2012, 9:27:53 AM2/22/12
to Cassia Users
Hi Robert,

I will look into the keepLooping to see if it is being reset after a
logout.

I have considered and tested the logout disconnected users in GPO but
it is not a graceful one - we had loads of datasets damaged this way
last time.

The CMD command "shutdown -l" or "shutdown /l" performs the same steps
as if a user actually click on Start and Logoff - which my application
is programmed to respond to and close down gracefully, but the group
policy one doesn't.

Thanks,

Ibrahim Rafiq

unread,
Feb 22, 2012, 10:42:23 AM2/22/12
to Cassia Users
The keepLooping Boolean seems to be working fine.

I haven't mentioned that for some reason if two different users log in
on the Terminal Server - the second logged in user seems to be sharing
the same variables with the first user.

For example, if user one disconnects, the forms text field changes to
disconnected on the second users form!

Have I done something really wrong here?
> > programming-interface, allowing you to find the cause more specificly.- Hide quoted text -
>
> - Show quoted text -

Kenneth Smith

unread,
Feb 22, 2012, 10:50:33 AM2/22/12
to cassia...@googlegroups.com
Most likely you are using Global variables. If you are, you need to use member variables/properties.


--
You received this message because you are subscribed to the Google Groups "Cassia Users" group.
To post to this group, send email to cassia...@googlegroups.com.
To unsubscribe from this group, send email to cassia-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cassia-users?hl=en.




--
I would love to change the world but they won't give me the source code

Dan Ports

unread,
Feb 23, 2012, 10:12:37 AM2/23/12
to cassia...@googlegroups.com
Ibrahim,

It seems like you are doing something a bit wrong here, assuming that you're running the code you posted in every user's session.

Your foreach (ITerminalServicesSession session in server.GetSessions()) loop is going to iterate through all of the sessions on the server, not just the current one. You probably want to replace that entire using block and foreach loop with sessionStatus = manager.CurrentSession.ConnectionState.ToString(). That will return the connection state for the session in which the current process is executing.

I ran into a very similar situation on one of my projects, and our solution was to add code to our Windows Forms application that would check the idle time of the current session periodically (via ITerminalServicesManager.CurrentSession.IdleTime) and close the application gracefully if it was above a certain threshold (say, an hour). Closing the application would then automatically logoff the session, since the application was set to be the startup program for the session.

Dan

On Wed, Feb 22, 2012 at 10:42 AM, Ibrahim Rafiq <ibraf...@gmail.com> wrote:

Ibrahim Rafiq

unread,
Feb 23, 2012, 10:34:02 AM2/23/12
to Cassia Users
Hi Dan,

That worked like a charm.

Thank You

Ibs

On Feb 23, 3:12 pm, Dan Ports <danpo...@gmail.com> wrote:
> Ibrahim,
>
> It seems like you are doing something a bit wrong here, assuming that
> you're running the code you posted in every user's session.
>
> Your foreach (ITerminalServicesSession session in server.GetSessions())
> loop is going to iterate through all of the sessions on the server, not
> just the current one. You probably want to replace that entire using block
> and foreach loop with sessionStatus =
> manager.CurrentSession.ConnectionState.ToString(). That will return the
> connection state for the session in which the current process is executing.
>
> I ran into a very similar situation on one of my projects, and our solution
> was to add code to our Windows Forms application that would check the idle
> time of the current session periodically (via
> ITerminalServicesManager.CurrentSession.IdleTime) and close the application
> gracefully if it was above a certain threshold (say, an hour). Closing the
> application would then automatically logoff the session, since the
> application was set to be the startup program for the session.
>
> Dan
>
> >http://groups.google.com/group/cassia-users?hl=en.- Hide quoted text -

Dan Ports

unread,
Mar 1, 2012, 8:21:21 PM3/1/12
to cassia...@googlegroups.com
Glad to hear it.

Robert and Kenneth: Thanks for the suggestions!

Robert, I did use the GP settings you mentioned in my project early on, but discarded that approach later for the same reason Ibrahim did. But it can work for running applications that don't need to do any significant cleanup on exit.

Dan
Reply all
Reply to author
Forward
0 new messages