Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi energiesparplan unter vista ändern (https://www.delphipraxis.net/122266-energiesparplan-unter-vista-aendern.html)

Admirandis 12. Okt 2008 17:06


energiesparplan unter vista ändern
 
Hi zusammen!

Ich bin auf der Suche nach einem Programm, mit dem ich auf Knopfdruck das Energiesparschema von Vista ändern kann. Kennt jemand dazu ein Freeware programm? immer mit der Maus aufs Akkusymbol wird mir zu blöd.

Von asus gibt es so ein tool. Bräuchte das nur für meinen Acer...

Falls niemand eine Idee hat würde ich das auch selber schreiben. Habe aber auch noch nix gefunden, wie man das energiesparschema mittels delphi ändern kann...

Kurzum: Ich bin auf eure Hilfe angewiesen. Gegooglet hab ich schon, aber erfolglos :-/

Grüße Admirandis

jfheins 13. Okt 2008 15:22

Re: energiesparplan unter vista ändern
 
Schau die mal
Zitat:

powercfg /?
an ;)

Gefunden über Google: http://de.autohotkey.com/forum/post-...d85077b9#11002

Kannste ja vll. sogar in die Sidebar integrieren ;)

Sherlock 13. Okt 2008 15:32

Re: energiesparplan unter vista ändern
 
Du willst also einen Mouseclick sparen und installierst Dir dafür lieber ein zusätzliches Programm?

Oder missverstehe ich die Problematik gänzlich?

Sherlock

Mr_G 13. Okt 2008 17:21

Re: energiesparplan unter vista ändern
 
Falls du das Programm selber schreiben willst sollten folgende Funktionen für dich interessant sein:
PowerSetActiveScheme
PowerEnumerate
Gruß

Mr_G

igschliff 11. Jan 2009 13:44

Re: energiesparplan unter vista ändern
 
hallo,

mich interessiert dieses thema auch. wie kann ich denn diese api verwenden? wenn ich einen aufruf starte
Delphi-Quellcode:
PowerSetActiveScheme(NULL, 2);
dann erhalte ich die meldung, dass PowerSetActiveScheme ein undefinierter bezeichner sei. ich verwende delphi 5.

jfheins 11. Jan 2009 13:49

Re: energiesparplan unter vista ändern
 
Die musst du dann wohl selbst einbinden. Sollte in "PowrProf.dll" drin sein ;)

igschliff 11. Jan 2009 13:51

Re: energiesparplan unter vista ändern
 
danke für die schnelle antwort. kannst du mir bitte ein bisschen quellcode geben? bin ein neuling...

Meflin 11. Jan 2009 13:56

Re: energiesparplan unter vista ändern
 
Zitat:

Zitat von igschliff
danke für die schnelle antwort. kannst du mir bitte ein bisschen quellcode geben? bin ein neuling...

Du musst die Funktion importieren
Delphi-Quellcode:
function PowerSetActiveScheme([Params]): DWord; external 'PowrProf.dll';
Allerdings hab ich grad keine ahnung was für Parameter die Funktion erwartet.

igschliff 11. Jan 2009 21:09

Re: energiesparplan unter vista ändern
 
hi,

danke. ich leider auch nicht, denn ich werde aus dem manual nicht schlau. da steht

Delphi-Quellcode:
DWORD WINAPI PowerSetActiveScheme(
  __in_opt HKEY UserRootPowerKey,
  __in     const GUID *SchemeGuid
);
aber ich kann da leider keine datentypen rauslesen.

meint ihr, das geht auch irgendwie, indem man die registry-keys kopiert? unter HKEY_CURRENT_USER\POWER_CFG->CURRENTPOWERPOLICY kann man das schema an sich umstellen, doch die einstellungen des neuen energieschemas werden nicht übernommen. ich nehme also an, dass man die werte unter HKEY_CURRENT_USER\POWER_CFG\GLOBAL_POWER_POLICY->Policies updaten müsste und da halt die werte aus einem der anderen schemata eintragen sollte. die werte sind vom typ REG_BINARY und ich bekomme es nicht hin, sie so auszulesen, dass ich sie anschließend wieder reinschreiben kann. ich probiere es im moment so:

Delphi-Quellcode:
...
var regist : TRegistry;
      buffer : array[1..256] of Int64;
    buffsize : integer;
...
begin
...
  try
    regist:=TRegistry.Create;
    regist.rootKey:=HKEY_CURRENT_USER;
    regist.openkey('Control Panel\PowerCfg\PowerPolicies\'+IntToStr(schema),true);
    buffsize := regist.GetDataSize('Policies');
    regist.ReadBinaryData('Policies',buffer,buffsize);
  finally
    regist.CloseKey;
  end;
  regist.free;

  try
    regist:=TRegistry.Create;
    regist.rootKey:=HKEY_CURRENT_USER;
    regist.openkey('Control Panel\PowerCfg\GlobalPowerPolicy',true);
    regist.WriteBinaryData('Policies',buffer,buffsize);
  finally
    regist.CloseKey;
  end;
  regist.free;
...
die werte, die dann in HKEY_CURRENT_USER\POWER_CFG\GLOBAL_POWER_POLICY->Policies geschrieben werden, sind aber irgendwie nicht die werte, die vorher ausgelesen werden. ich danke allen, die mir bisher geholfen haben und würde mich sehr freuen, wenn ich auch jetzt noch einmal eure hilfe bekäme.

gruß,
igschliff

jfheins 11. Jan 2009 21:18

Re: energiesparplan unter vista ändern
 
Delphi-Quellcode:
function PowerSetActiveScheme(Reserved: Pointer; SchemeGuid: PGUID): DWord; stdcall; external 'PowrProf.dll';
Zum Beispiel ;)

PGUID weis ich nicht obs den Typ gibt, es ist ein Pointer auf eine GUID. Wenn nicht, guck ob es den Typ "GUID" gibt (ist das vll. schon ein Pointer auf eine GUID?) ansonsten definiere den 2. Parameter ebenfalls als Pointer.

