nicc777 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Here is what I want to do: I would like to monitor my network activity (HTTP and SMTP) from my Windows machine if I am not at the desk - and the only way I can now figure out how to detect this is in one of two ways: either the screensaver is active, or the screen is locked.

I imagine installing a script as a service which poles the system every x amount of time. The updates are written to a DB on a *nix box. In the end I want to compare the number of HTTP and SMTP requests through my proxies while I was away from my computer.

This could potentially help me understand what my PC is upto when I am not at my desk :)

Thanks for any help you may have.

Cheers

Nico

  • Comment on Detect if Windows screensaver is running or screen is locked (Lock Computer)

Replies are listed 'Best First'.
Re: Detect if Windows screensaver is running or screen is locked (Lock Computer)
by Corion (Patriarch) on Aug 07, 2006 at 07:56 UTC

    After some quick digging in the MSDN, there is no WMI query but you have to use the raw Win32 API to access the tick count of the computer and the timestamp (in ticks) since the last user input. From the difference between the two you can determine the time the user has been idle (or rather, has been making no input, maybe because he's discussing some issue on the screen):

    #!/usr/bin/perl -w use strict; use Win32::API; use POSIX qw(strftime); use Data::Dumper; my $GetLastInputInfo = Win32::API->new("user32.dll",'GetLastInputInfo' +,'P','I'); my $GetTickCount = Win32::API->new("kernel32.dll",'GetTickCount','','I +'); sub get_user_idle_time { my $buffer = pack "VV", 8,0; $GetLastInputInfo->Call($buffer) or die "Couldn't call GetLastInputInfo: $^E"; my ($size,$time) = unpack "VV", $buffer; my $now = $GetTickCount->Call; # Adjust time to return a reference in seconds return int (($now-$time) / 1000); }; while (1) { print strftime( "Idle since %M:%S\n", localtime(get_user_idle_time +)); sleep(2); };
      my $GetTickCo­unt = Win32::API­->new("ker­nel32.dll"­,'GetTickC­ount', +'','­I');

      It is a lot easier to just use:

      my $now= Win32::GetTickCount();

      which is just built-in to Win32 perls.

      Note that tick counts wrap, so you need to have your math wrap and, if the user has been idle for 50 days, they will appear not idle again.

      If you are sure that your Perl isn't built to use 64-bit integers, then you can get the math to wrap with:

      my $ticks= do { use integer; Win32::GetTickCount() - $time };

      but that will show the user as not being idle for another 25 days into the future once they've been idle for 25 days.

      Better is probably something like:

      my $ticks= Win32::GetTickCount() - $time; $ticks += ~0 if $ticks < 0;

      Or replace ~0 with 0xffffffff if you might have a 64-bit version of Perl.

      - tye        

      Thanks - this does seem like the best way at the moment.
Re: Detect if Windows screensaver is running or screen is locked (Lock Computer)
by cdarke (Prior) on Aug 07, 2006 at 10:23 UTC
    General performance data is held in the volatile registry hive HKEY_PERFORMANCE_DATA, which I suggest you google for more info.
    There are quite a few network monitors available, like MRTG for example.
Re: Detect if Windows screensaver is running or screen is locked (Lock Computer)
by bart (Canon) on Sep 14, 2006 at 06:29 UTC
    I'm not convinced it's the best way to achieve your goal (I think Corion's is more useful), but there is a way to ask the Windows API if the screen saver is running: using the SystemParametersInfo API call, with the proper function selected using the constant SPI_GETSCREENSAVEACTIVE. I seem to recall that some of these functions (in particular, SPI_SETSCREENSAVEACTIVE) doesn't work, or work that well on XP. So I'm not sure that this function will still work.