Что бы было более понятно о чем идет речь, я описываю интерфейс
DXGI, а точнее переношу функционал из данного API себе в проект, для некоторых манипуляций.
Описываю
IDXGIObject:
[ComImport]
[Guid("aec22fb8-76f3-4639-9be0-28eb43a67a2e")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDXGIObject
{
HResult SetPrivateData(ref Guid name, uint dataSize, IntPtr dataPtr);
HResult SetPrivateDataInterface(ref Guid name, [MarshalAs(UnmanagedType.IUnknown)] object unknownInterfaceObject);
HResult GetPrivateData(ref Guid name, out int dataSize, out IntPtr dataPtr);
HResult GetParent(ref Guid rIId, out object pParent);
}
Далее наследую данный интерфейс, и определяю новый интерфейс
IDXGIFactory:
[ComImport]
[Guid("7b7166ec-21c7-44ae-b21a-c9ae321ae369")]
public interface IDXGIFactory : IDXGIObject
{
HResult EnumAdapters(uint numAdapter, [MarshalAs(UnmanagedType.IUnknown)] out object adapter);
HResult MakeWindowAssociation(IntPtr windowHandle, uint flags);
HResult GetWindowAssociation(out IntPtr outHandleWindow);
HResult CreateSwapChain(IntPtr lpIUnknown, IntPtr ptr, out IntPtr outPtr);
HResult CreateSoftwareAdapter(IntPtr moduleHandle, out IntPtr outPtr);
}
Так же имеется небольшой
Manager класс, для инициализации интерфейса
IDXGIFactory:
public static class Manager
{
private static Guid _dxgiFactory1Guid =
new Guid("7b7166ec-21c7-44ae-b21a-c9ae321ae369");
public static HResult CreateDxgiFactory(out IDXGIFactory factory)
{
HResult result = (HResult)CreateDXGIFactory(ref _dxgiFactory1Guid, out object tmpObject);
factory = tmpObject as IDXGIFactory;
return result;
}
[DllImport("dxgi.dll")]
private static extern long CreateDXGIFactory(ref Guid refIId,
[MarshalAs(UnmanagedType.IUnknown)] out object factoryPtr);
}
Так, все хорошо вызвалось, получили объект
IDXGIFactory、далее, пытаемся выполнить перечисление доступных адаптеров:
internal class Program
{
private static void Main(string[] args)
{
HResult result = Manager.CreateDxgiFactory(out IDXGIFactory factory);
if (result != HResult.Ok)
{
Marshal.ThrowExceptionForHR((int)result);
}
uint count = 0;
try
{
while (factory.EnumAdapters(count, out _) != HResult.ErrNotFound)
{
count++;
}
}
catch (COMException e)
{
Console.WriteLine(e);
}
IDXGIAdapter[] adapters = new IDXGIAdapter[count];
for (uint i = 0; i < count; i++)
{
factory.EnumAdapters(i, out object adapter);
adapters[i] = adapter as IDXGIAdapter;
}
foreach (IDXGIAdapter dxgiAdapter in adapters)
{
dxgiAdapter.GetDesc(out DxgiAdapterDesc dxgiAdapterDesc);
Debug.WriteLine(
$"IDXGIAdapter {dxgiAdapterDesc.Name} refs count = {Marshal.ReleaseComObject(dxgiAdapter)}",
"INFO");
}
adapters = null;
int refs = Marshal.ReleaseComObject(factory);
}
}
Сам вызов метода
EnumAdapters выполняется успешно、и возвращает
IDXGIAdapter、но, как только перечеслитель становится больше чем доступно адаптеров、бросается исключение:
Объект не найден. При вызове IDXGIFactory::EnumAdaptes отсутствует адаптер с указанным порядковым номером. (Исключение из HRESULT: 0x887A0002)
Как и почему выкидывается исключение、ведь по сути сам программист должен обрабатывать такие ошибки。
Как избавиться от данных выбросов если они на самом деле не нужны?