Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Das Handle ist ungültig (https://www.delphipraxis.net/196216-das-handle-ist-ungueltig.html)

EWeiss 2. Mai 2018 05:32


Das Handle ist ungültig
 
Wie kann ich das beheben bzw. auf was muss ich achten?
Ich starte einen Stream vom Internet über den IE11 anschließend führe ich TAudioVolume aus.
Bei normalen Prozessen ermittelt über die PID gibt es kein Problem.
Aber wenn hier die Session erstellt und die Abfrage über den Prozess läuft bekomme ich oben genannte Fehlermeldung.

Was kann man machen?
Das selbe Problem habe ich auch wenn die Sidebar.exe erkannt wird.

Delphi-Quellcode:
FAudioSessionList[Index].SessionGuid := GroupGuid;
HR := SessionControl2.GetDisplayName(pDisplayName);
if Succeeded(HR) then
begin
  FAudioSessionList[Index].DisplayName := pDisplayName;
  if AudioSessionInfo(Index).DisplayName = '' then
    FAudioSessionList[Index].DisplayName := GetBaseNameFromPID(PID);

Delphi-Quellcode:
function TAudioVolume.GetBaseNameFromPID(const PID: DWORD): string;
var
  hProcess: THandle;
  path: array [0 .. MAX_PATH - 1] of WChar;
  ErrorTxt : array [0..500] of char;
begin

  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
    try
      if GetModuleBaseName(hProcess, 0, path, MAX_PATH) = 0 then
      begin
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, GetLastError, 0, ErrorTxt, 500, nil);
        ShowMessage(ErrorTxt);
        //RaiseLastOSError;
      end;
      Result := path;
    finally
      CloseHandle(hProcess)
    end
  else
    RaiseLastOSError;
end;
Siehe shot! Das wird angezeigt.
Aber ich kann den Prozess steuern also die Lautstärke desselben.
Zudem bekomme ich so gut wie nie den DisplayName und den IconPath.
Eigentlich müsste der DisplayName wie beim Pic stream.png sein.

gruss

TiGü 2. Mai 2018 09:56

AW: Das Handle ist ungültig
 
iexplore.exe besteht ja MINDESTENS aus zwei Process-Instanzen, wenn ich ihn bei mir hier starte und sonst nichts mache (laut Task-Manager).
Probiere doch mal die andere PID aus.

EWeiss 2. Mai 2018 09:58

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401041)
iexplore.exe besteht ja MINDESTENS aus zwei Process-Instanzen, wenn ich ihn bei mir hier starte und sonst nichts mache (laut Task-Manager).
Probiere doch mal die andere PID aus.

Wenn ich den IE starte habe ich nur einen Prozess in der liste vom Taskmanager IExplorer.exe
Danke.

Auf der anderen seite wie soll ich den anderen ausprobieren ?
Da habe ich keinen Einfluss drauf es wird die Session initialisiert die in dem Moment Sound wieder gibt!

gruss

TiGü 2. Mai 2018 10:25

AW: Das Handle ist ungültig
 
Versuch mal anstatt GetModuleBaseName die Funktion GetProcessImageFileNameW.

Beispiel:
Delphi-Quellcode:
program Project3;

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.SysUtils,
  Winapi.Windows,
  PsAPI;

function GetProcessImageFileNameW(hProcess: THandle; lpBaseName: LPCWSTR; nSize: DWORD): DWORD; stdcall; external 'PSAPI.dll';

function GetBaseNameFromPID(const PID: DWORD): string;
var
  hProcess: THandle;
  LModule: HMODULE;
  path: array [0 .. MAX_PATH - 1] of WideChar;
  ErrorTxt: array [0 .. 500] of WideChar;
begin

  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
    try
      LModule := 0;
      path := '';
      // if GetModuleBaseName(hProcess, LModule, path, MAX_PATH) = 0 then
      if GetProcessImageFileNameW(hProcess, path, MAX_PATH) = 0 then
      begin
        ErrorTxt := '';
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, GetLastError, 0, ErrorTxt, 500, nil);
        Writeln(ErrorTxt);
        // RaiseLastOSError;
      end;
      Result := path;
    finally
      CloseHandle(hProcess)
    end
  else
    RaiseLastOSError;
end;

var
  gPID: DWORD;
  gName: string;

begin
  try
    while True do
    begin
      Writeln('Bitte PID eingeben');
      Readln(gPID);
      gName := GetBaseNameFromPID(gPID);
      Writeln(gName);
    end;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      Readln;
    end;
  end;

end.

EWeiss 2. Mai 2018 10:39

AW: Das Handle ist ungültig
 
Danke damit funktioniert es ;)
Aber!

Zitat:

Zudem bekomme ich so gut wie nie den DisplayName und den IconPath.
Das ist immer noch nicht bereinigt..
Verstehe nicht das da nie was ankommt.

gruss

TiGü 2. Mai 2018 10:54

AW: Das Handle ist ungültig
 
Wie machste das denn?
:glaskugel: Glaskugel sagt: Ohne genauen Quelltext keine Aussage! :glaskugel:

EWeiss 2. Mai 2018 11:02

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401054)
Wie machste das denn?
:glaskugel: Glaskugel sagt: Ohne genauen Quelltext keine Aussage! :glaskugel:

Nun ja denke Quelltext dafür hatte ich gepostet oder?
Delphi-Quellcode:
HR := SessionControl2.GetDisplayName(pDisplayName);


pDisplayName ist PWideChar und sollte den DisplayNamen zurück liefern tut er aber nicht.
Bei keiner Anwendung.

Wenn dieser leer ist erzwinge ich ihn das hat aber zur folge des er nicht korrekt ist.


gruss

TiGü 2. Mai 2018 11:08

AW: Das Handle ist ungültig
 
Was ist SessionControl2? Wo kommt es her? Wie wird es erzeugt? Was ist der Datentyp? Ist das ein Interface? Wie ist die Definition des Interfaces?

EWeiss 2. Mai 2018 11:15

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401059)
Was ist SessionControl2? Wo kommt es her? Wie wird es erzeugt? Was ist der Datentyp? Ist das ein Interface? Wie ist die Definition des Interfaces?

Delphi-Quellcode:
unit AudioSessionControl;

interface

uses
  Windows, Messages, Classes, AudioSessionEvents;

const
  IID_IAudioSessionControl: TGUID = '{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}';