Beim 1. Parameter immer nil übergeben.

igschliff 12. Jan 2009 15:55

Re: energiesparplan unter vista ändern
 
ich verstehe das jetzt so, dass ich über die PGUID (ist ein datentyp, den es gibt) definieren sollte, was ich der funktion übergeben will. PGUID hat nach delphi-hilfe folgendes format:
Delphi-Quellcode:
      type
     PGUID = ^TGUID;
     TGUID = packed record
       D1: Integer;
       D2: Word;
       D3: Word;
       D4: array[0..7] of Byte;
      end;
ich habe im netz gesucht, jedoch nicht herausbekommen können, wie ich hiermit nun mein gewünschtes energieschema definieren kann. mit dem progrämmchen powercfg ist das ganz einfach. wenn ich beispielsweise energieschema 2 haben möchte tippe ich in der konsole:
Delphi-Quellcode:
powercfg /SETACTIVE 2
ich dachte, dass das über die API ähnlich einfach sein sollte. oder bin ich einfach völlig auf dem holzweg und verstehe schlicht nicht richtig, was es mit PGUID auf sich hat?

gruß,
igschliff

himitsu 12. Jan 2009 16:06

Re: energiesparplan unter vista ändern
 
nach 'nem kurzen Blick in MSDN-Library durchsuchenPowerSetActiveScheme, bzw. die von da verlinkten Seiten,
würd ich mal vermuten du mußt dir über MSDN-Library durchsuchenEnumPwrSchemes/MSDN-Library durchsuchenPowerEnumerate (Enumerates all power schemes) die vorhndenen Schemata auflisten, dir das gewünschte Schema bzw. dessen GUID auswählen und diese an PowerSetActiveScheme übergeben.

powercfg /SETACTIVE 2 würde dann dem entsprechen, wenn du die dritte, erhaltene GUID verwendest
(oder die zweite GUID :gruebel: , falls der Index mit 1 beginnt)

igschliff 12. Jan 2009 17:38

Re: energiesparplan unter vista ändern
 
hi,

danke für die hilfe.
mir ist die einbindung von dlls aber noch zu suspekt, sodass ich bei jedem weiteren schritt noch verwirrter werde. ich habe mein problem jetzt simpel und unelegant gelöst:
Delphi-Quellcode:
ShellExecute(0,
        Nil,
        PChar('powercfg'),
        Pchar('-SETACTIVE '+EnergieSchemaFromID(schema)),
        NIL,
        SW_HIDE);
wobei EnergieSchemaFromID eine funktion ist, die eine id erhält und in der registry nach dem namen des dazugehörigen schemas sucht. es scheint zu funktionieren :)

Mr_G 12. Jan 2009 18:19

Re: energiesparplan unter vista ändern
 
Dabei ist das gar nicht soo kompliziert. Man muss das ganze nur einmal übersetzen. Ich hoffe ich hab das so richtig gemacht (funktioniert zumindest):
Delphi-Quellcode:
const PWR_PROF = 'PowrProf.dll';

{$EXTERNALSYM _POWER_DATA_ACCESSOR}
type _POWER_DATA_ACCESSOR = (
  ACCESS_AC_POWER_SETTING_INDEX  = 0,  // 0x0
  ACCESS_DC_POWER_SETTING_INDEX  = 1,  // 0x1
  ACCESS_SCHEME                  = 16, // 0x10
  ACCESS_SUBGROUP                = 17, // 0x11
  ACCESS_INDIVIDUAL_SETTING      = 18, // 0x12
  ACCESS_ACTIVE_SCHEME           = 19, // 0x13
  ACCESS_CREATE_SCHEME           = 20   // 0x14
);
{$EXTERNALSYM POWER_DATA_ACCESSOR}
POWER_DATA_ACCESSOR = _POWER_DATA_ACCESSOR;
{$EXTERNALSYM PPOWER_DATA_ACCESSOR}
PPOWER_DATA_ACCESSOR = ^_POWER_DATA_ACCESSOR;

const NO_SUBGROUP_GUID: TGUID = '{fea3413e-7e05-4911-9a71-700331f1c294}';
      GUID_DISK_SUBGROUP: TGUID = '{0012ee47-9041-4b5d-9b77-535fba8b1442}';
      GUID_SYSTEM_BUTTON_SUBGROUP: TGUID = '{4f971e89-eebd-4455-a8de-9e59040e7347}';
      GUID_PROCESSOR_SETTINGS_SUBGROUP: TGUID = '{54533251-82be-4824-96c1-47b60b740d00}';
      GUID_VIDEO_SUBGROUP: TGUID = '{7516b95f-f776-4464-8c53-06167f40cc99}';
      GUID_BATTERY_SUBGROUP: TGUID = '{e73a048d-bf27-4f12-9731-8b2076e8891f}';
      GUID_SLEEP_SUBGROUP: TGUID = '{238C9FA8-0AAD-41ED-83F4-97BE242C8F20}';
      GUID_PCIEXPRESS_SETTINGS_SUBGROUP: TGUID = '{501a4d13-42af-4429-9fd1-a8218c268e20}';

