【问题标题】:Exception calling "IAudioSessionManager2.GetSessionEnumerator()" in Delphi XE2在 Delphi XE2 中调用“IAudioSessionManager2.GetSessionEnumerator()”的异常
【发布时间】:2012-09-21 13:07:36
【问题描述】:

下面的代码,在Delphi XE2 Win32下编译,在Win 7 64位下运行,执行“AudioSessionManager2.GetSessionEnumerator”行时产生如下异常:

“Project22.exe 引发异常类 $C0000005 并带有消息‘访问冲突在 0x7027edb2:写入地址 0x0051ced6’”

我对异常类或它们的含义缺乏了解,因此我不知道异常的含义或如何修复它。

这是引发异常的代码(用于调试代码的断言):

var
  HRES: HRESULT;
  DeviceEnumerator: IMMDeviceEnumerator;
  DefaultDevice: IMMDevice;
  AudioSessionManager2: IAudioSessionManager2;
  Enumerator: IAudioSessionEnumerator;
begin

  CoInitialize( nil );

  HRES := CoCreateInstance( CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, DeviceEnumerator );
  Assert( Succeeded( HRES ) );

  HRES := DeviceEnumerator.GetDefaultAudioEndpoint( eRender, eMultimedia, DefaultDevice );
  Assert( Succeeded( HRES ) );

  HRES := DefaultDevice.Activate( IID_IAudioSessionManager2, CLSCTX_ALL, nil, IUnknown( AudioSessionManager2 ) );
  Assert( Succeeded( HRES ) );

  HRES := AudioSessionManager2.GetSessionEnumerator( Enumerator );  // <- EXCEPTION HERE
  Assert( Succeeded( HRES ) );

  [snip]

我使用来自MFPack on Google Code 的核心音频定义,IAudioSessionManager2 和 IAudioSessionEnumerator 接口如下所示:

IAudioSessionManager2 = interface(IUnknown)
['{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}']
  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;

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;

我相信接口定义正确,我还仔细检查了 GUID。

由于在 Visual Studio 2012(Win32 项目)下按预期执行相同的指令序列,我怀疑问题出在我的代码(这里有点疑问)、Core Audio 接口定义或 Delphi 上。 VS中运行的C++代码如下:

IMMDeviceEnumerator *DeviceEnumerator = NULL;
IMMDevice* DefaultDevice = NULL;
IAudioSessionManager2* AudioSessionManager = NULL;
IAudioSessionEnumerator* Enumerator = NULL;
HRESULT HR;

HR = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&DeviceEnumerator );
HR = DeviceEnumerator->GetDefaultAudioEndpoint( eRender, eMultimedia, &DefaultDevice );
HR = DefaultDevice->Activate( __uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL,(void**)&AudioSessionManager );
HR = AudioSessionManager->GetSessionEnumerator( &Enumerator );

使用 C++ 代码,我可以正确检索会话枚举器并使用 GetCount 等。

我花了无数个小时试图找出我的代码出了什么问题,但我仍然一无所知,所以任何帮助将不胜感激。

【问题讨论】:

  • 您不应该将DefaultDevice.Activate() 的最后一个参数类型转换为IUnknown,将其保留为原始类型,就像使用CoCreateInstance() 一样。您还应该使用OleCheck() 而不是Assert()
  • 感谢您的建议,雷米。 Activate() 被声明为将 IUnknown 作为其最后一个参数,这就是我将其转换为这样的原因。我确实尝试将声明更改为各种其他类型,包括“out ppInterface”,但没有任何效果。我刚刚在 C++ Builder 中尝试了 C++ 代码,它也按预期工作。几天的工作,我无法让它工作。我在想用 C++ 做一个 DLL 可能会更容易,因为我不能花更多的时间在这上面。
  • 最后一个参数应该是一个无类型的out,就像CoCreateInstance() 使用的一样。另一种方法是PPointer,使用@ 运算符传递变量,就像在C++ 中一样。

标签: delphi windows-7 delphi-xe2 core-audio


【解决方案1】:

根据 MSDN,IAudioSessionManager2 应该继承自 IAudioSessionManager

type
  IAudioSessionManager2 = interface(IAudioSessionManager)
  ...

【讨论】:

  • 你是对的。根据您链接的 MSDN 页面,IAudioSessionManager2 基于IAudioSessionManager,而IAudioSessionManager 来自IUnknown
  • 这很完美!我将检查其余接口是否存在此类疏忽,并希望能够联系维护它们的人员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
相关资源
最近更新 更多