type
  IAudioSessionControl = interface(IUnknown)
    ['{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}']
    function GetState(out pRetVal: uint): HResult; stdcall;
    function GetDisplayName(out pRetVal: LPWSTR): HResult; stdcall;
    function SetDisplayName(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall;
    function GetIconPath(out pRetVal: LPWSTR): HResult; stdcall;
    function SetIconPath(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall;
    function GetGroupingParam(pRetVal: pGuid): HResult; stdcall;
    function SetGroupingParam(OverrideValue, EventContext: pGuid): HResult; stdcall;
    function RegisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents)
      : HResult; stdcall;
    function UnregisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents)
      : HResult; stdcall;
  end;

implementation

end.
Delphi-Quellcode:
unit AudioSessionControl2;

interface

uses
  Windows, Messages, Classes, AudioSessionControl;

const
  IID_IAudioSessionControl2: TGUID = '{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}';

type
  IAudioSessionControl2 = interface(IAudioSessionControl)
    ['{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}']
    function GetSessionIdentifier(out pRetVal: LPWSTR): Hresult; stdcall;
    function GetSessionInstanceIdentifier(out pRetVal: LPWSTR): Hresult; stdcall;
    function GetProcessId(out pRetVal: DWord): Hresult; stdcall;
    //indicates whether the session is a system sounds session.
    function IsSystemSoundsSession(): Hresult; stdcall;
    //S_OK = The session is a system sounds session.
    //S_FALSE = The session is not a system sounds session.
    function SetDuckingPreference(const optOut: Boolean): Hresult; stdcall;
    //A BOOL variable that enables or disables system auto-ducking.
  end;

implementation

end.
Delphi-Quellcode:
SessionControl2: IAudioSessionControl2;
....
    HR := AudioDevice.Activate(IID_IAudioSessionManager2, CLSCTX_ALL, nil, IUnknown(SessionManager2)
      );
    if Succeeded(HR) then
    begin
      HR := SessionManager2.GetSessionEnumerator(pEnumerator);
      if Succeeded(HR) then
      begin
        HR := pEnumerator.GetSession(Index, SessionControl);
        if Succeeded(HR) then
        begin
          HR := SessionControl.QueryInterface(IAudioSessionControl2, SessionControl2);
          if Succeeded(HR) then
gruss

TiGü 2. Mai 2018 11:15

AW: Das Handle ist ungültig
 
Zusatzfrage: Welchen Wert hat HR?
Delphi-Quellcode:
HR := SessionControl2.GetDisplayName(pDisplayName);

EWeiss 2. Mai 2018 11:16

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401061)
Zusatzfrage: Welchen Wert hat HR?
Delphi-Quellcode:
HR := SessionControl2.GetDisplayName(pDisplayName);

HR: HResult und ist immer 0 also ohne Fehler.

gruss

TiGü 2. Mai 2018 11:20

AW: Das Handle ist ungültig
 
Das mit dem unvollständigen Quelltext-Schnipseln ist mir so zu mühselig.
Lade bitte ein kleines Konsolenprojekt mit allen notwendigen Units und Dateien als ZIP-Archiv hoch.

EWeiss 2. Mai 2018 11:24

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401063)
Das mit dem unvollständigen Quelltext-Schnipseln ist mir so zu mühselig.
Lade bitte ein kleines Konsolenprojekt mit allen notwendigen Units und Dateien als ZIP-Archiv hoch.

sorry nein keine unvollständigen Quellcodes.. hier hochzuladen das macht keinen sinn.
Schicke ihn dir aber gerne zu wenn ich eine Mail hätte.

gruss

TiGü 2. Mai 2018 11:32

AW: Das Handle ist ungültig
 
Das ist ein Forum.
Man stellt öffentlich Fragen und erhält öffentlich Antworten.
Es hätte keinen Sinn für nachfolgende Programmierergenerationen, wenn die eventuell folgende Lösung nur noch per internen Mailverkehr abläuft.

Ein kleines Beispielprogramm mit allen notwendigen Units wird ja möglich sein.
Anders machen das andere User ja auch nicht, wenn ihnen geholfen werden soll.
Mit den Quellcode Schnipseln kann ich bspw. nix anfangen, da ich weder die Unit AudioSessionEvents habe, noch die Definition von AudioDevice oder SessionManager2.
So ist das nur unvollständiges Stückwerk.

EWeiss 2. Mai 2018 11:35

AW: Das Handle ist ungültig
 
Zitat:

Mit den Quellcode Schnipseln kann ich bspw. nix anfangen, da ich weder die Unit AudioSessionEvents habe, noch die Definition von AudioDevice oder SessionManager2.
So ist das nur unvollständiges Stückwerk.
War aber von dir so erwünscht ;)
Ok macht ja nix muss mir dann selbst irgendwie weiter helfen. Danke

gruss

TiGü 2. Mai 2018 13:16

AW: Das Handle ist ungültig
 
Komplett lauffähiges Konsolenprogramm, alles in einer einzigen Unit.
Gibt bei mir aus:
Code:
DisplayName: @%SystemRoot%\System32\AudioSrv.Dll,-202
IconPath: @%SystemRoot%\System32\AudioSrv.Dll,-203

Delphi-Quellcode:
program AudioDevice;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  Winapi.ActiveX,
  Winapi.PropSys;

const
  IID_IAudioSessionControl: TGUID = '{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}';
  IID_IAudioSessionControl2: TGUID = '{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}';
  IID_IAudioSessionManager: TGUID = '{BFA971F1-4D5E-40BB-935E-967039BFBEE4}';
  IID_IAudioSessionManager2: TGUID = '{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}';

  CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
  IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
  IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
  IID_IMMAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
  IID_IAudioMeterInformation: TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
  IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
  IID_IMMNotificationClient: TGUID = '{7991EEC9-7E89-4D85-8390-6C703CEC60C0}';

  DEVICE_STATE_ACTIVE = $00000001;
  DEVICE_STATE_UNPLUGGED = $00000002;
  DEVICE_STATE_NOTPRESENT = $00000004;
  DEVICE_STATEMASK_ALL = $00000007;

type
  EDataFlow = TOleEnum;

const
  eRender = $00000000;
  eCapture = $00000001;
  eAll = $00000002;
  EDataFlow_enum_count = $00000003;

type
  ERole = TOleEnum;

const
  eConsole = $00000000;
  eMultimedia = $00000001;
  eCommunications = $00000002;
  ERole_enum_count = $00000003;

