none
Problema com Interface COM em C# RRS feed

  • Pergunta

  • Olá, 

    preciso declarar uma interface COM em C#, mas estou tendo problemas. Esta interface possui 2 métodos, um GetValue e um SetValue. Cada um deles recebe um GUID para identificar a propriedade desejada, e o outro é um objeto para receber ou enviar o valor.

    Esta interface funciona perfeitamente em C++, e é declarada da seguinte forma:

    interface IAVerCustomControl
    {
    STDMETHOD(SetValue) (THIS_ const GUID* Property, void* pValue) PURE;
    STDMETHOD(GetValue) (THIS_ const GUID* Property, void* pValue) PURE;
    };

    E há a declaração do GUID da mesma para o QueryInterface:

    DEFINE_PROP_GUID(IID_IAVerCustomControl, 
    0x8998bb49, 0x2ff4, 0x4106, 0x95, 0x3c, 0x6d, 0xca, 0xbc, 0x7d, 0x95, 0x7b);

    Tentei declarar da seguinte forma em c#:

    [ComImport]
    [SuppressUnmanagedCodeSecurityAttribute]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
    public interface IAVerCustomControl
    {
          [PreserveSig]
          int SetValue(ref Guid Property, out object pValue);
          [PreserveSig]
          int GetValue(ref Guid Property, out object pValue);
    }

    Se passo um GUID inválido, o HRESULT retorna erro, mas passando um válido ele retorna null no object para o GetValue e retorna erro genérico (E_FAIL) para o SetValue. Jpa tentei modificar alguns atributos, mas sem sucesso.

    Obrigado.

    quarta-feira, 20 de novembro de 2013 19:44

