PDA

Ver la Versión Completa : Capturar imagen de ventana inactiva


look
31-12-2013, 15:20:05
Hola amigos, estoy desarrollando un pequeño programa para control remoto, tengo una aplicacion cliente y una server, la aplicacion cliente manda una peticion cada segundo al servidor y este le manda al cliente una imagen de una ventana todo esto por medio de sockets, esto funcionan bien, el problema es que al bloquear la sesion ("WIN+L") , la aplicacion cliente conecta bien pero de alguna manera la imagen de capatura que envia se vuelve en blanco, he probado con varias funciones para capturar la imagen pero creo que el problema no va por ahi, pareciera que al bloquear la sesion la ventana queda inactiva... :confused: .
lo que quiero hacer es que se puede capturar la imagen de la ventana aun bloqueada la session, me parece extraño ya que la aplicacion cliente conecta bien con la aplicacion server. :(

procedure ScreenShot(activeWindow: bool; destBitmap : TBitmap ; hWin : Cardinal) ;
var
w,h : integer;
DC : HDC;
r : TRect;
begin
if activeWindow then
begin
hWin := GetForegroundWindow;
hWin := GetForegroundWindow;
dc := GetWindowDC(hWin) ;
GetWindowRect(hWin,r) ;
w := r.Right - r.Left;
h := r.Bottom - r.Top;
end
else
begin
hWin := GetDesktopWindow;
dc := GetDC(hWin) ;
w := GetDeviceCaps (DC, HORZRES) ;
h := GetDeviceCaps (DC, VERTRES) ;
end;
try
destBitmap.Width := w;
destBitmap.Height := h;
BitBlt(destBitmap.Canvas.Handle,
0,
0,
destBitmap.Width,
destBitmap.Height,
DC,
0,
0,
SRCCOPY) ;
finally
ReleaseDC(hWin, DC) ;
end;
end;

ecfisa
31-12-2013, 17:54:20
Hola look.

Tal vez te sirva impedir el bloqueo durante la duración de tu programa 'cliente' y restaurar la condición al finalizar, algo como:

implementation

uses Registry;

var
PrevLockState: Boolean;

function LockWorkstationState: Boolean;
var
r: TRegistry;
begin
Result := False;
with TRegistry.Create do
try
RootKey := HKEY_CURRENT_USER;
if OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System', False) then
begin
Result := Boolean(ReadInteger('DisableLockWorkstation'));
CloseKey;
end;
finally
Free;
end;
end;

procedure DisableLockWorkstation(Lock: Boolean);
begin
with TRegistry.Create do
try
RootKey := HKEY_CURRENT_USER;
if OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System', True) then
begin
WriteInteger('DisableLockWorkstation', Integer(Lock));
CloseKey;
end;
finally
Free;
end;
end;

procedure TfrmClienteMain.FormCreate(Sender: TObject);
begin
PrevLockState := LockWorkstationState;
DisableLockWorkstation(True);
...
end;

...

procedure TfrmClienteMain.FormDestroy(Sender: TObject);
begin
DisableLockWorkstation(PrevLockState);
...
end;


Saludos :)

look
31-12-2013, 18:23:54
Hola look.

Tal vez te sirva impedir el bloqueo durante la duración de tu programa 'cliente' y restaurar la condición al finalizar, algo como:


Saludos :)

Hola amigo, ya habia pensado algo como eso, de esa manera funciona bien, en mi caso lo que quiero monitorear es un servidor, el la aplicacion permite embeber a otra para que otros usuarios no tengan acceso total al servidor utilizando la aplicacion cliente, todo funciona de maravilla, pero el problema es que al bloquear la session el servidor ya deja de funcionar la captura solamente, si me conecto por remotdestktop al servidor y cierro la ventana del del remot desktop el servidor se queda con la ventana del login, es por eso que se me ocurrio si hay alguna manera de capturar la imagen de una ventana en particular aunque la session de windows este en modo lock y la aplicacion este corriendo en el background la aplicacion cliente se comunica bien con el servidor aunque este en modo lock pero no obtengo la captura. :o

look
02-01-2014, 15:02:13
hola, parece complicado no, se me ocurre que tel vez si la misma aplicacion pudiera iniciar session en windows cuando el cliente se conecte esto permitiria que trabajara bien, ¿ sera posible esto?, ¿iniciar session desde mi aplicacion en windows sabiendo el usuario y clave?

escafandra
02-01-2014, 21:22:55
Cuando una sesión es bloqueada, el sistema cambia de escritorio por lo que es imposible interactuar desde una aplicación que corre como otro usuario que no sea system. En WinXp si tu App corre como system puede cambiar al nuevo escritorio y capturar la pantalla de bloqueo. Si estás simulando entradas de teclado y ratón puedes iniciar o desbloquear la sesión en cuestión.

Saludos.

escafandra
03-01-2014, 17:27:50
Para documentar con código lo que expuse anteriormente propongo una función para apropiarse del escritorio que usa el sistema por defecto en un momento dado:


const WINSTA_ALL_ACCESS = $37F;
procedure SetDefaultWSDesktop;
var
hWSTA: HWINSTA;
hDSK: HDESK;
begin
// Me asigno la estación de ventana y el escritorio por defecto
hWSTA:= OpenWindowStation('winsta0', true, WINSTA_ALL_ACCESS);
if hWSTA<>0 then
if SetProcessWindowStation(hWSTA) then CloseWindowStation(hWSTA);

hDSK:= OpenInputDesktop(0, true, GENERIC_ALL);
if hDSK <> 0 then
if SetThreadDesktop(hDSK) then CloseDesktop(hDSK);
end;


A la hora de capturar conviene antes repetir la secuencia:

var
hDSK: HDESK;
begin
hDSK:= OpenInputDesktop(0, true, GENERIC_ALL);
if hDSK <> 0 then
if SetThreadDesktop(hDSK) then CloseDesktop(hDSK);
......


Tu aplicación residente en el PC remoto deberá ser un servicio, como forma más fácil de correr como SYSTEM, pero con la dificultad de acceder al GUI. También podrá ser una simple App que se lance desde un servicio, por lo que será SYSTEM también.

Para completar, conviene revisar los siguientes enlaces Lanzar una aplicación GUI desde un servicio (http://www.delphiaccess.com/forum/index.php?topic=8376.msg70772#msg70772) y MiniSystem, una miniaplicación para ejecutar programas con privilegios SYSTEM (http://www.delphiaccess.com/forum/index.php?topic=5055.msg50985#msg50985), que te aclararan conceptos y te darán pautas para realizar lo que pretendes.


Saludos.

look
03-01-2014, 21:23:35
Para documentar con código lo que expuse anteriormente propongo una función para apropiarse del escritorio que usa el sistema por defecto en un momento dado:

Gracias amigo, voy a investigar sobre lo que mencionas.

Saludos!