type
  IAudioSessionEvents = interface

  end;

  IAudioSessionControl = interface(IUnknown)
    ['{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}']
    function GetState(out pRetVal: uint): HRESULT; stdcall;
    function GetDisplayName(out pRetVal: LPWSTR): HRESULT; stdcall;
    function SetDisplayName(Value: LPCWSTR; EventContext: pGuid): HRESULT; stdcall;
    function GetIconPath(out pRetVal: LPWSTR): HRESULT; stdcall;
    function SetIconPath(Value: LPCWSTR; EventContext: pGuid): HRESULT; stdcall;
    function GetGroupingParam(pRetVal: pGuid): HRESULT; stdcall;
    function SetGroupingParam(OverrideValue, EventContext: pGuid): HRESULT; stdcall;
    function RegisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents)
      : HRESULT; stdcall;
    function UnregisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents)
      : HRESULT; stdcall;
  end;

  IAudioSessionControl2 = interface(IAudioSessionControl)
    [IID_IAudioSessionControl2]
    function GetSessionIdentifier(out pRetVal: LPWSTR): HRESULT; stdcall;
    function GetSessionInstanceIdentifier(out pRetVal: LPWSTR): HRESULT; stdcall;
    function GetProcessId(out pRetVal: DWord): HRESULT; stdcall;
    // indicates whether the session is a system sounds session.
    function IsSystemSoundsSession(): HRESULT; stdcall;
    // S_OK = The session is a system sounds session.
    // S_FALSE = The session is not a system sounds session.
    function SetDuckingPreference(const optOut: Boolean): HRESULT; stdcall;
    // A BOOL variable that enables or disables system auto-ducking.
  end;

  IAudioSessionEnumerator = interface(IUnknown)
    ['{E2F5BB11-0570-40CA-ACDD-3AA01277DEE8}']
    function GetCount(out SessionCount: Integer): HRESULT; stdcall;
    function GetSession(const SessionCount: Integer; out Session: IAudioSessionControl): HRESULT; stdcall;
  end;

  IAudioSessionNotification = interface
  end;

  IAudioVolumeDuckNotification = interface
  end;

  ISimpleAudioVolume = interface(IUnknown)
    ['{87CE5498-68D6-44E5-9215-6DA47EF883D8}']
    function SetMasterVolume(fLevel: Single; EventContext: pGuid): HRESULT; stdcall;
    function GetMasterVolume(out fLevel: Single): HRESULT; stdcall;
    function SetMute(bMute: LongBool; EventContext: pGuid): HRESULT; stdcall;
    function GetMute(out bMute: LongBool): HRESULT; stdcall;
  end;

  IAudioSessionManager = interface(IUnknown)
    [IID_IAudioSessionManager]
    function GetAudioSessionControl(AudioSessionGuid: pGuid; StreamFlag: uint; out SessionControl: IAudioSessionControl)
      : HRESULT; stdcall;
    function GetSimpleAudioVolume(AudioSessionGuid: pGuid; StreamFlag: uint; out AudioVolume: ISimpleAudioVolume)
      : HRESULT; stdcall;
  end;

  IAudioSessionManager2 = interface(IAudioSessionManager)
    [IID_IAudioSessionManager2]
    function GetSessionEnumerator(out SessionEnum: IAudioSessionEnumerator): HRESULT; stdcall;
    function RegisterSessionNotification(SessionNotification: IAudioSessionNotification): HRESULT; stdcall;
    function UnregisterSessionNotification(SessionNotification: IAudioSessionNotification): HRESULT; stdcall;
    function RegisterDuckNotification(const sessionID: LPCWSTR; const duckNotification: IAudioVolumeDuckNotification)
      : HRESULT; stdcall;
    function UnregisterDuckNotification(const duckNotification: IAudioVolumeDuckNotification): HRESULT; stdcall;
  end;

  IAudioEndpointVolumeCallback = interface(IUnknown)
    [IID_IAudioEndpointVolumeCallback]
  end;

  IMMAudioEndpointVolume = interface(IUnknown)
    [IID_IMMAudioEndpointVolume]
    function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function GetChannelCount(out PInteger): Integer; stdcall;
    function SetMasterVolumeLevel(fLevelDB: Double; pguidEventContext: TGUID): Integer; stdcall;
    function SetMasterVolumeLevelScalar(fLevelDB: Double; pguidEventContext: TGUID): Integer; stdcall;
    function GetMasterVolumeLevel(out fLevelDB: Double): Integer; stdcall;
    function GetMasterVolumeLevelScaler(out fLevel: Double): Integer; stdcall;
    function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: Double; pguidEventContext: TGUID): Integer; stdcall;
    function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: Double; pguidEventContext: TGUID): Integer; stdcall;
    function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: Double): Integer; stdcall;
    function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: Double): Integer; stdcall;
    function SetMute(bMute: Boolean; pguidEventContext: TGUID): Integer; stdcall;
    function GetMute(out bMute: Boolean): Integer; stdcall;
    function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;
    function VolumeStepUp(pguidEventContext: TGUID): Integer; stdcall;
    function VolumeStepDown(pguidEventContext: TGUID): Integer; stdcall;
    function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
    function GetVolumeRange(out pflVolumeMindB: Double; out pflVolumeMaxdB: Double; out pflVolumeIncrementdB: Double)
      : Integer; stdcall;
  end;

  IMMDevice = interface(IUnknown)
    [IID_IMMDevice]
    function Activate(const iid: TGUID; dwClsCtx: uint; pActivationParams: PPropVariant; out ppInterface: IUnknown)
      : HRESULT; stdcall;
    function OpenPropertyStore(stgmAccess: Integer; out ppProperties: IPropertyStore): HRESULT; stdcall;
    function GetId(ppstrId: PWChar): HRESULT; stdcall;
    function GetState(var pdwState: uint): HRESULT; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
    [IID_IMMDeviceCollection]
    function GetCount(var pcDevices: uint): HRESULT; stdcall;
    function Item(nDevice: uint; out ppDevice: IMMDevice): HRESULT; stdcall;
  end;

  IMMNotificationClient = interface(IUnknown)
    [IID_IMMNotificationClient]
  end;

  IMMDeviceEnumerator = interface(IUnknown)
    [IID_IMMDeviceEnumerator]
    function EnumAudioEndpoints(dataFlow: EDataFlow; dwStateMask: DWord; out ppDevices: IMMDeviceCollection): HRESULT; stdcall;
    function GetDefaultAudioEndpoint(dataFlow: EDataFlow; role: ERole; out ppEndpoint: IMMDevice): HRESULT; stdcall;
    function GetDevice(pwstrId: PWChar; out ppDevice: IMMDevice): HRESULT; stdcall;
    function RegisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall;
    function UnregisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall;
  end;

procedure PrintDefaultSessionControlDisplayName;
var
  DeviceEnumerator: IMMDeviceEnumerator;
  SessionManager: IAudioSessionManager;
  SessionManager2: IAudioSessionManager2;
  AudioDevice: IMMDevice;
  SessionControl2: IAudioSessionControl2;
  SessionEnumerator: IAudioSessionEnumerator;
  SessionControl: IAudioSessionControl;
  HR: HRESULT;
  SessionCount: Integer;
  pRetVal: PWideChar;
