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 ;-)

LVL 27
kretzschmarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Wim ten BrinkSelf-employed developerCommented:
No... Because all applications can just grab the contents of the screen whenever they want.
You could try to capture the PrintScreen button but an application like Paint Shop Pro doesn't use that key anyways.
0
kretzschmarAuthor Commented:
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 ;-)
0
Wim ten BrinkSelf-employed developerCommented:
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. :-)
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

kretzschmarAuthor Commented:
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 ;-)
0
Wim ten BrinkSelf-employed developerCommented:
I wonder if you would even ever get the desktop handle by hooking those API's. Besides, how would you know if the desktop is just drawn or captured? It doesn't matter which API you hook into. You need a way to determine if it is used to do a screen capture or just to update some window.
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...
0
BdLmCommented:
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?
0
kretzschmarAuthor Commented:
> 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 ;-)
0
BdLmCommented:
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.
0
Russell LibbySoftware Engineer, Advisory Commented:
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
0
BdLmCommented:
i think this should be a countermeasure against any spy software, correct?
0
kretzschmarAuthor Commented:
>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 ;-)
0
Wim ten BrinkSelf-employed developerCommented:
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
0
kretzschmarAuthor Commented:
>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 ;-)
0
Wim ten BrinkSelf-employed developerCommented:
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. ;-)
0
kretzschmarAuthor Commented:
good point, alex, i will try this next monday
0
kretzschmarAuthor Commented:
the debug option is disabled :-(
how to enable?
0
BdLmCommented:
hmm,
nobody interessed in coutermeasures for trojan hores working on screen
capture algorithms ?
http://www2.hig.no/~hannol/research/scits01p.pdf 
0
SaLzCommented:
I've found the best way 2 detect if the clipboard has change is it monitor it with this procedure below, this will capture any image that goes into the clipboard.

this detects and monitors the clipboard contents and replaces the contents to your hard drive.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, clipbrd, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
  private
    procedure ClipboardChanged(var message: TMessage); message WM_DRAWCLIPBOARD;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Procedure JPEG(FileName:String;Quality:Integer);
var
  bmp:TBitmap;
  Jpg:TJpegImage;
begin
  bmp:=TBitmap.Create;
  jpg:=TJpegImage.Create;
  try
    bmp.LoadFromClipBoardFormat(cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);
    Jpg.CompressionQuality:=Quality;
    Jpg.Assign(bmp);
    Jpg.SaveToFile(FileName);
  finally
    jpg.Free;
    bmp.Free;
  end;
end;

procedure TForm1.ClipboardChanged(var message: TMessage);
begin
  if Clipboard.HasFormat(CF_BITMAP) then begin
    Image1.Picture.Assign(Clipboard);
    JPEG('C:\1.jpg',strtoint('100'));
    beep;
    //u could put anything u want in here for an action.
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
SetClipboardViewer(Form1.Handle);
end;

end.


Sal.
0
SaLzCommented:
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.
0
Wim ten BrinkSelf-employed developerCommented:
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. ;-)
0
kretzschmarAuthor Commented:
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 ;-)
0
gandalf_the_whiteCommented:
maybe you could block the ip adress(es) that connects to you with the remote software?
0
kretzschmarAuthor Commented:
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?
0
Russell LibbySoftware Engineer, Advisory Commented:

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.

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20997952.html

If you think this would be useful for you, I could re-tool the code to handle your situation

Regards,
Russell
0
kretzschmarAuthor Commented:
>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 ;-)
0
Russell LibbySoftware Engineer, Advisory Commented:

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: LongWord): String;
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) do
        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(lpTable^.Table[dwCount].dwLocalPort),
                   ' , ',
                   TcpAddrFromLong(lpTable^.Table[dwCount].dwLocalAddr),
                   ' , ',
                   TcpStateDescription(lpTable^.Table[dwCount].dwState));

           // Example of closing a tcp port/connection
           // - check for a connection to a remote port 80 (http) and close it
           if (TcpPortFromLong(lpTable^.Table[dwCount].dwRemotePort) = 80) then
              TcpDeleteRow(@lpTable^.Table[dwCount]);
        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: LongWord): String;
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_STATE_DELETE_TCB;
     // Call SetTcpEntry
     result:=SetTcpEntry(TcpRow);
  end
  else
     // Invalid param
     result:=ERROR_INVALID_PARAMETER;

