Autor Beitrag
NeoInDerMATRIX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Do 20.01.05 03:47 
Hi,

ich habe ein kleines Problem. Ich benötige die Function "EnumMonitorsA" aus "WinSpool.drv". Soweit so gut. Allerdings habe ich jetzt das problem das ich es nicht hin bekomme die Function koreckt aufzurufen. Ich bekomme per OSError abfrage immer mitgeteilt das ich die Parameter falsch übergebe. Das WinSDK ist leider auch nicht wirklich hilfreich.

ausblenden Delphi-Quelltext
1:
Function EnumMonitors(AServerName: pChar; ALevel: DWord; ABuffer: Pointer; ABufferSize: DWord; ABufferNeed: Pointer; ABufferReturned: Pointer): Boolean; StdCallExternal 'WinSpool.drv' Name 'EnumMonitorsA';					


Ich denke ich sehe den Wald for lauter Bäumen nicht.

Also so weit ich das jetzt weis, muss ich die Function einmal mit ABufferSize:=0 aufrufen um die Benötigte Puffer größe zu bekommen. Allerdings bekomme ich dabei bereits einen Fehler. Ich denke ich habe das ganze falsch nach Delphi übersetzt. Deshalb hier die definition aus dem SDK:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
BOOL EnumMonitors(
  LPTSTR pName,       // server name
  DWORD Level,        // information level
  LPBYTE pMonitors,   // monitor information buffer
  DWORD cbBuf,        // size of monitor information buffer
  LPDWORD pcbNeeded,  // bytes received or required
  LPDWORD pcReturned  // number of monitors received
);


Ich hoffe das mir einer von euch helfen kann.

Thx & Cu
Neo
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 20.01.05 03:49 
Deklarier die letzten beiden Parameter mal als var Parameter, du willst ja was zurück bekommen. Sorry, da stimmt noch mehr nicht.
NeoInDerMATRIX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Do 20.01.05 04:01 
Hi,

@Luckie: Ja das habe ich bereits probiert. Allerdings macht das bei dem letztem Parameter nicht wirklich sin, wenn ich das aus dem SDK richtig verstanden habe!
Aber auch als Var bekomme ich eine Fehler.

Aber trotzdem danke.

Cu
Neo
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 20.01.05 04:27 
Was willst du eigentlich damit in Erfahrung birngen? Die Anzahl der Monitore? dann wäre wohl Suche im MSDN ENUMDISPLAYDEVICES oder Suche im MSDN ENUMDISPLAYMONITORS die richtige Wahl. Ich weiß nämlich gar nicht, ob man diese Funktion so aus der drv Datei aufrufen kann. Denn theoretisch sollte es so gehen:
ausblenden volle Höhe Delphi-Quelltext
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:
type
  TMONITOR_INFO_1 = record
    Name: PChar;
  end;
  PMONITOR_INFO_1 = ^TMONITOR_INFO_1;

function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer;
  cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean;
  stdcallexternal 'WinSpool.drv' Name 'EnumMonitorsA';

procedure TForm1.Button1Click(Sender: TObject);
var
  Needed       : DWORD;
  Returned     : DWORD;
  Monitors     : Pointer;
  pWork        : Pointer;
  i            : Integer;
begin
  Monitors := nil;

  if (not EnumMonitors(nil1, Monitors, 0, Needed, Returned) and (GetLastError =
    ERROR_INSUFFICIENT_BUFFER)) then
  begin
    EnumMonitors(nil1, Monitors, Needed, Needed, Returned);
    pWork := Monitors;
    for i := 0 to Returned - 1 do
    begin
      ShowMessage(PMONITOR_INFO_1(pWork)^.Name);
      Inc(Integer(pWork), sizeof(TMONITOR_INFO_1));
    end;
  end;
end;

Aber beim zweiten Aufruf bekomme ich eine AccessViolation.
NeoInDerMATRIX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Do 20.01.05 22:21 
Hi Luckie,

also die anzahl der Monitore habe ich schon. Ich benötige noch den Treiber für den Monitor und den rest der Strings aus der Monitor_Info_2 strucktur.

Laut WinSDK soll das euch eigentlich nicht aus der WinSpool.drv gelesen werden sondern aus der WinSpool.lib. Allerdings ist dies nicht möglich. Da ich diese nicht als DLL oder so laden kann. Und nach suchen auf meinem System war nur eine WinSpool.drv vorhanden. Aus diesem grund habe ich das versucht. Und als ich nur den Fehlercode Ungültiger Parameter zurückbekommen habe, dachte ich das es ja dann möglich sein müste.

Deine Code werde ich mal probieren. Ich melde mich dann auch gleich wenn ich etwas weis.
Und danke für deine Hilfe.

Cu
Neo
NeoInDerMATRIX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Do 20.01.05 23:05 
Hi,

also ich habe es jetzt zum laufen gebracht. Auch wenn es leider nicht die Information bringt die ich gesucht habe. Diese Function Listet Drucker, Modem, und komischer weise TCP/IP Port.

