使用自定义IDownloadManager从WebBrowser控件访问AccessViolationException

时间:2014-02-07 03:35:04

标签: c# com webbrowser-control

我的.NET应用程序托管了一个WebBrowser控件,并且我附加了一个自定义下载管理器。除了具有以下两个HTTP头的请求之外,一切似乎都能正常工作:

Content-Type: application/octet-stream
Content-Disposition: attachment; filename=blahblahblah

更改或省略内容类型标题,一切正常;它只是具有问题的application / octet-stream。删除内容处置标题,不使用下载管理器。

有趣的是,这个问题只发生在32位机器上(我测试过XP和Win 7 32位.Win 7/8 64位不会崩溃)。

application/octet-stream有什么特别之处?

如果有帮助,这里有大量注册自定义下载管理器的代码。它受到这个问题和答案的启发:Windows Forms Webbrowswer control with IDownloadManager

在我的班级中衍生自WebBrowser

protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
    var site = new DownloadWebBrowserSite(this);
    return site;
}

DownloadWebBrowserSite

    DownloadManager _manager = new DownloadManager();

    public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
    {
        if (guidService.CompareTo(ComInteropConstants.IID_IDownloadManager) == 0 && riid.CompareTo(ComInteropConstants.IID_IDownloadManager) == 0)
        {
            IntPtr punk = Marshal.GetIUnknownForObject(_manager);
            return Marshal.QueryInterface(punk, ref riid, out ppvObject);
        }
        ppvObject = IntPtr.Zero;
        return ComInteropConstants.E_NOINTERFACE;
    }

DownloadManager是我的自定义下载管理器。 Download的实施情况如下。

public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, IntPtr pBindInfo, string pszHeaders, string pszRedir, uint uiCP)
{
    return ComInteropConstants.S_OK;
}

它实现了IDownloadManager,在下面声明。

[ComVisible(false), ComImport]
[Guid("988934A4-064B-11D3-BB80-00104B35E7F9")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDownloadManager
{
    [return: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    int Download(
        [In, MarshalAs(UnmanagedType.Interface)] IMoniker pmk,
        [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc,
        [In, MarshalAs(UnmanagedType.U4)] uint dwBindVerb,
        [In] int grfBINDF,
        [In] IntPtr pBindInfo,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pszHeaders,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pszRedir,
        [In, MarshalAs(UnmanagedType.U4)] uint uiCP);
}

要重现崩溃,我不需要在该方法中实际执行任何操作。

1 个答案:

答案 0 :(得分:1)

我仍然不完全理解我的应用程序崩溃的原因,也不完全理解为什么下面的代码修复了它,但是这里最终防止了崩溃:

[DllImport("urlmon.dll"), PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
static extern int CoInternetSetFeatureEnabled(int FeatureEntry, [In, MarshalAs(UnmanagedType.U4)]uint dwFlags, bool fEnable);

CoInternetSetFeatureEnabled(ComInteropConstants.FEATURE_MIME_HANDLING, (uint)ComInteropConstants.SET_FEATURE_ON_PROCESS, true);
CoInternetSetFeatureEnabled(ComInteropConstants.FEATURE_MIME_SNIFFING, (uint)ComInteropConstants.SET_FEATURE_ON_PROCESS, true);

所以看起来没有打开这些功能(MIME处理和MIME嗅探),错误的HTTP响应(带有文本内容的内容类型应用程序/八位字节流)会导致问题。