{$EXTERNALSYM PowerSetActiveScheme}
function PowerSetActiveScheme(UserRootPowerKey: HKEY; const SchemeGUID: PGUID):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerEnumerate}
function PowerEnumerate(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; AccessFlag: POWER_DATA_ACCESSOR;
  Index: ULONG; Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;
Wenn man den Teil nun hat ist der Rest ganz einfach. Die Power-Schemes könnte man zum Bleistift nun so auflisten:
Delphi-Quellcode:
procedure TEinForm.ButtonClick(Sender: TObject);
var res, size: DWORD;
    i: ULONG;
    tmp: TGUID;
begin
  i := 0;
  size := SizeOf(TGUID);
  repeat
    res := PowerEnumerate(0, nil, nil, ACCESS_SCHEME, i, @tmp, @size);
    if res = ERROR_SUCCESS then
      Memo.Lines.Add(GUIDToString(tmp));
    Inc(i);
  until res <> ERROR_SUCCESS;
end;
Um mich selber zu zitieren:
Zitat:

Zitat von Mr_G
Falls du das Programm selber schreiben willst sollten folgende Funktionen für dich interessant sein:
PowerSetActiveScheme
PowerEnumerate
Gruß

Mr_G

Dort steht eigentlich alles Relavante zur Anwendung.
Gruß

Mr_G

P.S.: Vielleicht wäre das hier und dieses auch was für die CodeLib :gruebel:

igschliff 12. Jan 2009 19:59

Re: energiesparplan unter vista ändern
 
wow, vielen dank! das werd ich auf jeden fall noch ausprobieren. :-)

igschliff 15. Jan 2009 15:44

Re: energiesparplan unter vista ändern
 
hi,

ich hab das jetzt mal ausprobiert, bekomme aber leider die fehlermeldung
Delphi-Quellcode:
Der Prozedureinsprungpunkt "PowerEnumerate" wurde in der DLL "PowrProf.dll" nicht gefunden.
der komplette quelltext ist
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComObj, ActiveX;

const PWR_PROF = 'PowrProf.dll';

{$EXTERNALSYM _POWER_DATA_ACCESSOR}
const NO_SUBGROUP_GUID: TGUID = '{fea3413e-7e05-4911-9a71-700331f1c294}';
      GUID_DISK_SUBGROUP: TGUID = '{0012ee47-9041-4b5d-9b77-535fba8b1442}';
      GUID_SYSTEM_BUTTON_SUBGROUP: TGUID = '{4f971e89-eebd-4455-a8de-9e59040e7347}';
      GUID_PROCESSOR_SETTINGS_SUBGROUP: TGUID = '{54533251-82be-4824-96c1-47b60b740d00}';
      GUID_VIDEO_SUBGROUP: TGUID = '{7516b95f-f776-4464-8c53-06167f40cc99}';
      GUID_BATTERY_SUBGROUP: TGUID = '{e73a048d-bf27-4f12-9731-8b2076e8891f}';
      GUID_SLEEP_SUBGROUP: TGUID = '{238C9FA8-0AAD-41ED-83F4-97BE242C8F20}';
      GUID_PCIEXPRESS_SETTINGS_SUBGROUP: TGUID = '{501a4d13-42af-4429-9fd1-a8218c268e20}';

type
  _POWER_DATA_ACCESSOR = (
  ACCESS_AC_POWER_SETTING_INDEX,
  ACCESS_DC_POWER_SETTING_INDEX,
  ACCESS_SCHEME,
  ACCESS_SUBGROUP,
  ACCESS_INDIVIDUAL_SETTING,
  ACCESS_ACTIVE_SCHEME,
  ACCESS_CREATE_SCHEME
  );
{$EXTERNALSYM POWER_DATA_ACCESSOR}
POWER_DATA_ACCESSOR = _POWER_DATA_ACCESSOR;
{$EXTERNALSYM PPOWER_DATA_ACCESSOR}
PPOWER_DATA_ACCESSOR = ^_POWER_DATA_ACCESSOR;

  TForm1 = class(TForm)
    Button1: TButton;
    Memo: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

  {$EXTERNALSYM PowerSetActiveScheme}
function PowerSetActiveScheme(UserRootPowerKey: HKEY; const SchemeGUID: PGUID):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerEnumerate}
function PowerEnumerate(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; AccessFlag: POWER_DATA_ACCESSOR;
  Index: ULONG; Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var res, size: DWORD;
    i: ULONG;
    tmp: TGUID;
begin
  i := 0;
  size := SizeOf(TGUID);
  repeat
    res := PowerEnumerate(0, nil, nil, ACCESS_SCHEME, i, @tmp, @size);
    if res = ERROR_SUCCESS then
      Memo.Lines.Add(GUIDToString(tmp));
    Inc(i);
  until res <> ERROR_SUCCESS;
end;

end.
habe ich noch irgendwas verdreht?

gruß,
igschliff

Mr_G 15. Jan 2009 21:31

Re: energiesparplan unter vista ändern
 
Sollte da kein Vertipper drin sein sollte es eigentlich gehen... du hast doch auch Windows Vista, oder?

igschliff 15. Jan 2009 21:48

Re: energiesparplan unter vista ändern
 
nee, XP...hmm, jetzt lese ich es auch im msdn...

ich müsste es dann also mit EnumPwrSchemes und SetActivePwrScheme zusammenbasteln. hierzu zwei fragen:

1. würde das dann auch "aufwärtskompatibel" zu vista sein?
2. wo bekommt man die informationen her, wie man die transformation MSDN->DELPHI hinbekommt? ich bin beeindruckt, wenn ich die quelltexte hier sehe, aber ich komme nicht nur mit msdn auf eine übersetzung.

gruß,
igschliff

jfheins 15. Jan 2009 21:55

Re: energiesparplan unter vista ändern
 
Zitat:

Zitat von igschliff
1. würde das dann auch "aufwärtskompatibel" zu vista sein?

Ich zitiere mal:
Zitat:

[EnumPwrSchemes is available for use in the operating systems listed in the Requirements section. It may be altered or unavailable in subsequent versions. Applications written for Windows Vista and later should use PowerEnumerate instead.]
Client Requires Windows Vista, Windows XP, or Windows 2000 Professional.
Geht also, ist aber nicht empfohlen.

==> Betriebssystemweiche ;)

Zitat:

