Toon posts:

[win32] Screenshot nemen vanuit service

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met een soort remote desktop programma. Het server programma draait als Windows service. Een service draait niet op de gebruikersdesktop. Met de API calls OpenInputDesktop en SetThreadDesktop kan de service naar de actieve gebruikersdesktop (WinLogon, Default of ScreenSaver) geschakeld worden, waardoor screenshots genomen kunnen worden.

Maar nu het probleem. In Windows XP zit de mogelijkheid om snel over te schakelen van gebruikers. Er kunnen meerdere gebruikers ingelogd zijn. Het probleem is dat als de service draait (onder gebruikersnaam SYSTEM), dat de service zwart beeld krijgt als ik switch naar een andere gebruiker.

Heeft iemand een idee waar dit aan kan liggen? OpenInputDesktop en SetThreadDesktop gaan beide goed. Ik kan op internet ook geen informatie vinden van wat er nou precies gebeurd tijdens het overswitchen van een gebruiker. Tijdens het switchen wordt het scherm helemaal zwart en wordt het opgebouwd. Er gebeurd volgens mij meer dan een het veranderen van een desktop. Wordt er een ander window station actief?

Ik hoop dat iemand mij kan helpen. Ik maak het programma in Delphi, maar het gaat hier puur om API calls. Hulp in C++ of pseudo-code is ook welkom. Bedankt voor het meedenken.

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 06-03 20:19

_Thanatos_

Ja, en kaal

Misschien kun je door alle desktops wandelen met EnumDesktops en dan de desktop uitkiezen die je wil capturen?

日本!🎌


Verwijderd

Topicstarter
@_Thanatos_: Bedankt voor de tip. Ik heb het meteen geprobeerd. Ik loop eerst door alle window stations heen, en dan door alle desktops in die window stations. Ik schakel steeds naar die desktop en maak daar een screenshot van en sla deze op, en dit elke 5 seconden.

Als ik de service start krijg ik alleen beeld op window station "WinSta0" en desktop Default. Dit is normaal. Als ik dan Switch User klik, dan kom ik op WinLogon (gebruiker selecteren), ook op window station "WinSta0". Hier krijg ik dus ook beeld van. De service blijft dus draaien, en slaat ook allemaal bitmaps op van alle desktops van window stations, maar deze zijn allemaal zwart. Ik gebruik de volgende code, dat zou jij als Delphi programmeur moeten kunnen lezen.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
function SwitchToDesktop(Desktop: HDESK): Boolean; overload;
var
  OldDesktop: HDESK;
begin
  Result := False;
  if Desktop = 0 then
    Exit;

  OldDesktop := GetThreadDesktop(GetCurrentThreadId);
  if SetThreadDesktop(Desktop) then begin
    CloseDesktop(OldDesktop);
    Result := True;
  end;
end;

function SwitchToDesktop(const Name: string): Boolean; overload;
var
  Desktop: HDESK;
begin
  Result := False;
  Desktop := GetDesktopHDESK(Name);
  if SwitchToDesktop(Desktop) then
    Result := True
  else
    CloseDesktop(Desktop);
end;

function GetDesktopHDESK(Name: string): HDESK;
begin
  Result := OpenDesktop(PChar(Name), 0, False,
      DESKTOP_CREATEMENU or
      DESKTOP_CREATEWINDOW or
      DESKTOP_ENUMERATE or
      DESKTOP_HOOKCONTROL or
      DESKTOP_WRITEOBJECTS or
      DESKTOP_READOBJECTS or
      DESKTOP_SWITCHDESKTOP or
      GENERIC_WRITE);
end;

function EnumDesktopsProc(Name: PChar; lParam: LPARAM): Boolean; stdcall;
var
  WinStaName: string;
begin
  WinStaName := String(lParam);
  SwitchToDesktop(Name);

  CaptureScreen(Format('C:\%s - %s (%d).bmp', [WinStaName, Name, Count]));

  Result := True;
end;

function EnumWindowStationsProc(Name: PChar; lParam: LPARAM): Boolean; stdcall;
var
  WinSta: HWINSTA;
  S: string;
begin
  S := Name;
  WinSta := OpenWindowStation(Name, False, MAXIMUM_ALLOWED);
  EnumDesktops(WinSta, @EnumDesktopsProc, Integer(S));
  CloseWindowStation(WinSta);

  Result := True;
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
  while not Terminated do begin
    Sleep(5000);
    Inc(Count);

    EnumWindowStations(@EnumWindowStationsProc, 0);
  end;
end;


Alleen C:\WinSta0 - Default (x).bmp en C:\WinSta0 - WinLogon (x).bmp geven beeld.

[ Voor 27% gewijzigd door Verwijderd op 27-03-2005 16:15 ]


Verwijderd

Ik weet hier verder niks van, maar zou het niet kunnen dat het SYSTEM account waaronder de service draait simpelweg geen rechten heeft om het scherm van een bepaalde gebruiker te capturen? Misschien werkt het wel als je de service eens als domain admin uit voert.

Gewoon even een random idee... :)

Verwijderd

Topicstarter
Bedankt, dat is ook waar ik nu naar aan het kijken ben.

Het lijkt er inderdaad verdacht veel op dat SYSTEM geen rechten heeft om op die andere desktop te komen. Dit lijkt me erg sterk, want als ik eerst inlog op gebruiker A en ik switch naar gebruiker B gaat het mis, en als ik eerst inlog op gebruiker B kan ik niet op gebruiker A komen. Administrator heeft meer rechten. Ik kan altijd proberen om die SYSTEM gebruiker alle rechten te geven op het betreffende window station.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Persoonlijk lijkt een en ander me sterk: je kunt vanuit iedere service tenslotte een systrayicon tonen (uitgaande van dat 'Allow service to interact with desktop' aanstaat) en dus altijd aan de huidige desktop komen. Hell, da's het hele idee achter de LocalSystem account, dat ie lokaal in principe alles mag wat het systeem aangaat dus ook de desktops :P

Ik vermoed simpelweg dat je in je service jezelf ergens vastknoopt aan de context van de eerste user die je spot, en dat je vervolgens niet netjes doorswitcht :)

Professionele website nodig?

Pagina: 1