Was bei Luckie gefehlt hat ist nur das beim zweiten aufruf ein speicherbereich vorhanden sein muss.
ausblenden volle Höhe Delphi-Quelltext
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:
type  
  TMONITOR_INFO_1 = record  
    Name: PChar;  
  end;  
  PMONITOR_INFO_1 = ^TMONITOR_INFO_1;  

 
function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer;  
  cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean;  
  stdcallexternal 'WinSpool.drv' Name 'EnumMonitorsA';  

 
procedure TForm1.Button1Click(Sender: TObject);  
var  
  Needed       : DWORD;  
  Returned     : DWORD;  
  Monitors     : Pointer;  
  pWork        : Pointer;  
  i            : Integer;  
begin  
  Monitors := nil;  

 
  if (not EnumMonitors(nil1, Monitors, 0, Needed, Returned) and (GetLastError =  
    ERROR_INSUFFICIENT_BUFFER)) then  
  begin  
    EnumMonitors(nil1, Monitors, Needed, Needed, Returned);  
    GetMem(pWork, Needed);
    for i := 0 to Returned - 1 do  
    begin  
      ShowMessage(PMONITOR_INFO_1(pWork)^.Name);  
      Inc(Integer(pWork), sizeof(TMONITOR_INFO_1));  
    end;  
    FreeMem(pWork, Needed);
  end;  
end;


So geht es dann.

Thx & Cu
Neo
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 21.01.05 14:31 
Neo_in_der_MATRIX hat folgendes geschrieben:

Was bei Luckie gefehlt hat ist nur das beim zweiten aufruf ein speicherbereich vorhanden sein muss.

Ja, das ist mir gestern Nacht auch eingefallen. Ich ahtte imme rnoch die Netxxx-API Funktionen im Kopf, die diesen selber reservieren.

Allerdings würde ich es so machen:
ausblenden volle Höhe Delphi-Quelltext
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:
type
  TMONITOR_INFO_1 = record
    Name: PChar;
  end;
  PMONITOR_INFO_1 = ^TMONITOR_INFO_1;

function EnumMonitors(Name: PChar; Level: DWord; Monitors: Pointer;
  cbBuffer: DWord; var pcbNeeded: DWORD; var pcReturned: DWORD): Boolean;
  stdcallexternal 'WinSpool.drv' Name 'EnumMonitorsA';

procedure TForm1.Button1Click(Sender: TObject);
var
  Needed       : DWORD;
  Returned     : DWORD;
  Monitors     : Pointer;
  pWork        : Pointer;
  i            : Integer;
begin
  Monitors := nil;
  if (not EnumMonitors(nil1, Monitors, 0, Needed, Returned) and (GetLastError =
    ERROR_INSUFFICIENT_BUFFER)) then
  begin
    GetMem(Monitors, Needed);
    try
      EnumMonitors(nil1, Monitors, Needed, Needed, Returned);
      pWork := Monitors;
      for i := 0 to Returned - 1 do
      begin
        ShowMessage(PMONITOR_INFO_1(pWork)^.Name);
        Inc(Integer(pWork), sizeof(TMONITOR_INFO_1));
      end;
    finally
      FreeMem(Monitors, Needed);
    end;
  end;
end;

Grund ist der: Die Informationen befinden sich im Speicherbereich von Monitors. Jetzt muss ich diese Adresse aber inkrementieren. Bin ich am Ende angelangt, kenne ich die Startadresse nicht mehr. Gebe ich also Monitors frei, gebe ich nicht den Speicher von Anfang an frei. Mit Einführung des Arbeitszeigers pWork, mit dem ich dann die Informationen abrufe, kann ich selbigen inkrementieren. Der Zeiger Monitors bleibt aber auf dem ersten Speicherbereich stehen und wenn ich dann Monitors freigebe, habe ich den ganzen Speicherbereich wieder freigegeben.

Was mich jetzt bei dir etwas wundert: Du reservierst Speicher für pWork:
ausblenden Delphi-Quelltext
1:
GetMem(pWork, Needed);					

aber keinen für Monitors. Aber im Funktionsaufruf
ausblenden Delphi-Quelltext
1:
EnumMonitors(nil1, Monitors, Needed, Needed, Returned);					

füllst du selbigen. Arbeiten tust du dann aber wieder mit pWork, nur wo weißt du pWork den gefüllten Speicherbereich von Monitors zu? So wie ich das sehe, ist es purer Zufall, dass dein Code funktioniert.


Zuletzt bearbeitet von Luckie am Fr 21.01.05 14:46, insgesamt 1-mal bearbeitet
NeoInDerMATRIX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Fr 21.01.05 14:41 
Ja ist egal,

ich danke dir auf jeden fall für deine Hilfe.

Cu
Neo
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 21.01.05 14:51 
*push* Guck noch mal rein, habe noch was ergänzt.