end;

function TcpStateDescription(State: LongWord): String;
begin

  // Handle state
  if State in [MIB_TCP_STATE_CLOSED..MIB_TCP_STATE_DELETE_TCB] then
     // Return state description
     result:=MIB_TCP_STATES[State]
  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)) to High(lpBytes) do result:=result+'.'+IntToStr(lpBytes[dwIndex]);

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(TcpTable, @dwSize, True);

  // Check for insuffecient buffer
  if (result = ERROR_INSUFFICIENT_BUFFER) then
  begin
     // Re-alloc the table
     ReAllocMem(TcpTable, dwSize);
     // Call the function again
     result:=GetTcpTable(TcpTable, @dwSize, True);
  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(lpTcpTable, lpdwSize, bOrder)
  else
     // Function was not bound
     result:=ERROR_PROC_NOT_FOUND;

end;

function SetTcpEntry(lpTcpRow: PTcpRow): DWORD;
begin

  // Make sure the api function was bound
  if Assigned(@_SetTcpEntry) then
     // Call the function
     result:=_SetTcpEntry(lpTcpRow)
  else
     // Function was not bound
     result:=ERROR_PROC_NOT_FOUND;

end;

initialization

  // Load the ip helper api library
  hIphlp:=LoadLibrary(LIB_IPHLPAPI);

  // Attempt to get the function addresses
  if (hIphlp > 0) then
  begin
     // Bind both the get table and set entry functions
     @_GetTcpTable:=GetProcAddress(hIpHlp, FUNC_GETTCPTABLE);
     @_SetTcpEntry:=GetProcAddress(hIpHlp, FUNC_SETTCPENTRY_NAME);
  end;

finalization

  // Clear bound functions
  @_GetTcpTable:=nil;
  @_SetTcpEntry:=nil;

  // Free the ip helper api library
  if (hIphlp > 0) then FreeLibrary(hIphlp);

end.
0
kretzschmarAuthor Commented:
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 ;-)
0
kretzschmarAuthor Commented:
sorry, got no time during weekend :-( -> so no problems yet :-)
0
Russell LibbySoftware Engineer, Advisory Commented:
Take your time, no rush from this end...

Russell
0
SaLzCommented:
lol
0
MadshiCommented:
> usual i'm interested for solutions for
> DameWare Mini RemoteControl
> Tivoli RemoteControl
> pcAnyWhere

If you can limit your program to restrict only those products, then it should be not too difficult to realize - as long as those programs really do just screenshots (more about this later). You could inject a dll system wide and hook the APIs "CreateDC" and "GetDC". If you find that they're called to get a DC handle to the whole screen, return 0 and fill SetLastError with ERROR_ACCESS_DENIED. If you limit this to the 3 mentioned programs, you should be safe. Probably everything will work as usual. Maybe these 3 programs will crash, or they will return garbage or they will properly complain, depending on how clean they deal with the unexpected API call failure.

I'm not sure whether PcAnywhere uses simple screenshots, though. I think they also use a GDI mirror driver, so that they get notification about new painting operations. So I'm not sure whether my suggestion above fully works.

Maybe my suggestion even works for all programs. I'm not sure. You should do some serious testing before deciding to drop the restriction to those 3 programs.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
MadshiCommented:
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.
0
kretzschmarAuthor Commented:
good point, madshi, but how do i this?

seems this question extends 500 pts ;-)
0
MadshiCommented:
By using madCodeHook, of course!   :-)   Hooking an API is really easy that way...
0
kretzschmarAuthor Commented:
>By using madCodeHook, of course!
how could i this forget :-))
0
SaLzCommented:
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.
0
MadshiCommented:
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.
0
SaLzCommented:
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?
0
MadshiCommented:
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).
0
kretzschmarAuthor Commented:
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 ;-)
0
kretzschmarAuthor Commented:
0
DragonSlayerCommented:
Meikl: hope i get no problem with the PE ;-)

rofl... heheheheheh....
0
TvigepCommented:
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...
0
kretzschmarAuthor Commented:
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 ;-)
0
TvigepCommented:
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
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.