kretzschmar
asked on
Any way to detect if a screencapture (snapshot) is done?
Any way to detect if a screencapture (snapshot) is done?
and if possible, to replace the screenshot with another graphic?
scenario:
any software makes screenshots in a periodical intervall
i like to
- detect this
- replace the content of the shot on the fly
any ideas?
meikl ;-)
and if possible, to replace the screenshot with another graphic?
scenario:
any software makes screenshots in a periodical intervall
i like to
- detect this
- replace the content of the shot on the fly
any ideas?
meikl ;-)
ASKER
thanks for your response, alex
i guessed that also.
but i thought there may be a possibility to watch/hook/inject
about an access to the desktop-canvas
any further suggestions?
meikl ;-)
i guessed that also.
but i thought there may be a possibility to watch/hook/inject
about an access to the desktop-canvas
any further suggestions?
meikl ;-)
Well, perhaps you could hook into some Windows API's but if I think about Paint Shop Pro and it's ability to not just capture the whole screen but also just a part of the screen, or a window or even a button then I'm not sure it will work all the times. Besides, it could even be that some of those screen capture applications disable those kinds of hooks, but I'm not sure about that. Some screen capture tools are doing quite complicated things when you make a screenshot. :-)
ASKER
usually i thought about to hook the GetDC and/or GetWindowDC - api
and compare the given handle with the desktop handle,
if it match i would return a dc from a bitmap canvas
sounds hazardous, or?
meikl ;-)
and compare the given handle with the desktop handle,
if it match i would return a dc from a bitmap canvas
sounds hazardous, or?
meikl ;-)
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
isn't it enough to replace the bitblt function within the WIN-API as such kind of program will copy the screen content to a bitmap and send it to a remote host?
My idea: write some signature(pattern) to the screen and check all outgoing data packages for this pattern,
will this work?
My idea: write some signature(pattern) to the screen and check all outgoing data packages for this pattern,
will this work?
ASKER
> how would you know if the desktop is just drawn or captured?
well, thats unknown
>Another risk could be that you would slow down your system considerably because with >every screen update, you would have to check for update or capture...
yep, thats an issue to avoid partial
>isn't it enough to replace the bitblt function within the WIN-API
would be an idea too, but there are also other function like StretchBlt
>write some signature(pattern) to the screen and check all outgoing data packages for >this pattern, will this work?
the pattern maybe due compression or image-format change lost
any further suggestions?
meikl ;-)
well, thats unknown
>Another risk could be that you would slow down your system considerably because with >every screen update, you would have to check for update or capture...
yep, thats an issue to avoid partial
>isn't it enough to replace the bitblt function within the WIN-API
would be an idea too, but there are also other function like StretchBlt
>write some signature(pattern) to the screen and check all outgoing data packages for >this pattern, will this work?
the pattern maybe due compression or image-format change lost
any further suggestions?
meikl ;-)
what about a statistical analysis of the outgoing data bytes of the machine, you should see some peaks?
and a peak change correlated to the screen change.
and a peak change correlated to the screen change.
Meikl,
Perhaps this problem could be tackled from another angle? (the angle you are proposing is nearly impossible to handle correctly)
Is it a case where you are trying to circumvent a certain program, or group of programs? If so, it may be easier to work that angle. Maybe with a little more info the others here can provide alternative ideas that would suit your needs.
Regards,
Russell
Perhaps this problem could be tackled from another angle? (the angle you are proposing is nearly impossible to handle correctly)
Is it a case where you are trying to circumvent a certain program, or group of programs? If so, it may be easier to work that angle. Maybe with a little more info the others here can provide alternative ideas that would suit your needs.
Regards,
Russell
i think this should be a countermeasure against any spy software, correct?
ASKER
>Is it a case where you are trying to circumvent a certain program, or group of
>programs? If so, it may be easier to work that angle.
usual i'm interested for solutions for
DameWare Mini RemoteControl
Tivoli RemoteControl
pcAnyWhere
>i think this should be a countermeasure against any spy software, correct?
well, as above most remotecontrols, but a general solution would be nice
meikl ;-)
>programs? If so, it may be easier to work that angle.
usual i'm interested for solutions for
DameWare Mini RemoteControl
Tivoli RemoteControl
pcAnyWhere
>i think this should be a countermeasure against any spy software, correct?
well, as above most remotecontrols, but a general solution would be nice
meikl ;-)
Wait... You don't want your Boss to see the bikini girl you use as desktop background when he has remote access to your system, right? :-P
ASKER
>Wait... You don't want your Boss to see the bikini girl you use as desktop background
>when he has remote access to your system, right? :-P
usual i have no problem with my boss, its more the young administartors (outsourced IT),
which taking itself too important, and i dislike if someone is lurking over my shoulder ;-)
(usual i notice this by jumping mousecursor and popupping a background window, so
some big brother is watching me, very annoying)
meikl ;-)
>when he has remote access to your system, right? :-P
usual i have no problem with my boss, its more the young administartors (outsourced IT),
which taking itself too important, and i dislike if someone is lurking over my shoulder ;-)
(usual i notice this by jumping mousecursor and popupping a background window, so
some big brother is watching me, very annoying)
meikl ;-)
Just kill the process that would allow them to access your system remotely in that case. That's a lot easier.
I have never been bothered by young administrators anyway since I just don't allow them access to my system when I need all it's resources to develop software. No administrator is allowed to peek remotely on my system because that would invalidate the performance tests that I need to do quite often. :-)
One nice trick to kill unwanted processes is quite simple, btw. Start the task manager and right-click the unwanted process. Then attach the debugger (!!) and once the debugger is attached, you own the process and can kill it by closing the debugger. It is what I sometimes used to kill a background task that kept making a full backup of my system every day. The administrator was so frustrated after a while because it kept "crashing" on my system that they finally decided to use a better back-up system, that would make backups during the night when I wasn't using the system. ;-)
I have never been bothered by young administrators anyway since I just don't allow them access to my system when I need all it's resources to develop software. No administrator is allowed to peek remotely on my system because that would invalidate the performance tests that I need to do quite often. :-)
One nice trick to kill unwanted processes is quite simple, btw. Start the task manager and right-click the unwanted process. Then attach the debugger (!!) and once the debugger is attached, you own the process and can kill it by closing the debugger. It is what I sometimes used to kill a background task that kept making a full backup of my system every day. The administrator was so frustrated after a while because it kept "crashing" on my system that they finally decided to use a better back-up system, that would make backups during the night when I wasn't using the system. ;-)
ASKER
good point, alex, i will try this next monday
ASKER
the debug option is disabled :-(
how to enable?
how to enable?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
u know that if u could replace a ss with an image on your hd, then in effect, print screen is a myth, this idea could work for Anti-Cheat Programs for games, when an Anti-Cheat program take a SS of your screen and sends it to the master server, the delphi program will say hey, ur not taking a snap of this desktop, u can have this snap from my hard drive instead.
pritty good idea.
Sal.
pritty good idea.
Sal.
Awww. No debug option. You have a smart administrator... :) Mine wasn't that smart. He did notice the application crashing all the time so he blamed it to the application. (Especially after I've sold a few collegues how to disable it, because then the "problem" occurred on several systems.)
Maybe it works if you install MS Visual Studio on your system or at least the debugger from VS.
@Sal, responding to clipboard changes won't work since screen capture applications just don't use the clipboard to capture screenshots. The problem here is that Meikl doesn't want someone else looking at his desktop by using some remote tool. Responding to the print screen key won't work either. These capture programs just ask the system do draw a screenshot on some device that is NOT the desktop. Thus you need to approach the problem at the root, which happens to be at API level or even lower. It would have been nice if there was a way to disable those sneaky applications that try to capture the screen.
But I wonder... If you can replace API functions within Windows, then perhaps you can alter them for a single process. Maybe the solution to disable those spies is by just injecting some DLL within their process space that will make them crash. Not a nice way, but no application will continue to run after an unhandled exception. Maybe it's enough to capture one specific API call for these processes and make it fail, thus bringing it completely down.
Also gives you a reason to complain about your administrator because every time he tries to spy on your system, some part of it just crashes and it is caused by his spying software. ;-)
Maybe it works if you install MS Visual Studio on your system or at least the debugger from VS.
@Sal, responding to clipboard changes won't work since screen capture applications just don't use the clipboard to capture screenshots. The problem here is that Meikl doesn't want someone else looking at his desktop by using some remote tool. Responding to the print screen key won't work either. These capture programs just ask the system do draw a screenshot on some device that is NOT the desktop. Thus you need to approach the problem at the root, which happens to be at API level or even lower. It would have been nice if there was a way to disable those sneaky applications that try to capture the screen.
But I wonder... If you can replace API functions within Windows, then perhaps you can alter them for a single process. Maybe the solution to disable those spies is by just injecting some DLL within their process space that will make them crash. Not a nice way, but no application will continue to run after an unhandled exception. Maybe it's enough to capture one specific API call for these processes and make it fail, thus bringing it completely down.
Also gives you a reason to complain about your administrator because every time he tries to spy on your system, some part of it just crashes and it is caused by his spying software. ;-)
ASKER
well,
thanks for all comments, seems there is no easy to implement solution ;-)
i will share the points equal to all participants.
is this ok for you?
meikl ;-)
thanks for all comments, seems there is no easy to implement solution ;-)
i will share the points equal to all participants.
is this ok for you?
meikl ;-)
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
would be an idea too, but this may detected, and i don't know how to block a port
(btw. i know the ports)
any who knows to block a port?
(btw. i know the ports)
any who knows to block a port?
Well, there is a way to get the tcp table (very quickly) and to forcefully close any given connection. This would allow you to effectively close the communication channel that the remote software has established with your computer.
Take a look at the following paq.
https://www.experts-exchange.com/questions/20997952/blocking-internet-connections.html
If you think this would be useful for you, I could re-tool the code to handle your situation
Regards,
Russell
ASKER
>I could re-tool the code to handle your situation
would be great, russell, its a thematic that was out of my focus,
so i guess it would be hard and therefore time expensive for me
to re-tool the code
meikl ;-)
would be great, russell, its a thematic that was out of my focus,
so i guess it would be hard and therefore time expensive for me
to re-tool the code
meikl ;-)
Meikl,
I'm sure that you could have worked the code to fit yuor situation, but I figured I would save you the time. Here is a re-coding of the tcp table handling so its a little more generic, and can be used as a set of function calls. There are only a few functions, so the learning curve is pretty low
function TcpOpenEnum(var TcpTable: PTcpTable): DWORD;
procedure TcpCloseEnum(TcpTable: PTcpTable);
function TcpPortFromLong(Port: LongWord): Word;
function TcpAddrFromLong(Address: LongWord): String;
function TcpStateDescription(State:
function TcpDeleteRow(TcpRow: PTcpRow): DWORD;
An example of using all functions:
var lpTable: PTcpTable;
dwCount: Integer;
begin
// Retrieve the table of tcp entries
if (TCPOpenEnum(lpTable) = ERROR_SUCCESS) then
begin
// Resource protection
try
// Walk the table entries
for dwCount:=0 to Pred(lpTable^.dwNumEntries
begin
// Write out
// - the local port (in common format, vs network order)
// - the local address (in string format)
// - the descriptive state of the tcp entry
WriteLn(TcpPortFromLong(lp
' , ',
TcpAddrFromLong(lpTable^.T
' , ',
TcpStateDescription(lpTabl
// Example of closing a tcp port/connection
// - check for a connection to a remote port 80 (http) and close it
if (TcpPortFromLong(lpTable^.
TcpDeleteRow(@lpTable^.Tab
end;
finally
// Free the memory allocated by the open enum function
TCPCloseEnum(lpTable);
end;
end;
end;
And finally, the source for it all.
Let me know if you run into questions/problems,
Russell
--------
unit TcpApi;
//////////////////////////
//
// Unit : TCPAPI
// Date : Original - 05.25.2004
// Updated - 11.12.2004
// Author : rllibby
//
// Description : Set of TCP enumeration and helper routines.
//
//////////////////////////
interface
//////////////////////////
// Include units
//////////////////////////
uses
Windows,
SysUtils;
//////////////////////////
// General constants
//////////////////////////
const
ALLOC_SIZE = 4096;
//////////////////////////
// Data structures
//////////////////////////
type
PMIB_TCPROW = ^MIB_TCPROW;
MIB_TCPROW = packed record
dwState: LongWord;
dwLocalAddr: LongWord;
dwLocalPort: LongWord;
dwRemoteAddr: LongWord;
dwRemotePort: LongWord;
end;
TTcpRow = MIB_TCPROW;
PTcpRow = ^TTcpRow;
PMIB_TCPTABLE = ^MIB_TCPTABLE;
MIB_TCPTABLE = packed record
dwNumEntries: LongWord;
Table: Array [0..MaxWord] of MIB_TCPROW;
end;
TTcpTable = MIB_TCPTABLE;
PTcpTable = ^TTcpTable;
PIP_BYTES = ^IP_BYTES;
IP_BYTES = Array [0..3] of Byte;
TIpBytes = IP_BYTES;
PIpBytes = ^TIpBytes;
//////////////////////////
// Function definitions
//////////////////////////
type
TGetTcpTable = function(lpTcpTable: PTcpTable; lpdwSize: PDWORD; bOrder: BOOL): DWORD; stdcall;
TSetTcpEntry = function(lpTcpRow: PTcpRow): DWORD; stdcall;
//////////////////////////
// TCP table entry state constants
//////////////////////////
const
MIB_TCP_STATE_CLOSED = 1;
MIB_TCP_STATE_LISTEN = 2;
MIB_TCP_STATE_SYN_SENT = 3;
MIB_TCP_STATE_SYN_RCVD = 4;
MIB_TCP_STATE_ESTAB = 5;
MIB_TCP_STATE_FIN_WAIT1 = 6;
MIB_TCP_STATE_FIN_WAIT2 = 7;
MIB_TCP_STATE_CLOSE_WAIT = 8;
MIB_TCP_STATE_CLOSING = 9;
MIB_TCP_STATE_LAST_ACK = 10;
MIB_TCP_STATE_TIME_WAIT = 11;
MIB_TCP_STATE_DELETE_TCB = 12;
const
MIB_TCP_STATES: Array [0..12] of PChar =
('Unknown',
'Closed',
'Listening',
'Syn Sent',
'Syn Received',
'Established',
'Fin Wait1',
'Fin Wait2',
'Close Wait',
'Closing',
'Last Ack',
'Time Wait',
'Deleted');
//////////////////////////
// Late bound function wrappers
//////////////////////////
function GetTcpTable(lpTcpTable: PTcpTable; lpdwSize: PDWORD; bOrder: BOOL): DWORD; stdcall;
function SetTcpEntry(lpTcpRow: PTcpRow): DWORD; stdcall;
//////////////////////////
// TCP functions designed to be used by developers
//////////////////////////
function TcpOpenEnum(var TcpTable: PTcpTable): DWORD;
procedure TcpCloseEnum(TcpTable: PTcpTable);
function TcpPortFromLong(Port: LongWord): Word;
function TcpAddrFromLong(Address: LongWord): String;
function TcpStateDescription(State:
function TcpDeleteRow(TcpRow: PTcpRow): DWORD;
implementation
//////////////////////////
// Library and function name constants
//////////////////////////
const
LIB_IPHLPAPI = 'iphlpapi.dll';
FUNC_GETTCPTABLE = 'GetTcpTable';
FUNC_SETTCPENTRY_NAME = 'SetTcpEntry';
//////////////////////////
// Protected variables
//////////////////////////
var
hIphlp: HMODULE = 0;
_GetTcpTable: TGetTcpTable = nil;
_SetTcpEntry: TSetTcpEntry = nil;
function TcpDeleteRow(TcpRow: PTcpRow): DWORD;
begin
// Check assignment
if Assigned(TcpRow) then
begin
// Set entry state
TcpRow^.dwState:=MIB_TCP_S
// Call SetTcpEntry
result:=SetTcpEntry(TcpRow
end
else
// Invalid param
result:=ERROR_INVALID_PARA
end;
function TcpStateDescription(State:
begin
// Handle state
if State in [MIB_TCP_STATE_CLOSED..MIB
// Return state description
result:=MIB_TCP_STATES[Sta
else
// Unknown state
result:=MIB_TCP_STATES[0];
end;
function TcpAddrFromLong(Address: LongWord): String;
var lpBytes: TIpBytes;
dwIndex: Integer;
begin
// Move dword to byte array
Move(Address, lpBytes, SizeOf(LongWord));
// Set start of string
result:=IntToStr(lpBytes[0
// Walk remaining bytes
for dwIndex:=Succ(Low(lpBytes)
end;
function TcpPortFromLong(Port: LongWord): Word;
begin
// Convert from network order to common port format
result:=(Port div 256) + (Port mod 256) * 256;
end;
function TcpOpenEnum(var TcpTable: PTcpTable): DWORD;
var dwSize: DWORD;
begin
// Set the default size, this is enough to hold appx 204 entries
dwSize:=ALLOC_SIZE;
// Allocate memory
TcpTable:=AllocMem(dwSize)
// Attempt to get the full tcp table
result:=GetTcpTable(TcpTab
// Check for insuffecient buffer
if (result = ERROR_INSUFFICIENT_BUFFER)
begin
// Re-alloc the table
ReAllocMem(TcpTable, dwSize);
// Call the function again
result:=GetTcpTable(TcpTab
end;
// Check result
if (result <> ERROR_SUCCESS) then
begin
// Failed to get table, cleanup allocated memory
FreeMem(TcpTable);
// Clear the table
TcpTable:=nil;
end;
end;
procedure TcpCloseEnum(TcpTable: PTcpTable);
begin
// Need to free the memory allocated by a call to open enum
if Assigned(TcpTable) then FreeMem(TcpTable);
end;
function GetTcpTable(lpTcpTable: PTcpTable; lpdwSize: PDWORD; bOrder: BOOL): DWORD;
begin
// Make sure the api function was bound
if Assigned(@_GetTcpTable) then
// Call the function
result:=_GetTcpTable(lpTcp
else
// Function was not bound
result:=ERROR_PROC_NOT_FOU
end;
function SetTcpEntry(lpTcpRow: PTcpRow): DWORD;
begin
// Make sure the api function was bound
if Assigned(@_SetTcpEntry) then
// Call the function
result:=_SetTcpEntry(lpTcp
else
// Function was not bound
result:=ERROR_PROC_NOT_FOU
end;
initialization
// Load the ip helper api library
hIphlp:=LoadLibrary(LIB_IP
// Attempt to get the function addresses
if (hIphlp > 0) then
begin
// Bind both the get table and set entry functions
@_GetTcpTable:=GetProcAddr
@_SetTcpEntry:=GetProcAddr
end;
finalization
// Clear bound functions
@_GetTcpTable:=nil;
@_SetTcpEntry:=nil;
// Free the ip helper api library
if (hIphlp > 0) then FreeLibrary(hIphlp);
end.
ASKER
many thanks, russell, you save my rare time ;-)
i will code a little frontend to your unit tomorrow,
and if i run into problems, then i will post it here
meikl ;-)
i will code a little frontend to your unit tomorrow,
and if i run into problems, then i will post it here
meikl ;-)
ASKER
sorry, got no time during weekend :-( -> so no problems yet :-)
Take your time, no rush from this end...
Russell
Russell
lol
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
P.S: Probably instead of returning 0 you could also return a fake DC. This should avoid crashes, as long as the DC behaves just like the screen DC would.
ASKER
good point, madshi, but how do i this?
seems this question extends 500 pts ;-)
seems this question extends 500 pts ;-)
By using madCodeHook, of course! :-) Hooking an API is really easy that way...
ASKER
>By using madCodeHook, of course!
how could i this forget :-))
how could i this forget :-))
madshi, could u tell me this, is it possible to hook your application into another application when the other application starts?
so if someone clicks on another program lets say notepad for an example, if they start up notepad as normal with a shortcut or a direct execute, could u have hooked your app so it will start up along side notepad and close with notepad when notepad is closed? so it opens and closes along side notepad or any other application?
if so, and u know how to do this, I'll make a 500point question on this and send u the link.
Sal.
so if someone clicks on another program lets say notepad for an example, if they start up notepad as normal with a shortcut or a direct execute, could u have hooked your app so it will start up along side notepad and close with notepad when notepad is closed? so it opens and closes along side notepad or any other application?
if so, and u know how to do this, I'll make a 500point question on this and send u the link.
Sal.
Sal, there are multiple ways to do it. But most of them require you to run your own program (or a part of your program) before Notepad starts, so that you can detect when Notepad is loaded. Probably you don't like that. In that case you could try to rename Notepad.exe to Notepad2.exe and put your own exe as Notepad.exe. But I'm not sure what the system file protection will say about this.
ya, that way seems the only way at the moment, replace your app with the apps name and swap them around when user clicks on it and both load up.
like with, anti-cheats, they use a wrapper, so when the app loads your app loads up, gives u an option to start in ac mode or normal mode.
can this be done in the same way to a normal app?
like with, anti-cheats, they use a wrapper, so when the app loads your app loads up, gives u an option to start in ac mode or normal mode.
can this be done in the same way to a normal app?
Well, probably that's exactly what the wrapper does, namely simply replacing the app names. Maybe additionally encrypting/decrypting the original exe. But let's not hijack meikl's thread here. That's another topic and doesn't really belong here... Anyway, there's not really more I can say about this, so perhaps we should just stop here now. (No needs to give me points for what I said until now).
ASKER
well, thanks to all, time to close this thread
i will split the points equal to all participants
(because this q isn't really solveable)
except for rllibby
for rllibby i will post an additional q (for blocking ports)
(hope i get no problem with the PE ;-)) and the mods,
because exciting 500 pts, but i do argument that this solution,
isn't a solution for this q)
meikl ;-)
i will split the points equal to all participants
(because this q isn't really solveable)
except for rllibby
for rllibby i will post an additional q (for blocking ports)
(hope i get no problem with the PE ;-)) and the mods,
because exciting 500 pts, but i do argument that this solution,
isn't a solution for this q)
meikl ;-)
ASKER
rllibby,
please collect your points at
https://www.experts-exchange.com/questions/21219913/for-rllibby-close-ports.html
meikl ;-)
please collect your points at
https://www.experts-exchange.com/questions/21219913/for-rllibby-close-ports.html
meikl ;-)
Meikl: hope i get no problem with the PE ;-)
rofl... heheheheheh....
rofl... heheheheheh....
Meikl,
I've had the same issue: I don't like others looking over my shoulder as well. What I did is a wee bit simpler though: I wrote a small little app that runs LoggedOn.exe from www.sysinternals.com. This little gem shows you all users logged on to your machine locally and remotely. The little shell I wrote around it uses a timer to check every 5 seconds who is logged on, and if the list (usually it's only me) changes it shows an alert, pops to the foreground and shows the list of users. So I know within 5 seconds when somebody else is on my machine, you could even set the timer faster if you want (it doesn't use much in the way of CPU/memory).
Maybe that does what you want? You could easily set it to block all network trafficv instead of popping up a message, for example.
Regards,
Stefan
PS. I know the question is already closed, but still wanted to contribute this approach. IMHO a lot easier...
I've had the same issue: I don't like others looking over my shoulder as well. What I did is a wee bit simpler though: I wrote a small little app that runs LoggedOn.exe from www.sysinternals.com. This little gem shows you all users logged on to your machine locally and remotely. The little shell I wrote around it uses a timer to check every 5 seconds who is logged on, and if the list (usually it's only me) changes it shows an alert, pops to the foreground and shows the list of users. So I know within 5 seconds when somebody else is on my machine, you could even set the timer faster if you want (it doesn't use much in the way of CPU/memory).
Maybe that does what you want? You could easily set it to block all network trafficv instead of popping up a message, for example.
Regards,
Stefan
PS. I know the question is already closed, but still wanted to contribute this approach. IMHO a lot easier...
ASKER
sounds interested, could you post the source here or forward me via email
(email is found in my profiole, just click on my name)
of course i will spent some points for you then
meikl ;-)
(email is found in my profiole, just click on my name)
of course i will spent some points for you then
meikl ;-)
Sorry, I don't have the code here on my workmachine (I'm at the office now). Basically I had downloaded LoggedOn.exe from SysInternals, which is a little utility listing all users logged on to your machine. It is a little command line utility, now part of the PsTools suite. It can still be downloaded for free from http://www.sysinternals.com/ntw2k/freeware/psloggedon.shtml. I then simply wrote a little delphi interface around it, which on a timer event executed the app with a hidden window, redirecting the output to a text file. I then read the text file from my little shell and compare it with a previous list. So there's very little coding that I've done myself, the real engine behind it is from Mark Russinovich (Thanks Mark!).
You will always see yourself logged on, and if you browse to Windows Network, and find your own computer, then display a share in the explorer on your machine you will even see yourself twice in the list: once Locally and once with your domain name. SysInternals used to make the code available as well, but it is C++. Checking their site they have renewed it, for Win2K: http://www.sysinternals.com/ntw2k/source/misc.shtml#logonsessions.
HTH,
Stefan
You will always see yourself logged on, and if you browse to Windows Network, and find your own computer, then display a share in the explorer on your machine you will even see yourself twice in the list: once Locally and once with your domain name. SysInternals used to make the code available as well, but it is C++. Checking their site they have renewed it, for Win2K: http://www.sysinternals.com/ntw2k/source/misc.shtml#logonsessions.
HTH,
Stefan
You could try to capture the PrintScreen button but an application like Paint Shop Pro doesn't use that key anyways.