InvokeScript декомпилированного HtmlDocument не работает

Вот код, который я получил, используя ILSpy:

public static object InvokeScript(this IHTMLDocument2 document, string scriptName, object[] args = null)
{
    object result = null;
    UnsafeNativeMethods.tagDISPPARAMS tagDISPPARAMS = new UnsafeNativeMethods.tagDISPPARAMS();
    tagDISPPARAMS.rgvarg = IntPtr.Zero;
    try
    {
        UnsafeNativeMethods.IDispatch dispatch = ((IHTMLDocument)document).Script as UnsafeNativeMethods.IDispatch;
        if (dispatch != null)
        {
            Guid empty = Guid.Empty;
            string[] rgszNames = new string[]
            {
                scriptName
            };
            int[] array = new int[]
            {
                -1
            };
            int iDsOfNames = dispatch.GetIDsOfNames(ref empty, rgszNames, 1, UnsafeNativeMethods.GetThreadLCID(), array);
            if (UnsafeNativeMethods.Succeeded(iDsOfNames) && array[0] != -1)
            {
                if (args != null)
                {
                    Array.Reverse(args);
                }
                tagDISPPARAMS.rgvarg = ((args == null) ? IntPtr.Zero : ArrayToVARIANTVector(args));
                tagDISPPARAMS.cArgs = ((args == null) ? 0 : args.Length);
                tagDISPPARAMS.rgdispidNamedArgs = IntPtr.Zero;
                tagDISPPARAMS.cNamedArgs = 0;
                object[] array2 = new object[1];
                if (dispatch.Invoke(array[0], ref empty, UnsafeNativeMethods.GetThreadLCID(), 1, tagDISPPARAMS, array2, new UnsafeNativeMethods.tagEXCEPINFO(), null) == 0)
                {
                    result = array2[0];
                }
            }
        }
    }
    catch (Exception ex)
    {
        if (IsSecurityOrCriticalException(ex))
        {
            throw;
        }
    }
    finally
    {
        if (tagDISPPARAMS.rgvarg != IntPtr.Zero)
        {
            FreeVARIANTVector(tagDISPPARAMS.rgvarg, args.Length);
        }
    }
    return result;
}

Я также получил некоторые из их других методов, которые вызываются из этого метода. Вот как я это называю (примечание - это метод расширения):

var doc = Browser.Document.DomDocument as IHTMLDocument2;
doc.InvokeScript("alert", new object[] { "hi" });

Но линия int iDsOfNames = dispatch.GetIDsOfNames(ref empty, rgszNames, 1, UnsafeNativeMethods.GetThreadLCID(), array); бросает AccessViolationException, Одна вещь, в которой я не уверен, это UnsafeNativeMethods.IDispatch dispatch = ((IHTMLDocument)document).Script as UnsafeNativeMethods.IDispatch; линия. Фактическая строка ILSpy UnsafeNativeMethods.IDispatch dispatch = this.NativeHtmlDocument2.GetScript() as UnsafeNativeMethods.IDispatch; но по какой-то причине у меня нет GetScript метод.

Есть идеи, что я делаю не так?

редактировать

Вот мой IDispatch:

    [Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SuppressUnmanagedCodeSecurity]
    [ComImport]
    internal interface IDispatch
    {
        [SecurityCritical]
        void GetTypeInfoCount(out uint pctinfo);
        [SecurityCritical]
        void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
        [SecurityCritical]
        void GetIDsOfNames(ref Guid iid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names, uint cNames, int lcid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)] [Out] int[] rgDispId);
        [PreserveSig]
        int GetIDsOfNames([In] ref Guid riid, [MarshalAs(UnmanagedType.LPArray)] [In] string[] rgszNames, [MarshalAs(UnmanagedType.U4)] [In] int cNames, [MarshalAs(UnmanagedType.U4)] [In] int lcid, [MarshalAs(UnmanagedType.LPArray)] [Out] int[] rgDispId);
        [SecurityCritical]
        void Invoke(int dispIdMember, ref Guid riid, int lcid, System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, IntPtr pvarResult, IntPtr pExcepInfo, IntPtr puArgErr);
        [PreserveSig]
        int Invoke(int dispIdMember, [In] ref Guid riid, [MarshalAs(UnmanagedType.U4)] [In] int lcid, [MarshalAs(UnmanagedType.U4)] [In] int dwFlags, [In] [Out] tagDISPPARAMS pDispParams, [MarshalAs(UnmanagedType.LPArray)] [Out] object[] pVarResult, [In] [Out] tagEXCEPINFO pExcepInfo, [MarshalAs(UnmanagedType.LPArray)] [Out] IntPtr[] pArgErr);
    }

1 ответ

Решение

Редактировать: параметр dispid в GetIDsOfNames является предоставленным вызывающим массивом, поэтому вы не можете использовать [out] (это означает, что вызываемый объект выделяет массив в куче COM).

Трудно сказать, не видя вашего заявления UnsafeNativeMethods.IDispatch, но зовет GetIDsOfNames без закрепления массива dispid или добавления ссылки на параметр неправильно. Если вы упорядочили массив, передавая адрес по значению, сборщик мусора может перемещать массив, пока GetIDsOfNames вызов все еще выполняется, и нативный код будет записывать в дикий указатель по возвращении. Если вы передадите массив как ссылку, ваш код не скомпилируется - вам нужно добавить ref к параметру.

Ты можешь использовать System.Type.InvokeMember метод доступа к глобальным переменным или функциям через объект сценария. Этот метод вызывает IDispatch::GetIDsOfNames а также IDispatch::Invoke для тебя.

Другие вопросы по тегам