Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.12.2024, 23:19   #1
kav01
 
Регистрация: 22.09.2010
Сообщений: 4
По умолчанию Использование интерфейсов в консольных приложениях

Доброго времени!
Уважаемые гуру, подскажите, есть ли какие-то принципиальные различия при использовании интерфейсов в GUI и в консольных приложениях?

Суть вопроса в следующем:
Имеется код с использованием интерфейсов, который прекрасно работает в GUI (Delphi 7).
При переносе кода в консольное приложение возникает ошибка:

Exception EAccessViolation in module adevdef.exe at 000521C9.
Access violation at address 004521C9 in module 'adevdef.exe'. Read of address 00000000.


Код:
program adevdef;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, Classes,  ActiveX, OleServer, MMSystem, ShlObj;

const
  CLSID_MMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  Class_PolicyConfigClient: TGUID ='{870af99c-171d-4f9e-af0d-e63df40c2bc9}';

  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_IAudioEndpointVolume: 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}';
  IID_IPropertyStore: TGUID = '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}';

  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
  _tagpropertykey = packed record
    fmtid: TGUID;
    pid: DWORD;
  end;

  PROPERTYKEY = _tagpropertykey;
  PPropertyKey = ^TPropertyKey;
  TPropertyKey = _tagpropertykey;

const
  PKEY_Device_FriendlyName: TPropertyKey = (fmtid:(D1:$a45c254e;D2:$df1c;D3:$4efd;D4:($80,$20,$67,$d1,$46,$a8,$50,$e0));pid:14);

type
  IAudioEndpointVolumeCallback = interface(IUnknown)
    ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
  end;

  IAudioEndpointVolume = interface(IUnknown)
    ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
  end;

  IAudioMeterInformation = interface(IUnknown)
    ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
  end;

  IPropertyStore = interface(IUnknown)
    ['{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}']
    function GetCount(out cProps: LongWord): HResult; stdcall;
    function GetAt(iProp: LongWord; out pkey: _tagpropertykey): HResult; stdcall;
    function GetValue(const key: TPropertyKey; out pv: TPROPVARIANT): HResult; stdcall;
    function SetValue(const key: TPropertyKey; out propvar: TPROPVARIANT): HResult; stdcall;
    function Commit: HResult; stdcall;
  end;

  IMMDevice = interface(IUnknown)
    ['{D666063F-1587-4E43-81F1-B948E807363F}']
    function Activate(const refId: TGUID; dwClsCtx: DWORD; pActivationParams: PInteger; out pEndpointVolume: IAudioEndpointVolume): HRESULT; stdCall;
    function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): HRESULT; stdcall;
    function GetId(out ppstrId: PWideChar): HRESULT; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
    ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
    function GetCount(out pcDevices: UINT): HRESULT; stdcall;
    function Item(nDevice: UINT; out ppDevice: IMMDevice): HRESULT; stdcall;
  end;

  IMMNotificationClient = interface(IUnknown)
    ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
  end;

  IMMDeviceEnumerator = interface(IUnknown)
    ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; out DevCollection: IMMDeviceCollection): HRESULT; stdcall;
  end;

  IPolicyConfig = interface(IUnknown)
    ['{f8679f50-850a-41cf-9c72-430f290290c8}']
      function GetMixFormat(a: PWideChar; var b: TWAVEFORMATEX): HRESULT; stdcall;
      function GetDeviceFormat(a: PWideChar; b: integer; var c: TWAVEFORMATEX): HRESULT; stdcall;
      function ResetDeviceFormat(a: PWideChar): HRESULT; stdcall;
      function SetDeviceFormat(a: PWideChar; var b: TWAVEFORMATEX; var c: TWAVEFORMATEX): HRESULT; stdcall;
      function GetProcessingPeriod(a: PWideChar; b: integer; c: PINT64; d: PINT64): HRESULT; stdcall;
      function SetProcessingPeriod(a: PWideChar; b: PINT64): HRESULT; stdcall;
      function GetShareMode(a: PWideChar; b: pointer{struct DeviceShareMode *}): HRESULT; stdcall;
      function SetShareMode(a: PWideChar; b: pointer{struct DeviceShareMode *}): HRESULT; stdcall;
      function GetPropertyValue(devID: PWideChar; const Key: _tagpropertykey; V: TPROPVARIANT): HRESULT; stdcall;
      function SetPropertyValue(devID: PWideChar; const Key: _tagpropertykey; V: TPROPVARIANT): HRESULT; stdcall;
      function SetDefaultEndpoint(wszDeviceID: PWideChar; ARole: ERole):Hresult; stdcall;
  end;

function GetAudioDeviceList(DevList: TStrings): boolean;
var
  AudioEndpoints: IMMDeviceEnumerator;
  Collection: IMMDeviceCollection;
  Device: IMMDevice;
  Proper: IPropertyStore;
  i: Integer;
  Count_Dev: UINT;
  Id_Dev: PWideChar;
  DId: WideString;
  Prop: IPropertyStore;
  DeviceName: PROPVARIANT;