Todas as Respostas

  • Primeiro pra que fazer isso em C#, qual é o seu proposito!?

    Você implementou essa Interface ?

    Bom fico no aguardo!


    Fulvio Cezar Canducci Dias

    terça-feira, 26 de novembro de 2013 11:53
  • Estou alterando um projeto C# já existente, vou adicionar um filtro directshow do SDK da AverMedia (não implementada por mim) e preciso acessar a interface customizada que descrevi. Para utilizá-la com C++, a declaração é a que havia passado:

    interface IAVerCustomControl
    {
    STDMETHOD(SetValue) (THIS_ const GUID* Property, void* pValue) PURE;
    STDMETHOD(GetValue) (THIS_ const GUID* Property, void* pValue) PURE;
    };

    Esta interface funciona sem problemas. No entanto, como o projeto está em C#, procurei declará-la da seguinte forma:

    [ComImport]
    [SuppressUnmanagedCodeSecurityAttribute]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
    public interface IAVerCustomControl
    {
          [PreserveSig]
          int SetValue(ref Guid Property, out object pValue);
          [PreserveSig]
          int GetValue(ref Guid Property, out object pValue);
    }



    No entanto, desta forma não está funcionando. O método SetValue sempre altera o valor da variável pValue para null, e o GetValue resulta em erro desconhecido. Já tentei modificar os atributos da interface de várias formas, mas não resolveram. Também já tentei adicionar os atributos para interpretação dos parâmetros, como [MarshalAs(UnmanagedType.IUnknown)] para o pValue, mas sem sucesso.

    Agradeço a atenção.




    quarta-feira, 27 de novembro de 2013 18:07
  • Além desse código se ta usando como!?

    Você implementou a IAVerCustomControl ?


    Fulvio Cezar Canducci Dias

    quarta-feira, 27 de novembro de 2013 18:10
  • Não, esta interface IAVerCustomControl não foi implementada por mim, faz parte do SDK da AverMedia.

    Em C++, para utilizar a inteface para, por exemplo, alterar a propriedade noise reduction:

    IAVerCustomControl *piCustomControl = NULL;
    hr = pVideoProc->QueryInterface(IID_IAVerCustomControl,(void**)&piCustomControl);
    BOOL bEnableNR = FALSE;
    piCustomControl->SetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);
    piCustomControl->GetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);

    Em C#, estou fazendo da seguinte forma:

    IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;
    Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
    object nrEnabled = true;
    hr = iAcc.GetValue(ref Guid_AVerNoiseReductionMode, out nrEnabled);
    hr = iAcc.SetValue(ref Guid_AVerNoiseReductionMode, out nrEnabled);

    Também já tentei utilizar o nrEnabled como bool, mas não resolveu.


    • Editado Apek_Dev segunda-feira, 2 de dezembro de 2013 13:47
    segunda-feira, 2 de dezembro de 2013 13:46
  • Não, esta interface IAVerCustomControl não foi implementada por mim, faz parte do SDK da AverMedia.

    Em C++, para utilizar a inteface para, por exemplo, alterar a propriedade noise reduction:

    IAVerCustomControl *piCustomControl = NULL;
    hr = pVideoProc->QueryInterface(IID_IAVerCustomControl,(void**)&piCustomControl);
    BOOL bEnableNR = FALSE;
    piCustomControl->SetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);
    piCustomControl->GetValue(&AVerNoiseReductionMode,(void*)&bEnableNR);

    Em C#, estou fazendo da seguinte forma:

    IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;
    Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
    object nrEnabled = true;
    hr = iAcc.GetValue(ref Guid_AVerNoiseReductionMode, ref nrEnabled);
    hr = iAcc.SetValue(ref Guid_AVerNoiseReductionMode, ref nrEnabled);

    Também já tentei utilizar o nrEnabled como bool, mas não resolveu.

    Essa linha

    IAVerCustomControl iAcc = (IAVerCustomControl)pAverVideoProcessor;

    Tire ficando assim

    IAVerCustomControl iAcc = pAverVideoProcessor;

    Por favor e teste


    Fulvio Cezar Canducci Dias

    segunda-feira, 2 de dezembro de 2013 13:51
  • O pAverVideoProcessor é um IBaseFilter, não é possível converter implicitamente na interface IAverCustomControl.

    Quando utilizo o cast, a lib do DirectShow utiliza o médoto QueryInterface (a lib não disponibiliza o médoto diretamente, somente através do cast), retornando o objeto COM. No entanto, os métodos que não funcionam. Já conferi o GUID utilizado na interface e está ok.

    segunda-feira, 2 de dezembro de 2013 14:31
  • "O pAverVideoProcessor é um IBaseFilter" ele é um Interface ou é um classe Concreta (pelo que eu to vendo Concreta, se tiver enganado) implementando IBaseFilter ... é isso ???


    Fulvio Cezar Canducci Dias

    segunda-feira, 2 de dezembro de 2013 14:35
  • Desculpe, não entendi bem sua pergunta. O pAverVideoProcessor é uma instância do tipo IBaseFilter (do DirectShow), criada a partir do "Filter Moniker" do filtro "AVerMedia Video Processor (capsdk)", que implementa esta interface que estou querendo utilizar.

    Para criar esta IBaseFilter através do Filter Moniker, estou utilizando o método abaixo:

    public static object CreateObject(string displayName)
    {
    int hr = 0;
    object obj = null;
    IBindCtx bindCtx = null;
    IMoniker moniker = null;

    try
    {
    hr = CreateBindCtx(0, out bindCtx);
    Marshal.ThrowExceptionForHR(hr);

    int eaten;
    hr = MkParseDisplayName(bindCtx, displayName, out eaten, out moniker);
    Marshal.ThrowExceptionForHR(hr);

    Guid guid = typeof(IBaseFilter).GUID;
    moniker.BindToObject(bindCtx, null, ref guid, out obj);
    }
    finally
    {
    if (bindCtx != null) Marshal.ReleaseComObject(bindCtx);
    if (moniker != null) Marshal.ReleaseComObject(moniker);
    }

    return obj;
    }

    segunda-feira, 2 de dezembro de 2013 14:42
  • Faz esse teste então naquele antigo código:

    é porque amigo Interface C++ é muito diferente de C#

    mas, vamos tentar por erros:

    coloque dinâmico assim

    var iAcc = (IAVerCustomControl)pAverVideoProcessor;

    Tente rodar para ver se ele roda!!!

    Eu to tentanndo mas, eu já mexi e nunca passei por isso!


    Fulvio Cezar Canducci Dias

    segunda-feira, 2 de dezembro de 2013 14:46
  • Fiz o teste, mas ocorre o mesmo problema.

    Acho estranho que, apesar das interfaces serem diferentes em C#, deve haver uma forma de fazê-la funcionar. Por isto mencionei anteriormente que deve estar faltando algum atributo para utilização correta do objeto COM.

    Já verifiquei as interfaces que são declaradas na lib do DirectShow e não encontrei nada diferente. Como também não desenvolvi o filtro, não imagino o que possa resolver.

    Obrigado.

    segunda-feira, 2 de dezembro de 2013 16:41
  • Funciona diferente sim ...!!!, podem ter o mesmo resultado!!! mas, são diferentes! o Engraçado é que você ta implementando algo que existe então!

    Fulvio Cezar Canducci Dias



    segunda-feira, 2 de dezembro de 2013 18:14
  • Sim. Eu crio o filtro "AVerMedia Video Processor" como um IBase filter e adiciono ao graph, funciona sem problemas. Quando faço o cast (QueryInterface) para a interface IAVerCustomControl, é retornado um objeto COM (o que entendo que está então encontrando a interface com a GUID informada). O que não funciona corretamente é a chamada aos métodos mesmo.

    Tentei recriar a mesma definição da interface utilizada no C++, ficando desta forma:

    [ComImport]
    [SuppressUnmanagedCodeSecurityAttribute]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("8998BB49-2FF4-4106-953C-6DCABC7D957B")]
    public interface IAVerCustomControl
    {
    [PreserveSig]
    unsafe int SetValue([In] Guid* Property, [In] void* pValue);
    [PreserveSig]
    unsafe int GetValue([In] Guid* Property, [Out] void* pValue);
    }

    Testei utilizando da seguinte forma:

    var iAcc = (IAVerCustomControl)pAverVideoProcessor;
    Guid Guid_AVerNoiseReductionMode = new Guid(0x1ed9c780, 0x3272, 0x4a11, 0x8d, 0xdb, 0x2d, 0x9c, 0x79, 0xb9, 0x8c, 0x1c);
    bool isEnabled = true;
    unsafe
    {
    bool* nrEnabled = &isEnabled;
    //hr = iAcc.GetValue(&Guid_AVerNoiseReductionMode, &nrEnabled);
    hr = iAcc.SetValue(&Guid_AVerNoiseReductionMode, &nrEnabled);
    }

    No entanto, ocorre um efeito similar. Ao chamar o GetValue, o endereço do ponteiro nrEnabled é zerado. Se, ao invés de chamar GetValue, chamar SetValue, um erro não especificado é retornado. 

    terça-feira, 3 de dezembro de 2013 13:57