begin
  SessionCount := 0;

  HR := CoInitializeEx(nil, 0);
  if Succeeded(HR) then
  begin
    HR := CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, DeviceEnumerator);
    if Succeeded(HR) then
    begin
      HR := DeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, AudioDevice);
      if Succeeded(HR) then
      begin
        HR := AudioDevice.Activate(IID_IAudioSessionManager, CLSCTX_INPROC_SERVER, nil, IUnknown(SessionManager));
        if Succeeded(HR) then
        begin
          if Supports(SessionManager, IID_IAudioSessionManager2, SessionManager2) then
          begin
            HR := SessionManager2.GetSessionEnumerator(SessionEnumerator);
            if Succeeded(HR) then
            begin
              HR := SessionEnumerator.GetSession(SessionCount, SessionControl);
              if Succeeded(HR) then
              begin
                if Supports(SessionControl, IID_IAudioSessionControl2, SessionControl2) then
                begin
                  SessionControl2.GetDisplayName(pRetVal);
                  Writeln('DisplayName: ', pRetVal);
                  CoTaskMemFree(pRetVal);

                  SessionControl2.GetIconPath(pRetVal);
                  Writeln('IconPath: ', pRetVal);
                  CoTaskMemFree(pRetVal);
                end;
              end;
            end;
          end;
        end;
      end;
    end;

    CoUninitialize;
  end;
end;

begin
  try
    PrintDefaultSessionControlDisplayName;
    Readln;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      Readln;
    end;
  end;

end.

EWeiss 2. Mai 2018 13:35

AW: Das Handle ist ungültig
 
Sieht gut aus..)

Muss das mal mit meiner Herangehensweise vergleichen.
Bin auch schon was weiter wenn auch mit ach und krach muss noch einiges optimiert werden.
Zum Beispiel scheint MS die SideBar zu kombinieren.

Bei mir wird für jedes das Sound enthält ein Control erstellt.

Danke.

gruss

EWeiss 2. Mai 2018 14:06

AW: Das Handle ist ungültig
 
Nope habe deine Funktion testweise mal eingebaut da kommt nichts an.
Beides bleibt leer.
...........
Dein Projekt ohne Änderung kompiliert D2010
Siehe das Ergebnis.

Sollte eigentlich den Namen und den IconPfad meiner Anwendung anzeigen.Tut's aber nicht.
Und wenn ich die Konsole vorher starte und anschließend ein Sound Programm stürzt das Konsolen teil ab.

Hmmm.. vielleicht lege ich das Projekt erst mal zur Seite.

Hier die Änderung damit es nicht mehr abstürzt.
Aber funktionieren tut es trotzdem nicht. (Win7 Problem? Keine Ahnung)
Delphi-Quellcode:
procedure PrintDefaultSessionControlDisplayName;
var
   DeviceEnumerator: IMMDeviceEnumerator;
   SessionManager: IAudioSessionManager;
   SessionManager2: IAudioSessionManager2;
   AudioDevice: IMMDevice;
   SessionControl2: IAudioSessionControl2;
   SessionEnumerator: IAudioSessionEnumerator;
   SessionControl: IAudioSessionControl;
   HR: HRESULT;
   SessionCount: Integer;
   pRetVal: PWideChar;
begin
   SessionCount := 0;

   HR := CoInitializeEx(nil, 0);
   if Succeeded(HR) then
   begin
     HR := CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, DeviceEnumerator);
     if Succeeded(HR) then
     begin
       HR := DeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, AudioDevice);
       if Succeeded(HR) then
       begin
         HR := AudioDevice.Activate(IID_IAudioSessionManager, CLSCTX_INPROC_SERVER, nil, IUnknown(SessionManager));
         if Succeeded(HR) then
         begin
           if Supports(SessionManager, IID_IAudioSessionManager2, SessionManager2) then
           begin
             HR := SessionManager2.GetSessionEnumerator(SessionEnumerator);
             if Succeeded(HR) then
             begin
               HR := SessionEnumerator.GetSession(SessionCount, SessionControl);
               if Succeeded(HR) then
               begin
                 if Supports(SessionControl, IID_IAudioSessionControl2, SessionControl2) then
                 begin
                   SessionControl2.GetDisplayName(pRetVal);
                   Writeln('DisplayName: ', pRetVal);
                   CoTaskMemFree(pRetVal);

                   SessionControl2.GetIconPath(pRetVal);
                   Writeln('IconPath: ', pRetVal);
                   CoTaskMemFree(pRetVal);
                 end;
                 SessionControl2 := nil;
               end;
               SessionControl := nil;
             end;
             SessionEnumerator := nil;
           end;
           SessionManager2 := nil;
         end;
         SessionManager := nil;
       end;
     end;
     DeviceEnumerator := nil;
     CoUninitialize;
   end;
end;
gruss

jaenicke 2. Mai 2018 22:18

AW: Das Handle ist ungültig
 
Bei mir wird es auch korrekt angezeigt, aber unter Windows 10. Windows 7 habe ich leider nicht zur Verfügung zum Testen.

EWeiss 3. Mai 2018 04:31

AW: Das Handle ist ungültig
 
Zitat:

Zitat von jaenicke (Beitrag 1401124)
Bei mir wird es auch korrekt angezeigt, aber unter Windows 10. Windows 7 habe ich leider nicht zur Verfügung zum Testen.

seltsam :evil:
Ich kann machen was ich will beide WideChars ergeben immer .. nothing. :)

Ein
Delphi-Quellcode:
if Supports(SessionControl

Ist nicht unbedingt nötig denn wenn ich ein query auf SessionControl2 ausführe würde es wenn nicht unterstützt eh fehl schlagen.

so..
Delphi-Quellcode:
HR := SessionControl.QueryInterface(IAudioSessionControl2, SessionControl2);

oder so
Delphi-Quellcode:
if Supports(SessionManager, IID_IAudioSessionManager2, SessionManager2) then


bleibt sich gleich.
Mein Test bezieht sich auf das von mir korrigierte Obige Schnipsel.
Alle Test's schlagen fehl.

gruss

jaenicke 3. Mai 2018 05:39

AW: Das Handle ist ungültig
 
Zitat:

Zitat von EWeiss (Beitrag 1401126)
seltsam :evil:
Ich kann machen was ich will beide WideChars ergeben immer .. nothing. :)

Ich habe es kurz mit "echten" Anwendungen getestet (hatte bisher immer nur den Systemsound aktiv), da steht in der Tat nichts drin. Also habe ich einfach mal in die Doku geschaut... und siehe da, das Verhalten ist so dokumentiert und vollkommen korrekt. ;-)

