L
L
LLENN2018-11-25 10:16:11
C++ / C#
LLENN, 2018-11-25 10:16:11

Is an exception thrown when calling the Com object's method instead of the execution result?

To make it more clear what is at stake, I describe the DXGI interface , or rather, I transfer the functionality from this API to my project, for some manipulations.
Describing 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);
}

Next, I inherit this interface, and define a new IDXGIFactory interface :
[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);
}

There is also a small Manager class to initialize the IDXGIFactory interface :
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);
}

So, everything came out well, we got the IDXGIFactory object 、next, we try to enumerate the available adapters:
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);
    }
}

The EnumAdapters method call itself succeeds、and returns an IDXGIAdapter、but as soon as the enumerator becomes more than available adapters、an exception is thrown:
Object not found. When calling IDXGIFactory::EnumAdaptes, there is no adapter with the specified ordinal. (Exception from HRESULT: 0x887A0002)

How and why an exception is thrown、after all, in fact, the programmer himself must handle such errors。
How to get rid of these throws if they are not really needed?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
LLENN, 2018-11-25
@LLENN

It turns out that COM Interop converts all unsuccessful returned HRESULTs into exceptions by default .
It's worth adding the [PreserveSig] attribute to prevent this:
[PreserveSig] int EnumAdapters(...);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question