Reputation: 51
I need to find out the idle time of remote pc from server pc using c# application. I have a list of IP addresses and host names connected in Local Area Network. I want to find out idle time more then 30 min for each computer connected in LAN. I done it for local pc, but it not works for remote pc. here is my code for local pc.
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
private int GetIdleTime()
{
LASTINPUTINFO lastone = new LASTINPUTINFO();
lastone.cbSize = (uint)Marshal.SizeOf(lastone);
lastone.dwTime = 0;
int idleTime = 0;
int tickCount = Environment.TickCount;
if (GetLastInputInfo(ref lastone))
{
idleTime = tickCount - (int)lastone.dwTime;
return idleTime;
}
else
return 0;
}
Upvotes: 0
Views: 2087
Reputation: 91
I use this remote WMI query:
object idleResult = Functions.remoteWMIQuery(machinename, "", "", "Select CreationDate From Win32_Process WHERE Name = \"logonUI.exe\"", "CreationDate", ref wmiOK);
Logonui.exe is the lockscreen. In business environments most systems lock when a user is idle.
You can translate the result like this in DateTime format
DateTime idleTime = Functions.ParseCIM_DATETIME((string)idleResult);
Where ParseCIM_DATETIME is this fucntion:
public static DateTime ParseCIM_DATETIME(string date)
{
//datetime object to store the return value
DateTime parsed = DateTime.MinValue;
//check date integrity
if (date != null && date.IndexOf('.') != -1)
{
//obtain the date with miliseconds
string newDate = date.Substring(0, date.IndexOf('.') + 4);
//check the lenght
if (newDate.Length == 18)
{
//extract each date component
int y = Convert.ToInt32(newDate.Substring(0, 4));
int m = Convert.ToInt32(newDate.Substring(4, 2));
int d = Convert.ToInt32(newDate.Substring(6, 2));
int h = Convert.ToInt32(newDate.Substring(8, 2));
int mm = Convert.ToInt32(newDate.Substring(10, 2));
int s = Convert.ToInt32(newDate.Substring(12, 2));
int ms = Convert.ToInt32(newDate.Substring(15, 3));
//compose the new datetime object
parsed = new DateTime(y, m, d, h, mm, s, ms);
}
}
//return datetime
return parsed;
}
The remote WMI Query function is as follows:
public static object remoteWMIQuery(string machine, string username, string password, string WMIQuery, string property, ref bool jobOK)
{
jobOK = true;
if (username == "")
{
username = null;
password = null;
}
// Configure the connection settings.
ConnectionOptions options = new ConnectionOptions();
options.Username = username; //could be in domain\user format
options.Password = password;
ManagementPath path = new ManagementPath(String.Format("\\\\{0}\\root\\cimv2", machine));
ManagementScope scope = new ManagementScope(path, options);
// Try and connect to the remote (or local) machine.
try
{
scope.Connect();
}
catch (ManagementException ex)
{
// Failed to authenticate properly.
jobOK = false;
return "Failed to authenticate: " + ex.Message;
//p_extendederror = (int)ex.ErrorCode;
//return Status.AuthenticateFailure;
}
catch (System.Runtime.InteropServices.COMException)
{
// Unable to connect to the RPC service on the remote machine.
jobOK = false;
return "Unable to connect to RPC service";
//p_extendederror = ex.ErrorCode;
//return Status.RPCServicesUnavailable;
}
catch (System.UnauthorizedAccessException)
{
// User not authorized.
jobOK = false;
return "Error: Unauthorized access";
//p_extendederror = 0;
//return Status.UnauthorizedAccess;
}
try
{
ObjectQuery oq = new ObjectQuery(WMIQuery);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, oq);
foreach (ManagementObject queryObj in searcher.Get())
{
if (property != null)
{
return queryObj[property];
}
else return queryObj;
}
}
catch (Exception e)
{
jobOK = false;
return "Error: " + e.Message;
}
return "";
}
Upvotes: 1
Reputation: 173
If you have the screensaver enabled I would suggest you check the CreateDate on the screensaver process and do a difference from the remote the createdate time and you get the idle time + the screensaver timeout
you might want to use WMI for this kind of thing
its a hack but it works
Upvotes: 0
Reputation: 2020
Acording to MSDN, this is not possible entirely for the local machine let alone a remote one.
This function is useful for input idle detection. However, GetLastInputInfo does not provide system-wide user input information across all running sessions. Rather, GetLastInputInfo provides session-specific user input information for only the session that invoked the function.
You could however try one of the following:
If you do not have terminal services deactivated, and the clients are xp or higher, you can also use
ITerminalServicesSession.LastInputTime
For this you either use the Cassia libraries or p/invoke
WTSQuerySessionInformation
Upvotes: 1