2. wo bekommt man die informationen her, wie man die transformation MSDN->DELPHI hinbekommt? ich bin beeindruckt, wenn ich die quelltexte hier sehe, aber ich komme nicht nur mit msdn auf eine übersetzung.
Also die Funktionsaufrufe alssen sich recht einfach übersetzten. (Wenns mit recors und unions zugeht kanns noch komplizierter werden, aber sonst ...)

Aus dem C++ Header mit

Rückgabetyp Name(Typ Name, Typ Name);

Code:
BOOLEAN EnumPwrSchemes(
PWRSCHEMESENUMPROC lpfnPwrSchemesEnumProc,
LPARAM lParam
);
wird eben

function Name(Name: Typ, Name:Typ); external '...'; stdcall;

Das stdcall muss da rein, weil du C++ Funktionen aufrufst. Das external gibt die dll an in welcher die Funktion steht.

Mr_G 16. Jan 2009 13:55

Re: energiesparplan unter vista ändern
 
Da ich das ganze auch mal für XP gemacht habe will ich das nun nicht verheimlichen ;)
Delphi-Quellcode:
type
  WRSCHEMESENUMPROC = function(uiIndex: UINT; dwName: DWORD; sName: PWideChar;
    dwDesc: DWORD; sDesc: PWideChar; pp: Pointer; lParam: LPARAM): BOOLEAN; stdcall;
  {$EXTERNALSYM PWRSCHEMESENUMPROC}
  PWRSCHEMESENUMPROC = ^WRSCHEMESENUMPROC;


{$EXTERNALSYM SetActivePwrScheme}
function SetActivePwrScheme(uiID: UINT; lpGlobalPowerPolicy: Pointer;
  lpPowerPolicy: Pointer): BOOL; stdcall; external PWR_PROF;
{$EXTERNALSYM EnumPwrSchemes}
function EnumPwrSchemes(lpfnPwrSchemesEnumProc: PWRSCHEMESENUMPROC;
  lParam: LPARAM): BOOL; stdcall; external PWR_PROF;
Bei SetActivePwrScheme werden eigentlich Zeiger auf eine GLOBAL_POWER_POLICY bzw. eine POWER_POLICY übergeben... hab ich aber mal weggelassen. (Kann bei Bedarf nachgereicht werden...)
Was das Aufzählen angeht: Das funktioniert hier mit einem Callback. Das Beispiel mit dem Memo würde dann etwa so aussehen:
Delphi-Quellcode:
function XPEnumSchemes(uiIndex: UINT; dwName: DWORD; sName: PWideChar;
  dwDesc: DWORD; sDesc: PWideChar; pp: Pointer; lParam: LPARAM): BOOLEAN; stdcall;
begin
  Form.Memo.Lines.Add(IntToStr(uiIndex) +' '+ sName +' --> '+ sDesc);
  Result := True;
end;

procedure TForm1.ButtonClick(Sender: TObject);
var clb: WRSCHEMESENUMPROC;
begin
  clb := XPEnumSchemes;
  EnumPwrSchemes(@clb, 0);
end;
Hoffe das funktioniert und ist auch richtig... Viel Spaß damit :)

himitsu 16. Jan 2009 14:03

Re: energiesparplan unter vista ändern
 
nja, wir wollen mal den Parameter lParam nicht außer Acht lassen ...
den kann man nämlich für ganz nette Dinge benutzen :angel:
Delphi-Quellcode:
function XPEnumSchemes(uiIndex: UINT; dwName: DWORD; sName: PWideChar;
  dwDesc: DWORD; sDesc: PWideChar; pp: Pointer; lParam: LPARAM): BOOLEAN; stdcall;
begin
  TMemo(lParam).Lines.Add(Format('%d %s --> %s', [uiIndex, sName, sDesc]));
  Result := True;        
end;

procedure TForm1.Button1Click(Sender: TObject);
var clb: WRSCHEMESENUMPROC;
begin
  clb := XPEnumSchemes;
  EnumPwrSchemes(@clb, LPARAM(Memo1));
end;

[add]
wieso Trickser?
dieser Parameter ist schließlich für soetwas da :zwinker:
( nja, ich versteh schon den Spaß in deiner Antwort ...
wollte aber nicht, daß hier welche Denken man darf sowas nicht machen )

Mr_G 16. Jan 2009 14:19

Re: energiesparplan unter vista ändern
 
Immer diese Trickser... :mrgreen:

igschliff 16. Jan 2009 17:41

Re: energiesparplan unter vista ändern
 
Wow, vielen Dank an alle Beteiligten!
Das funktioniert nun wunderbar. :thumb:

jDallmeyer 7. Mär 2009 11:25

Re: energiesparplan unter vista ändern
 
Hallo zusammen,

ich möchte die PowerScheme-Funktionen auch in ein Programm von mir einbauen. Die XP-Variante funktioniert wunderbar, doch bei Vista breche ich mir einen ab. Ich habe folgenden Quelltext zusammengeschustert:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComObj, ActiveX;

const PWR_PROF = 'PowrProf.dll';

{$EXTERNALSYM _POWER_DATA_ACCESSOR}
const NO_SUBGROUP_GUID: TGUID = '{fea3413e-7e05-4911-9a71-700331f1c294}';
      GUID_DISK_SUBGROUP: TGUID = '{0012ee47-9041-4b5d-9b77-535fba8b1442}';
      GUID_SYSTEM_BUTTON_SUBGROUP: TGUID = '{4f971e89-eebd-4455-a8de-9e59040e7347}';
      GUID_PROCESSOR_SETTINGS_SUBGROUP: TGUID = '{54533251-82be-4824-96c1-47b60b740d00}';
      GUID_VIDEO_SUBGROUP: TGUID = '{7516b95f-f776-4464-8c53-06167f40cc99}';
      GUID_BATTERY_SUBGROUP: TGUID = '{e73a048d-bf27-4f12-9731-8b2076e8891f}';
      GUID_SLEEP_SUBGROUP: TGUID = '{238C9FA8-0AAD-41ED-83F4-97BE242C8F20}';
      GUID_PCIEXPRESS_SETTINGS_SUBGROUP: TGUID = '{501a4d13-42af-4429-9fd1-a8218c268e20}';