https://msdn.microsoft.com/de-de/lib...(v=vs.85).aspx
Zitat:

If the client has not called IAudioSessionControl::SetDisplayName to set the display name, the string will be empty. Rather than display an empty name string, the Sndvol program uses a default, automatically generated name to label the volume control for the audio session.
Wie es der Windows Mixer macht steht also auch direkt da, der geht vermutlich über die Process-ID.

GetSessionIdentifier gibt übrigens immer etwas zurück, auch unter Windows 7.

EWeiss 3. Mai 2018 06:47

AW: Das Handle ist ungültig
 
Zitat:

Wie es der Windows Mixer macht steht also auch direkt da, der geht vermutlich über die Process-ID.
Ich mache nichts anderes.. und gehe ebenfalls nur über die ID.

Ich liste alle Prozesse auf addiere diese zu einer liste und prüfe ob irgendeiner davon
diese Bedingung erfüllt.

Delphi-Quellcode:
if State <> uint(TAudioSessionState.AudioSessionStateExpired) then
Zitat:

GetSessionIdentifier gibt übrigens immer etwas zurück, auch unter Windows 7.
Hmm... kleines Beispiele ?
Wenn du das meinst ? Ja!
Zitat:

SessionIdentifier = {0.0.0.00000000}.{e457a6b5-b413-4304-9b72-f8ba7de1d36a}|\Device\HarddiskVolume1\Program Files (x86)
Was ich bei @TiGü gesehen habe hatte vergessen DisplayName und IconPath frei zu geben.
Delphi-Quellcode:
CoTaskMemFree(pDisplayName);
(Ok war\ist eh leer von daher erst mal egal)

Zitat:

und siehe da, das Verhalten ist so dokumentiert und vollkommen korrekt.
Korrekt ja laut Doku aber in meinen Augen.. sorry Schwachsinn.
Es wird also geprüft ob es sich um eine echte Anwendung handelt, wenn ja wird nix zurück gegeben um zu verhindern
das Developer den Mixer in dieser Art nachahmen können.
Diese Funktion ist dann einfach Nutzlos.

gruss

EWeiss 3. Mai 2018 07:08

AW: Das Handle ist ungültig
 
Mein Problem ist also..
Ich muss den DisplayNamen bzw.. den Pfad zum IconPath selbst vorher setzen.

Macht irgendwo keine sinn.
Es wären zwei funktionsaufrufe die letztendlich für die Katz sind wenn ich anschließend selbst noch das Icon bzw. den DisplayNamen selbst noch suchen muss.

Das würde also ausreichen.
Delphi-Quellcode:
FAudioSessionList[Index].DisplayName := pDisplayName;
if AudioSessionInfo(Index).DisplayName = '' then
  FAudioSessionList[Index].DisplayName := ExtractFileName
  (ChangeFileExt(GetBaseNameFromPID(PID), ''));
CoTaskMemFree(pDisplayName);
kann mir das dann schenken und muss anstelle dessen versuchen den Korrekten Namen zu analysieren.
Delphi-Quellcode:
GetBaseNameFromPID


Hmm.. was für ein schmarrn ;)

gruss

TiGü 3. Mai 2018 08:53

AW: Das Handle ist ungültig
 
Zitat:

Zitat von EWeiss (Beitrag 1401129)
Zitat:

und siehe da, das Verhalten ist so dokumentiert und vollkommen korrekt.
Korrekt ja laut Doku aber in meinen Augen.. sorry Schwachsinn.
Es wird also geprüft ob es sich um eine echte Anwendung handelt, wenn ja wird nix zurück gegeben um zu verhindern
das Developer den Mixer in dieser Art nachahmen können.
Diese Funktion ist dann einfach Nutzlos.

Kann es sein, dass du den von jaenicke zitierten Abschnitt nicht so ganz verstanden hast?
Hier nochmal auf Deutsch:

Zitat:

Zitat von MSDN
Wenn der Client IAudioSessionControl::SetDisplayName nicht aufgerufen hat, um den Anzeigenamen zu setzen, ist der String leer.
Anstatt einen leeren Namenstring anzuzeigen, verwendet das Programm Sndvol einen automatisch generierten Standardnamen, um den Lautstärkeregler für die Audiositzung zu beschriften.


Was heißt das also?
Es besagt, dass es für Programme wie Skype, Chrome, Internet Explorer, FireFox, WinAmp, VLC KEINE Pflicht ist, das Interface IAudioSessionControl zu implementieren bzw. die Methode SetDisplayName aufzurufen.

Keine Ahnung, was du eigentlich bezwecken möchtest???
Wahrscheinlich setzt du einfach voraus, dass wir alle deine Beiträge lesen und wir daher genau wissen, woran du arbeitest und den Rest können wir uns gefälligst selber zusammenreimen.
Wäre ja auch noch schöner, ein vollständiges Gegeben, Gesucht und zumindest einen Lösungsansatz zu verlangen. :o

Möchtest eine der folgenden Informationen?