begin
  Result := false;
  CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, AudioEndpoints);
  AudioEndpoints.EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, Collection);
  Collection.GetCount(Count_Dev);
  for i:=0 to Count_Dev-1 do
  begin
    Collection.Item(i, Device);
    DId := '';
    Result := Succeeded(Device.GetId(Id_Dev)) and (Id_Dev <> nil);
    if Result then
    begin
      DId := WideString(Id_Dev);
      Device.OpenPropertyStore(STGM_READ, Prop);
      Prop.GetValue(PKEY_Device_FriendlyName, DeviceName);
      CoTaskMemFree(Id_Dev);
      DevList.Append(DId + ' ' + PROPVARIANT(DeviceName).pwszVal);
    end;
  end;
end;

procedure SetAudioDeviceDefault(Index: integer);
var
  AudioEndpoints: IMMDeviceEnumerator;
  Collection: IMMDeviceCollection;
  Device: IMMDevice;
  Def_Dev_Ch: IPolicyConfig;
  Id_Dev: PWideChar;
  ID_Dev_Def: WideString;
begin
  CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, AudioEndpoints);
  AudioEndpoints.EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, Collection);
  Collection.Item(Index, Device);
  Device.GetId(Id_Dev);
  if Succeeded(CoCreateInstance(Class_PolicyConfigClient, nil, CLSCTX_INPROC_SERVER, IPolicyConfig, Def_Dev_Ch)) then begin
    if Succeeded(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev, eConsole)) then begin
      Writeln('eConsole')
    end
    else begin
      Writeln(IntToStr(HResult(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev, eConsole))));
    end;
    if Succeeded(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev, eMultimedia)) then begin
      Writeln('eMultimedia')
    end
    else begin
      Writeln(IntToStr(HResult(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev, eMultimedia))));
    end;
    if Succeeded(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev,eCommunications)) then begin
      Writeln('eCommunications')
    end
    else begin
      Writeln(IntToStr(HResult(Def_Dev_Ch.SetDefaultEndpoint(Id_Dev, eCommunications))));
    end;
  end;
end;

var
 i: integer;
 R: boolean;
 MyDevList: TStringList;

begin
  { TODO -oUser -cConsole Main : Insert code here }

  MyDevList := TStringList.Create;
  R := GetAudioDeviceList(MyDevList);
  for i:=0 to MyDevList.Count-1 do
  begin
    Writeln(MyDevList.Strings[i]);
  end;
  if MyDevList <> nil then MyDevList.Free;
end.

Последний раз редактировалось kav01; 03.12.2024 в 23:31.
kav01 вне форума Ответить с цитированием
Старый 04.12.2024, 00:27   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,422
По умолчанию

Стоит проверять на успешность все вызовы. Вызов "CoCreateInstance(CLSID_MMDeviceEnu merator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, AudioEndpoints);" возвращает CO_E_NOTINITIALIZED. Похоже, нужно вызвать CoInitialize. В GUI вызов происходит через Application.Initialize (см. модуль ComObj, процедуру InitComObj).
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 04.12.2024, 00:43   #3
kav01
 
Регистрация: 22.09.2010
Сообщений: 4
По умолчанию

BDA, Спасибо, будем изучать!
kav01 вне форума Ответить с цитированием
Старый 04.12.2024, 00:52   #4
kav01
 
Регистрация: 22.09.2010
Сообщений: 4
По умолчанию

BDA, Огромное спасибо! Добавил CoInitialize(Nil) - заработало:

Код:
...
begin
  { TODO -oUser -cConsole Main : Insert code here }

  CoInitialize(Nil);
  
  MyDevList := TStringList.Create;
  R := GetAudioDeviceList(MyDevList);
  for i:=0 to MyDevList.Count-1 do
  begin
    Writeln(MyDevList.Strings[i]);
  end;
  if MyDevList <> nil then MyDevList.Free;
end.
kav01 вне форума Ответить с цитированием
Старый 04.12.2024, 13:25   #5
kav01
 
Регистрация: 22.09.2010
Сообщений: 4
По умолчанию

да, и на всякий случай:

"В любом потоке, в котором планируется использовать COM объекты все места использования следует обложить CoInitialize(nil); - CoUninitialize."
kav01 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
использование консольных команд Linux из Java application regress000 Общие вопросы по Java, Java SE, Kotlin 3 28.07.2017 11:16
Использование консольных команд [си] Win32Trojan Общие вопросы C/C++ 11 29.09.2009 22:21
Обработка сообщений в консольных приложениях Mixasik Общие вопросы Delphi 2 06.06.2009 22:50
Вопрос по адресной арифметике и Message в консольных приложениях Enikov Помощь студентам 5 01.01.2009 19:44