type _POWER_DATA_ACCESSOR = (
  ACCESS_AC_POWER_SETTING_INDEX  = 0,  // 0x0
  ACCESS_DC_POWER_SETTING_INDEX  = 1,  // 0x1
  ACCESS_SCHEME                  = 16, // 0x10
  ACCESS_SUBGROUP                = 17, // 0x11
  ACCESS_INDIVIDUAL_SETTING      = 18, // 0x12
  ACCESS_ACTIVE_SCHEME           = 19, // 0x13
  ACCESS_CREATE_SCHEME           = 20   // 0x14
);
{$EXTERNALSYM POWER_DATA_ACCESSOR}
POWER_DATA_ACCESSOR = _POWER_DATA_ACCESSOR;
{$EXTERNALSYM PPOWER_DATA_ACCESSOR}
PPOWER_DATA_ACCESSOR = ^_POWER_DATA_ACCESSOR;

  TForm1 = class(TForm)
    Button1: TButton;
    Memo: TMemo;
    Button2: TButton;
    Button3: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    active_guid : TGUID;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

  {$EXTERNALSYM PowerSetActiveScheme}
function PowerSetActiveScheme(UserRootPowerKey: HKEY; const SchemeGUID: PGUID):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerEnumerate}
function PowerEnumerate(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; AccessFlag: POWER_DATA_ACCESSOR;
  Index: ULONG; Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerGetActiveScheme}
function PowerGetActiveScheme(UserRootPowerKey: HKEY; Buffer: PUCHAR): DWORD;
  stdcall; external PWR_PROF;
{$EXTERNALSYM PowerReadDescription}
function PowerReadDescription(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; const PowerSettingGuid: PGUID;
  Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var res, size: DWORD;
    i: ULONG;
    tmp: TGUID;
begin
  i := 0;
  size := SizeOf(TGUID);
  repeat
    res := PowerEnumerate(0, nil, nil, ACCESS_SCHEME, i, @tmp, @size);
    if res = ERROR_SUCCESS then begin
      Memo.Lines.Add(GUIDToString(tmp));
      active_guid := tmp;
    end
    else Memo.Lines.Add(inttostr(res));
    Inc(i);
  until res <> ERROR_SUCCESS;
end;

procedure TForm1.Button2Click(Sender: TObject);
var res: DWORD;
    tmp: TGUID;
begin
  res := PowerGetActiveScheme(0, @tmp);
  if res = ERROR_SUCCESS then begin
    Memo.Lines.Add(GUIDToString(tmp));
    active_guid := tmp;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var res, size: DWORD;
    tmp: TGUID;
begin
  size := SizeOf(PGUID);
//  res := PowerReadDescription(0, active_guid, nil, nil, @tmp, @size);
  if res = ERROR_SUCCESS then
    Memo.Lines.Add(GUIDToString(tmp))
  else
    Memo.Lines.Add('Fehler -> '+GUIDToString(tmp));
end;

end.
Button1: Auslesen der Schemata und Ausgabe der TGuids in Memo
Button2: Auslesen des aktuellen Schemas und Ausgabe der TGuid in Memo
Button3: Auslesen der Beschreibung zum aktuellen Schema. Hierfür muss vorher entweder Button1 oder Button2 gedrückt worden sein.

Ich habe folgende Probleme:
1. Wenn ich mehrfach auf Button2 drücke, erhalte ich verschiedene Ausgaben. Es sollte imho aber immer die selbe Guid ausgegeben werden.
Delphi-Quellcode:
{0020BB60-3313-0040-8819-500101F71200}
{001FF710-3313-0040-8819-500101F71200}
{0020BB88-3313-0040-8819-500101F71200}
{0020BBB0-3313-0040-8819-500101F71200}
{0020BD10-3313-0040-8819-500101F71200}
{0020BC30-3313-0040-8819-500101F71200}
2. Die Funktionen von Button1 und Button2 liefern Ergebnisse im Format TGUID. Um allerdings mit diesen Guids weiterarbeiten zu können und sie in andere Funktionen zu stecken, benötige ich Daten im Format PGUID. Wie bekomme ich diese Transformation hin? PowerReadDescription und PowerSetActiveScheme erwarten PGUID, ich habe aber nur TGUID.

Gruß,
jDallmeyer

jDallmeyer 8. Mär 2009 14:31

Re: energiesparplan unter vista ändern
 
Gude,

ich bin etwas weitergekommen, stehe nun aber wieder vor ner Wand... Mein altes Problem konnte ich beheben, indem ich einen Zeiger auf die Speicheradresse der TGUID im Funktionsaufruf verwendet habe.

Ich lade folgende Funktionen:
Delphi-Quellcode:
{$EXTERNALSYM PowerSetActiveScheme}
function PowerSetActiveScheme(UserRootPowerKey: HKEY; const SchemeGUID: PGUID):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerEnumerate}
function PowerEnumerate(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; AccessFlag: POWER_DATA_ACCESSOR;
  Index: ULONG; Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerGetActiveScheme}