Code:
- - - - - - - - - - - - - - - - - -
SessionIndex:             0
SessionIdentifier:        {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|#%b{A9EF3FD9-4240-455E-A4D5-F2B3301887B2}
SessionInstanceIdentifier: {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|#%b{A9EF3FD9-4240-455E-A4D5-F2B3301887B2}|12%b#
DisplayName:              @%SystemRoot%\System32\AudioSrv.Dll,-202
IconPath:                 @%SystemRoot%\System32\AudioSrv.Dll,-203
Process ID:               0
- - - - - - - - - - - - - - - - - -
SessionIndex:             1
SessionIdentifier:        {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|\Device\HarddiskVolume4\Program Files (x86)\Google\Chrome\Application\chrome.exe%b{00000000-0000-0000-0000-000000000000}
SessionInstanceIdentifier: {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|\Device\HarddiskVolume4\Program Files (x86)\Google\Chrome\Application\chrome.exe%b{00000000-0000-0000-0000-000000000000}|12%b13524
DisplayName:
IconPath:
Process ID:               13524
ProcessName:              C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- - - - - - - - - - - - - - - - - -
SessionIndex:             2
SessionIdentifier:        {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|\Device\HarddiskVolume4\Program Files (x86)\Skype\Phone\Skype.exe%b{00000000-0000-0000-0000-000000000000}
SessionInstanceIdentifier: {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|\Device\HarddiskVolume4\Program Files (x86)\Skype\Phone\Skype.exe%b{00000000-0000-0000-0000-000000000000}|12%b184
DisplayName:
IconPath:
Process ID:               184
ProcessName:              C:\Program Files (x86)\Skype\Phone\Skype.exe

EWeiss 3. Mai 2018 09:23

AW: Das Handle ist ungültig
 
Zitat:

Kann es sein, dass du den von jaenicke zitierten Abschnitt nicht so ganz verstanden hast?
Habe ich!
Zitat:

Ich muss den DisplayNamen bzw.. den Pfad zum IconPath selbst vorher setzen.
Du hast schon gesehen das ich es mit meinem Programm teste?
Also muss ich hier den DisplayNamen und den Pfad zum Icon selber setzen.. Ist das jetzt deutlich genug?

Zitat:

Möchtest eine der folgenden Informationen?
Die habe ich selber.. wenn du meinen Shot angeschaut hättest wäre es dir aufgefallen.

Du musst mich auch nicht auf diese Art hier belehren das mag ich gar nicht!. :evil:
Zudem bringen mir deine Infos nichts denn die Strings bleiben wie zuvor leer.

Auch wenn bsp. Winamp
Zitat:

VLC KEINE Pflicht ist, das Interface IAudioSessionControl zu implementieren bzw. die Methode SetDisplayName aufzurufen.
es nicht implementiert kommt MS mit seinem Mixer an den Namen sowie das Icon heran.

Zum IExplorer habe ich ja schon einen Shot geschickt. (Es geht also)
So nun mit all deinen klugen Sprüchen (Belehrungen) wenn MS es kann warum funktioniert es dann nicht bei mir?

Ach vergiss es einfach.. Ich finde eine Lösung dessen kannst du sicher sein!

gruss

jaenicke 3. Mai 2018 09:27

AW: Das Handle ist ungültig
 
Zitat:

Zitat von EWeiss (Beitrag 1401150)
Auch wenn bsp. Winamp
Zitat:

VLC KEINE Pflicht ist, das Interface IAudioSessionControl zu implementieren bzw. die Methode SetDisplayName aufzurufen.
es nicht implementiert kommt MS mit seinem Mixer an den Namen sowie das Icon heran.

Richtig, aber eben nicht über eine fertige API, sondern indem es selbst eine passende Beschriftung ermittelt, wie es ja auch in der Doku steht, ich vermute z.B. aus dem Prozessnamen, Fenstertiteln oder ähnlichem.

EWeiss 3. Mai 2018 09:31

AW: Das Handle ist ungültig
 
Zitat:

Zitat von jaenicke (Beitrag 1401152)
Zitat:

Zitat von EWeiss (Beitrag 1401150)
Auch wenn bsp. Winamp
Zitat:

VLC KEINE Pflicht ist, das Interface IAudioSessionControl zu implementieren bzw. die Methode SetDisplayName aufzurufen.
es nicht implementiert kommt MS mit seinem Mixer an den Namen sowie das Icon heran.

Richtig, aber eben nicht über eine fertige API, sondern indem es selbst eine passende Beschriftung ermittelt, wie es ja auch in der Doku steht, ich vermute z.B. aus dem Prozessnamen, Fenstertiteln oder ähnlichem.

Danke und genau das bin ich am versuchen wenn der Name\Pfad zum Icon Leer ist.
Was ich möchte.. das TAudioVolume auf einen Kompletten Mixer erweitern so wie er sichtbar wird wie wenn man im Tray auf das Lautsprecher Symbol klickt.

EDIT:
Schlage mich jetzt mit der Änderung rum.
Durch die Änderung auf GetProcessImageFileNameW habe ich nun Probleme den korrekten Pfad zu Anwendung zu finden um das Icon zu setzen.
Muss diesen Pfad
Zitat:

\Device\HarddiskVolume1\Program Files\Windows Sidebar\sidebar.exe
in einem gültigen umwandeln.

Und so geht es immer weiter.. ;)

Delphi-Quellcode:
a := MAX_PATH;
GetVolumePathNamesForVolumeNameW(PWideChar(FAudioSessionList[Index].IconPath),
  @FullPath, MAX_PATH, a);

SetSysItemIcon(FullPath);
FullPath ist leer.. :)

gruss

TiGü 3. Mai 2018 09:48

AW: Das Handle ist ungültig
 
Zitat:

...wenn MS es kann warum funktioniert es dann nicht bei mir?
Spruch des Tages, Internet kann zu! :spin2:


Du hast den vollständigen Processpfad/-dateinamen, du hast das Process Handle, du hast die Process ID...woran scheitert es jetzt genau?

Hier noch ein Schups in die richtige Richtung, weil heute Donnerstag ist:

Delphi-Quellcode:
procedure ExtractIcons(const FileName: string);
var
  IconCount: Cardinal;
  I: Integer;
  IconHandle: HICON;
begin
  IconCount := ExtractIcon(HInstance, PChar(FileName), UINT(-1));
  if IconCount <> 0 then
  begin
    for I := 0 to IconCount - 1 do
    begin
      IconHandle := ExtractIcon(HInstance, PChar(FileName), I);
      if IconHandle <> 0 then
      begin
        // mach irgendwas mit dem Icon Handle
        // . . .

        // am Ende freigeben
        DestroyIcon(IconHandle);
      end;
    end;
  end;
end;

TiGü 3. Mai 2018 09:51

AW: Das Handle ist ungültig
 
Zitat:

Zitat von EWeiss (Beitrag 1401153)
EDIT:
Schlage mich jetzt mit der Änderung rum.
Durch die Änderung auf GetProcessImageFileNameW habe ich nun Probleme den korrekten Pfad zu Anwendung zu finden um das Icon zu setzen.
Muss diesen Pfad
Zitat:

\Device\HarddiskVolume1\Program Files\Windows Sidebar\sidebar.exe
in einem gültigen umwandeln.

Delphi-Quellcode:
                      SessionControl2.GetProcessId(ProcessId);
                      Writeln('Process ID:               ', ProcessId);

                      ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessId);
                      if ProcessHandle <> 0 then
                      begin
                        if GetModuleFileNameEx(ProcessHandle, 0, ProcessName, MAX_PATH) <> 0 then
                        begin
                          Writeln('ProcessName:              ', ProcessName);
                        end;
                        CloseHandle(ProcessHandle);
                      end;

EWeiss 3. Mai 2018 09:56

AW: Das Handle ist ungültig
 
Zitat:

Zitat von TiGü (Beitrag 1401161)
Zitat:

Zitat von EWeiss (Beitrag 1401153)
EDIT:
Schlage mich jetzt mit der Änderung rum.
Durch die Änderung auf GetProcessImageFileNameW habe ich nun Probleme den korrekten Pfad zu Anwendung zu finden um das Icon zu setzen.
Muss diesen Pfad
Zitat:

\Device\HarddiskVolume1\Program Files\Windows Sidebar\sidebar.exe
in einem gültigen umwandeln.

Delphi-Quellcode:
                      SessionControl2.GetProcessId(ProcessId);
                      Writeln('Process ID:               ', ProcessId);

                      ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessId);
                      if ProcessHandle <> 0 then
                      begin
                        if GetModuleFileNameEx(ProcessHandle, 0, ProcessName, MAX_PATH) <> 0 then
                        begin
                          Writeln('ProcessName:              ', ProcessName);
                        end;
                        CloseHandle(ProcessHandle);
                      end;

Das hatten wir schon Seiten vorher... aber trotzdem Danke.
Nicht nur GetModuleBaseName (gibt den ExeNamen ohne Pfad zurück) verursacht diesen Fehler auch GetModuleFileNameEx (ExeNamen inklusive Pfad)

Hier gibt es den Fehler das mein Handle ungültig ist.
Deshalb haben wir es doch geändert.

Zitat:

Hier noch ein Schups in die richtige Richtung, weil heute Donnerstag ist:
Danke hatte ich schon fertig.. und ist mir bekannt.
Delphi-Quellcode:
procedure TAudioVolume.SetSysItemIcon(wsItems: PWideChar);
var
  fi: TSHFileInfo;
begin

  ZeroMemory(@fi, sizeof(TSHFileInfo));
  if SHGetFileInfo(wsItems, 0, fi, sizeof(TSHFileInfo),
    SHGFI_DISPLAYNAME Or SHGFI_SYSICONINDEX or SHGFI_LARGEICON or SHGFI_ICON) <> 0 then

  Icon := fi.HICON;

end;
gruss

TiGü 3. Mai 2018 10:17

AW: Das Handle ist ungültig
 
Zitat:

Zitat von EWeiss (Beitrag 1401164)
Das hatten wir schon Seiten vorher... aber trotzdem Danke.
Nicht nur GetModuleBaseName (gibt den ExeNamen ohne Pfad zurück) verursacht diesen Fehler auch GetModuleFileNameEx (ExeNamen inklusive Pfad)

Hier gibt es den Fehler das mein Handle ungültig ist.
Deshalb haben wir es doch geändert.

Gehen wir nochmal ganz doll zurück zum ersten Beitrag:

Delphi-Quellcode:
FAudioSessionList[Index].DisplayName := GetBaseNameFromPID(PID);


Woher kommt die Variable PID? Oder um die Frage vielleicht klarer zu stellen: Wie ermittelst du den Wert von PID?
Wenn die Process ID gültig ist - also wie von mir gezeigt per einzelner SessionControl-Instanz geholt - dann muss OpenProcess ein gültiges Handle liefern.

Ansonsten machst du was falsch.
Laufen die Programme vielleicht als Administrator ("Als Administrator ausführen")? Dann kann OpenProcess so nicht funktionieren.

Vergleiche mit Konsolenausgabe in Beitrag #24:
https://www.delphipraxis.net/1401141-post24.html

EWeiss 3. Mai 2018 10:27

AW: Das Handle ist ungültig
 
Zitat:

Laufen die Programme vielleicht als Administrator ("Als Administrator ausführen")? Dann kann OpenProcess so nicht funktionieren.
IExplorer und SideBar? denke schon.

Zitat:

Woher kommt die Variable PID? Oder um die Frage vielleicht klarer zu stellen: Wie ermittelst du den Wert von PID?
Delphi-Quellcode:
            HR := SessionControl2.GetProcessID(PID);
            if Succeeded(HR) then
            begin
              FAudioSessionList[Index].ProcessID := intToStr(PID);
              HR := SessionControl2.GetState(State);
              if Succeeded(HR) then
              begin
                if PID = ProcId then
                begin
                  if State <> uint(TAudioSessionState.AudioSessionStateExpired) then
                  begin
Zitat:

Ansonsten machst du was falsch.
möglich ;)
Sonst würde ja alles funktionieren.

Anwendung..
Delphi-Quellcode:
    AudioVolume[i].GetSessionCount(AudioVolume1.Device);
    if AudioVolume1.AudioSessionInfo(i).PID <> 0 then
Delphi-Quellcode:
function TAudioVolume.GetSessionCount(AudioDevice: IMMDevice): integer;
var
  SessionControl2: IAudioSessionControl2;
  SessionControl: IAudioSessionControl;
  pEnumerator: IAudioSessionEnumerator;
  SCount: Integer;
  PID, ProcId: DWORD;
  State: uint;
  HR: HResult;
  i, j: integer;
  ProcList: TStringList;
begin

  ProcList := TStringList.Create;
  SCount := 0;

  GetProzessList(ProcList);
  if Assigned(SessionManager2) then
  begin
    HR := AudioDevice.Activate(IID_IAudioSessionManager2, CLSCTX_ALL, nil, IUnknown(SessionManager2)
      );
    if Succeeded(HR) then
    begin
      // get SessionQuery
      HR := SessionManager2.GetSessionEnumerator(pEnumerator);
      if Succeeded(HR) then
      begin
        HR := pEnumerator.GetCount(FSessionCount);
        if Succeeded(HR) then
          Setlength(FAudioSessionList, FSessionCount + 1);
        if Succeeded(HR) then
        begin
          for i := 0 to FSessionCount - 1 do
          begin
            HR := pEnumerator.GetSession(i, SessionControl);
            if Succeeded(HR) then
            begin
              HR := SessionControl.QueryInterface(IAudioSessionControl2, SessionControl2);
              if Succeeded(HR) then
              begin
                HR := SessionControl2.GetProcessID(PID);
                if Succeeded(HR) then
                begin
                  HR := SessionControl2.GetState(State);
                  if Succeeded(HR) then
                  begin
                    for j := 0 to ProcList.Count - 1 do
                    begin
                      ProcId := GetProcessIdFromModuleName(pWideChar(ProcList[j]));
                      if (PID = ProcId) and (PID <> GetCurrentProcessId) then
                      begin
                        if State <> uint(TAudioSessionState.AudioSessionStateExpired) then
                        begin
                          FAudioSessionList[i].ActiveSession := IntToStr(i);
                          FAudioSessionList[i].PID := PID;
                          inc(SCount, i);
                        end;
                      end;
                    end;
                  end;
                end;
              end;
              SessionControl2 := nil;
            end;
            SessionControl := nil;
          end;
        end;
      end;
      pEnumerator := nil;
    end;
  end;
  ProcList.free;
  Result := SCount;
end;
Ok hier GetSessionCount muss ich noch was tun es dauert einfach zu lange für jedes control diese Funktion zu durchlaufen.

gruss

KodeZwerg 3. Mai 2018 10:41

AW: Das Handle ist ungültig
 
Ich gab Dir hier eine Funktion, wenn Du die mit Deiner ermittelten PID aufrufst, was kommt da raus, das was bei Dir auch rauskommen sollte?

EWeiss 3. Mai 2018 10:47

AW: Das Handle ist ungültig
 
Zitat:

Zitat von KodeZwerg (Beitrag 1401181)
Ich gab Dir hier eine Funktion, wenn Du die mit Deiner ermittelten PID aufrufst, was kommt da raus, das was bei Dir auch rauskommen sollte?

Ach mano ...
Ich sagte doch schon das habe ich alles schon durch deshalb habe ich doch den Thread hier erstellt.

Ich sammle auch nicht die Funktionen andere Leute sondern erarbeite sie selbst.
Es hat bei meiner Funktion

Delphi-Quellcode:
function TAudioVolume.GetPathFromPID(const PID: DWORD): string;
var
  hProcess: THandle;
  path: array [0 .. MAX_PATH - 1] of WChar;
begin

  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
    try
      if GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) = 0 then
        RaiseLastOSError;
      Result := path;
    finally
      CloseHandle(hProcess)
    end
  else
    RaiseLastOSError;
end;
gekracht wegen ungültigen Handle.
Bei der Sidebar und dem IExplorer bei normalen Anwendungen seltsamer weise nicht.

gruss

Neutral General 3. Mai 2018 11:46

AW: Das Handle ist ungültig
 
Ich werfe einfach mal was in den Raum obwohl ich mir nicht 100%ig sicher bin ob das relevant ist.
Kann es vllt. ein 32-Bit <-> 64-Bit Problem sein, dass du in deiner 32-Bit Anwendung vllt. keine 64-Bit Prozesse öffnen kannst/darfst?

Sowas kam mir nur in den Kopf.. kann aber durchaus sein, dass ich Unsinn rede.

EWeiss 3. Mai 2018 11:50

AW: Das Handle ist ungültig
 
Zitat:

Zitat von Neutral General (Beitrag 1401190)
Ich werfe einfach mal was in den Raum obwohl ich mir nicht 100%ig sicher bin ob das relevant ist.
Kann es vllt. ein 32-Bit <-> 64-Bit Problem sein, dass du in deiner 32-Bit Anwendung vllt. keine 64-Bit Prozesse öffnen kannst/darfst?

Sowas kam mir nur in den Kopf.. kann aber durchaus sein, dass ich Unsinn rede.

Wäre möglich aber um das genau feststellen zu können müsste man das Projekt nach 64Bit Portieren.
Nur dafür fehlen mir die Möglichkeiten.

Auf der anderen Seite dürfte dann gar nichts gehen denn ich denke das die API ja letztendlich auch auf die 64Bit Prozesse der Soundkarten Treiber zugreift oder?
Oder aber die werden umgelenkt. Dann müsste es aber funktionieren.

gruss

Zacherl 3. Mai 2018 11:58

AW: Das Handle ist ungültig
 
Zitat:

Zitat von Neutral General (Beitrag 1401190)
Kann es vllt. ein 32-Bit <-> 64-Bit Problem sein, dass du in deiner 32-Bit Anwendung vllt. keine 64-Bit Prozesse öffnen kannst/darfst?

MSDN-Library durchsuchenOpenProcess ist unproblematisch. Es gibt aber tatsächlich einige APIs, welche da Probleme bereiten. Alles was intern MSDN-Library durchsuchenZwReadVirtualMemory bzw. MSDN-Library durchsuchenReadProcessMemory verwendet, sind dafür beispielsweise Kandidaten. Hierzu zählt auch die verwendete MSDN-Library durchsuchenGetModuleFilenameEx API.

Siehe hier:
https://www.delphipraxis.net/160046-...ermitteln.html (Konvertierung vom NT-Pfad zu standard DOS-Pfad kann man sich hier auch anschauen)

Edit:
Habe grade unter Win10 nochmal geschaut (mein Post von damals ist ja schon ein wenig in die Jahre gekommen) und das Verhalten hat sich scheinbar geändert. Mitlerweile funktioniert GetModuleFilenameEx wohl auch bei 64-Bit Prozessen.

EWeiss 3. Mai 2018 12:04

AW: Das Handle ist ungültig
 
Danke dir werde mir das mal anschauen.

EDIT:
Also kein Problem scheint zu funktionieren.
Auch das Icon bekomme ich nun. Muss das jetzt erst mal zuweisen um das Ergebnis sehen zu können.

gruss

TiGü 3. Mai 2018 12:56

AW: Das Handle ist ungültig
 
Delphi-Quellcode:
for j := 0 to ProcList.Count - 1 do
                    begin
                      ProcId := GetProcessIdFromModuleName(pWideChar(ProcList[j]));
                      if (PID = ProcId) and (PID <> GetCurrentProcessId) then
                      begin
                        if State <> uint(TAudioSessionState.AudioSessionStateExpired) then
                        begin
                          FAudioSessionList[i].ActiveSession := IntToStr(i);
                          FAudioSessionList[i].PID := PID;
                          inc(SCount, i);
                        end;
                      end;
                    end;
Warum eigentlich der Vergleich von PID mit der ProcID, die du über die gefüllte ProcList holst? Wozu dient das?
Die PID, die du mit SessionControl2.GetProcessID(PID); ermittelst, gibt dir doch eine gültige Process ID einer Audiosession?

Der ieexplore lässt sich ohne große Verrenkungen per OpenProcess ermitteln:
Code:
SessionIndex:             2
SessionIdentifier:        {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|#%b{63C9CE85-D9FF-4AE9-A105-C25B9A69E0C8}
SessionInstanceIdentifier: {0.0.0.00000000}.{18e53891-8712-4c0d-9aab-e23e4b813b96}|#%b{63C9CE85-D9FF-4AE9-A105-C25B9A69E0C8}|12%b#
DisplayName:
IconPath:
Process ID:               5444
ProcessName:              C:\Program Files (x86)\Internet Explorer\iexplore.exe
ProcessName wird über OpenProcess() und GetModuleFileNameEx() geholt.

TiGü 3. Mai 2018 13:01

AW: Das Handle ist ungültig
 
Du solltest deiner
Delphi-Quellcode:
TAudioVolume.GetPathFromPID
Methode in der ersten Zeile übrigens ein
Delphi-Quellcode:
Result := '';
gönnen. Sicher ist sicher!


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:47 Uhr.
Seite 1 von 3  1 23      

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