function PowerGetActiveScheme(UserRootPowerKey: HKEY; Buffer: PGUID): DWORD;
  stdcall; external PWR_PROF;
{$EXTERNALSYM PowerReadDescription}
function PowerReadDescription(UserRootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; const PowerSettingGuid: PGUID;
  Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;
{$EXTERNALSYM PowerReadDescription}
function PowerReadFriendlyName(RootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; const PowerSettingGuid: PGUID;
  Buffer: PUCHAR; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;
In der Listbox lb1 werden die Strings zu den EnergieschemaGUIDS eingetragen. Per Klick auf Button3 wird das markierte Schema ausgewählt (PowerSetActiveScheme) und das funktioniert auch. Ich würde allerdings gern Informationen zu den jeweiligen Schemata erhalten. Die auskommentierten Zeilen mit den Aufrufen von PowerReadDescription und PowerReadFriendlyName liefern als Ergebnis nicht ERROR_SUCCESS. Mache ich irgendwas falsch oder verwende ich die falschen Funktionen? Zusätzlich möchte ich Einstellungen so abändern können, dass der Monitor nicht abgeschaltet wird und der Rechner nicht in den Standby verfällt. Hat sowas schon mal jemand von Euch gemacht?

MfG

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var res, size: DWORD;
    tmp: TGUID;

    function getSel:integer;
    var i : integer;
    begin
      result := 0;
      for i := 0 to lb1.Items.Count-1 do
        if(lb1.Selected[i]) then begin
          result := i;
          break;
        end;
    end;

begin
  size := SizeOf(TGUID);
  active_guid := StringToGuid(lb1.Items[getSel()]);
  //res := PowerReadDescription(0, @active_guid, @NO_SUBGROUP_GUID, nil, @tmp, @size);
  //res := PowerReadFriendlyName(0, @active_guid, nil, nil, @tmp, @size);
  res := PowerSetActiveScheme(0, @active_guid);
  // @active_guid ist ein zeiger auf die speicheradresse von active_guid.
  if res = ERROR_SUCCESS then
    lb1.Items.Add('->'+GUIDToString(active_guid))
  else
    lb1.Items.Add('Fehler -> '+GUIDToString(tmp));
end;

Mr_G 8. Mär 2009 22:58

Re: energiesparplan unter vista ändern
 
So wie ich das sehe ist tmp bei dir vom Typ TGUID. Man benötigt aber einen Buffer der UChar aufnimmt.
Was die Veränderungen angeht: Ein Blick in das MSDN könnte dich da weiter bringen (MSDN-Library durchsuchenPower Scheme Management).

jDallmeyer 9. Mär 2009 10:21

Re: energiesparplan unter vista ändern
 
Danke für die Antwort.

Ich habe versucht, den im MSDN vorgeschriebenen Datentyp UCHAR zu verwenden, doch es entstehen dann immer AccessViolations. Ich habe daher auch andere Typen getestet, doch der einzige, der keinen Fehler produziert, ist TGUID. In einer TGUID kann aber nicht die gesuchte Information stehen. Ich habe eine Weile das Netz durchsucht, um herauszufinden, wie ich mit UCHAR umzugehen habe. Meine Frage hierzu: UCHAR ist ein vorzeichenloses 8-Bit Integer. Daraus sollte sich sehr leicht ein Buchstabe ableiten lassen. Aber dann doch nur EIN Buchstabe, denn ein EIN UCHAR sollte auch nur Platz für EINEN Buchstaben sein. Die verwendete Funktion sollte aber einen String liefern, der aus mehreren Buchstaben besteht. Ich habe daher auch versucht, ein Array von UCHARS zu verwenden, bei dem die Größe des Arrays identisch zur Rückgabegröße der Funktion ist.

Bitte schau nochmal drüber. Die gezeigte Prozedur verabschiedet sich mit einer AccessViolation. Verwende ich anstelle von UCHAR TGUID, bekomme ich zwar keinen Fehler, dafür aber nichts wirklich brauchbares.

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var res, size: DWORD;
    tmp,tmp2: UCHAR; //TGUID

    function getSel:integer; [...]
begin
  size := 0;
  active_guid := StringToGuid(lb1.Items[getSel()]);
  res := PowerReadFriendlyName(0, @active_guid, nil, nil, @tmp, @size);

  if res = ERROR_MORE_DATA then // Nach dem ersten Aufruf wird size richtig gesetzt.
    res := PowerReadFriendlyName(0, @active_guid, nil, nil, @tmp2, @size)
  else showmessage('Fehler');

  if res = ERROR_SUCCESS then begin
    lb1.Items.Add(inttostr(size));
//    lb1.Items.Add(GUIDToString(tmp2));
  end
  else
    lb1.Items.Add('Fehler -> '+inttostr(size));
end;

Mr_G 9. Mär 2009 17:27

Re: energiesparplan unter vista ändern
 
Ich kann dein Problem nachvollziehen... habe mich zu Beginn auch gewundert aber UCHAR ist etwas missverständlich verwendet. Letztendlich kommt ein Unicode String raus. Ich hab das ganze dann einfach mit PWideChar gemacht. Hier mein Code:
Delphi-Quellcode:
var b: PWideChar;
    s: DWORD;
    tmp: TGUID;
{...}
PowerReadFriendlyName(0, @tmp, nil, nil, nil, @s);
GetMem(b, s);
PowerReadFriendlyName(0, @tmp, nil, nil, Pointer(b), @s);
Memo.Lines.Add('Friendly Name --> '+ b);
FreeMem(b);
{...}
Der erste Aufruf dient dabei nur dazu die benötigte Buffergröße zu ermitteln. Ich hoffe der Code ist soweit korrekt (bei mir hat es funktioniert).

jDallmeyer 9. Mär 2009 21:12

Re: energiesparplan unter vista ändern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

vielen Dank! Das war genau, worauf ich nicht kam :thumb:

Ich habe mein Progrämmchen noch etwas erweitert, sodass nun die Energieschemata ausgelesen werden, die Namen und Beschreibungen werden angezeigt (wenn man den entsprechenden Eintrag in der Listbox markiert). Das derzeit aktive Schema kann ausgelesen und angezeigt werden. Man kann auch ein Schema in der Listbox markieren und dieses als aktiv setzen.

Ich lade das Projekt als Anhang hoch. Ich hoffe, dass es nochmal jemandem helfen kann.

Vielen Dank!

MfG

:dp:

PS
ja..der code ist noch nicht sauber, aber es kam mir jetzt erstmal nur auf funktionalität an ;)

Admirandis 16. Apr 2009 08:04

Re: energiesparplan unter vista ändern
 
wow, hier hat sich ja einiges getan, seit ich das letzte mal da war oO

Hab aber keine Mail bekommen für eine Antwort. Sonst hätte ich schon sehr viel früher vorbeigeschaut ;-)

Auf jeden Fall vielen Dank für das Projekt an jDallmeyer.

Grüße Admirandis

EDIT:
@Sherlock: Nein, ich will mir kein zusätzliches Programm installieren, sondern in meines integrieren. Hab bei mir ein Prog im Hintergrund laufen, wo ich eigene Hotkeys verwalte. Da kommt das einfach mit rein ;-)

Oliver1983 15. Jun 2009 21:36

Re: energiesparplan unter vista ändern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

ich habe mal das Programm etwas "aufgeräumt" bzw. etwas schöner gemacht Icons sowie ein TrayIcon ist nun auch drin mit Popup Menü
nun stehe ich aber vor einem Problem ich würde auch gerne die einzelheiten des EnergieSchemes auflisten, also die Einstellung die gespeichert wurden anzeigen lassen!

Die GUID's habe ich mittels in einer CMD Box mit "powercfg /Q" Befehl ausgelesen, aber wie erstelle ich nun richtig die Functionen im Delphi Programm?

Anbei das Programm auf wunsch auch der QuellCode
dazu sei gesagt die JediVCL und die LMD Tools müssen vorhanden sein

um jede hilfe sei gedankt

gruss olli

Mithrandir 15. Jun 2009 21:48

Re: energiesparplan unter vista ändern
 
Für Betriebssysteme < Windows Vista vielleicht noch ne kleine Abfrage einbauen. Is' hübscher als ne AV. :stupid:

Mr_G 16. Jun 2009 01:03

Re: energiesparplan unter vista ändern
 
Zitat:

Zitat von Oliver1983
...nun stehe ich aber vor einem Problem ich würde auch gerne die einzelheiten des EnergieSchemes auflisten, also die Einstellung die gespeichert wurden anzeigen lassen!

Ich weiß zwar nicht genau was du meinst aber aus einem Bauchgefühl heraus würde ich sagen der Parameter SubGroupOfPowerSettingsGuid der Funktion PowerEnumerate ist dein Freund ;)
Einfach mal einen Blick in die MSDN-Library werfen: MSDN-Library durchsuchenPowerEnumerate

Oliver1983 16. Jun 2009 20:39

Re: energiesparplan unter vista ändern
 
So habe mal weiter gemacht bisher hat alles gut funktioniert nun komme ich aber nicht weiter!!!

Wenn ich nun den Minimum wert der CPU anzeigen lassen will mit dieser Function

bekomme ich nichts zurück bzw. mein Label bleibt leer

hier das wesentliche:
Delphi-Quellcode:

{$EXTERNALSYM PowerReadValueMin}
function PowerReadValueMin (RootPowerKey: HKEY;
  const SubGroupOfPowerSettingGuid: PGUID; const PowerSettingGuid: PGUID;
  Buffer: PUCHAR):
  DWORD; stdcall; external PWR_PROF;

implementation

{$R *.dfm}



function TForm1.getMinValueFromsubGroupSetting(sub_guid:TGUID ; setting_guid:TGUID):string;
var res, size: DWORD;
    b: PWideChar;
begin
  size := 0;

  PowerReadValueMin (0, @sub_guid, @setting_guid, nil);
  GetMem(b, size);
  // Nach dem ersten Aufruf wird size richtig gesetzt.
  res := PowerReadValueMin (0, @sub_guid, @setting_guid, Pointer(b));
  if res = ERROR_SUCCESS then begin
    result := b;
  end
  else
    result := b;

  FreeMem(b);
end;
habe ich irgendwo einen gedanken fehler gemacht?

gruss olli

Mr_G 16. Jun 2009 21:11

Re: energiesparplan unter vista ändern
 
Du hast die Funktion so wie ich das gesehen habe falsch übersetzt:
Delphi-Quellcode:
function PowerReadValueMin(RootPowerKey: HKEY;
  const SubGroupOfPowerSettingsGuid: PGUID; const PowerSettingGuid: PGUID;
  ValueMinimum: PDWORD): DWORD; stdcall; external PWR_PROF;
Bei ValueMinimum übergibst du dann einfach einen Zeiger auf deine DWORD-Variable und schon gehts.

Ich würde aber auch nochmal einen Blick auf deinen Quelltext werfen:
Delphi-Quellcode:
PowerReadValueMin (0, @sub_guid, @setting_guid, nil);
  PowerReadValueMin (0, @sub_guid, @setting_guid, nil);
  GetMem(b, size);
  // Nach dem ersten Aufruf wird size richtig gesetzt.
  {size wurde nie an die Funktion übergeben... wer soll da was richtig setzen?} 
  res := PowerReadValueMin (0, @sub_guid, @setting_guid, Pointer(b));
  if res = ERROR_SUCCESS then begin
    result := b;
  end
  else
    {wozu der Else-Zweig wenn hier das Selbe passiert?} 
    result := b;

Oliver1983 16. Jun 2009 21:26

Re: energiesparplan unter vista ändern
 
[quote="Mr_G"]Du hast die Funktion so wie ich das gesehen habe falsch übersetzt:
Delphi-Quellcode:
function PowerReadValueMin(RootPowerKey: HKEY;
  const SubGroupOfPowerSettingsGuid: PGUID; const PowerSettingGuid: PGUID;
  ValueMinimum: PDWORD): DWORD; stdcall; external PWR_PROF;
Bei ValueMinimum übergibst du dann einfach einen Zeiger auf deine DWORD-Variable und schon gehts.

hmm bei mir geht das immer noch nicht

aufrufen tue ich die Funktion mit
Delphi-Quellcode:

procedure TForm1.PS_getActiveClick(Sender: TObject);
var res, res2: DWORD;
    tmp: PGUID;
    tmp2 : TGUID;
    actindex: integer;
    s : string;
    tray_balloon_title, tray_balloon_hint: string;
begin
  res := PowerGetActiveScheme(0, @tmp);
  if res = ERROR_SUCCESS then
   begin
    label1.caption := 'AKTIV: '+getNameFromPowerScheme(PGuidToTGuid(tmp));
    label2.caption := getDescriptionFromPowerScheme(PGuidToTGuid(tmp));
    label3.Caption := form1.getNameFromsubGroup(PGuidToTGuid(tmp),GUID_PROCESSOR_SETTINGS_SUBGROUP);
    label4.Caption := form1.getNameFromsubGroupSetting(PGuidToTGuid(tmp),GUID_PROCESSOR_SETTINGS_SUBGROUP,GUID_CPU_Minimum);
//    label5.Caption := form1.getMinValueFromsubGroupSetting(PGuidToTGuid(tmp),GUID_PROCESSOR_SETTINGS_SUBGROUP,GUID_CPU_Minimum);
    edit1.text := getMinValueFromsubGroupSetting(GUID_PROCESSOR_SETTINGS_SUBGROUP,GUID_CPU_Minimum);

.
.
.
.
das ist doch richtig oder muss ich da was noch beachten?

gruss olli

Mr_G 16. Jun 2009 22:23

Re: energiesparplan unter vista ändern
 
Jetzt muss ich wieder meine Glaskugel rausholen :glaskugel:
Was geht nicht? Und was soll mir der Code sagen? Ich seh da nur wie du deine eigene Funktion aufrufst.

P.S.: Mir läuft ein kalter Schauer bei der Funktion PGuidToTGuid über den Rücken. Hab mir gerade mal die Implementation angesehen. Ihr solltet euch unbedingt nocheinmal den Umgang mit Pointern ansehen.

Oliver1983 17. Jun 2009 04:05

Re: energiesparplan unter vista ändern
 
Moin,

was ich damit meine ist das ich immer noch kein ergebniss in meinem Label bz. meiner Edit angezeigt bekomme!

Delphi-Quellcode:
function TForm1.getMinValueFromsubGroupSetting(sub_guid:TGUID ; setting_guid:TGUID):string;
var res, size: DWORD;
    b: PWideChar;
begin
  size := 0;

  PowerReadValueMin (0, @sub_guid, @setting_guid, nil);
  GetMem(b, size);
  // Nach dem ersten Aufruf wird size richtig gesetzt.
  res := PowerReadValueMin (0, @sub_guid, @setting_guid, Pointer(b));
  if res = ERROR_SUCCESS then begin
    result := b;
  end
  else
    result := b;

  FreeMem(b);
end;
Wie ich die funktion nun aufrufe weißt du nun, habe es auch geändert was du geschrieben hattest mit dem PDWord

Delphi-Quellcode:
function PowerReadValueMin(RootPowerKey: HKEY;
  const SubGroupOfPowerSettingsGuid: PGUID; const PowerSettingGuid: PGUID;
  ValueMinimum: PDWORD): DWORD; stdcall; external PWR_PROF;
Nur was meinst du damit:?
Zitat:


Bei ValueMinimum übergibst du dann einfach einen Zeiger auf deine DWORD-Variable und schon gehts.

gruss olli

Mr_G 17. Jun 2009 10:38

Re: energiesparplan unter vista ändern
 
Ohne dir zu Nahe treten zu wollen: Du weißt nicht wirklich was du machst, oder? Schau dir doch bitte mal ein Grundlagentutorial an!
Zitat:

Zitat von Oliver1983
Nur was meinst du damit:?

Ich meine was ich sagte:
Delphi-Quellcode:
function TForm1.getMinValueFromsubGroupSetting(sub_guid, setting_guid: TGUID): String;
var val: DWORD;
begin
  if PowerReadValueMin(0, @sub_guid, @setting_guid, @val) = ERROR_SUCCESS then
    Result := IntToStr(val)
  else
    Result := 'Fehler...';
end;
Zitat:

Zitat von Mr_G
Ihr solltet euch unbedingt nocheinmal den Umgang mit Pointern ansehen.


Oliver1983 19. Jun 2009 05:12

Re: energiesparplan unter vista ändern
 
hi,

super habe jetzt einiges rausgefunden, und klappt auch so wie es soll, nun habe ich aber wieder ein problem und zwar bei PowerWriteFriendlyName Function link
bei
__in UCHAR *Buffer,
__in DWORD BufferSize

Buffersize ist eigentlich klar

aber was muss ich bei Buffer übergeben ich bin der meinung entweder PWideString oder PWideChar

Delphi-Quellcode:

{$EXTERNALSYM PowerWriteFriendlyName}
function PowerWriteFriendlyName(RootPowerKey: HKEY; const SchemeGuid: PGUID;
  const SubGroupOfPowerSettingGuid: PGUID; const PowerSettingGuid: PGUID;
  Buffer: PUChar; BufferSize: PDWORD):
  DWORD; stdcall; external PWR_PROF;


function TForm1.setNameToPowerScheme(guid:TGUID; fname: WideString ):string;
var
 res, size: DWORD;
 pfname: PWideChar;
begin
  size := 512;
  StringToWideChar(fname, Pfname, size);


  GetMem(pfname, size);
  //PowerWriteFriendlyName(0, @guid, nil, nil, Pointer(fname), @size);

  res := PowerWriteFriendlyName(0, @guid, nil, nil, Pointer(pfname), @size);
  if res = ERROR_SUCCESS then begin
    result := 'Name geändert';
  end
  else
    result := 'fehler';

 FreeMem(pfname);
end;
ich weiß das die Funktion noch etwas unaufgeräumt aussieht aber ich habe vieles getestet

Hoffe mir kann einer Helfen

gruss olli


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:13 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz