C# 带有自定义IDownloadManager的WebBrowser控件的AccessViolationException

C# 带有自定义IDownloadManager的WebBrowser控件的AccessViolationException,c#,com,webbrowser-control,C#,Com,Webbrowser Control,我的.NET应用程序拥有一个WebBrowser控件,我还附加了一个自定义下载管理器。除了具有以下两个HTTP头的请求外,其他一切似乎都正常工作: Content-Type: application/octet-stream Content-Disposition: attachment; filename=blahblahblah 更改或省略内容类型标题,一切正常;问题出在应用程序/八位字节流上。删除内容处置标头,则不使用下载管理器 有趣的是,这个问题只发生在32位机器上(我已经测试过XP和

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

Content-Type: application/octet-stream
Content-Disposition: attachment; filename=blahblahblah
更改或省略内容类型标题,一切正常;问题出在应用程序/八位字节流上。删除内容处置标头,则不使用下载管理器

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

应用程序/octet流有什么特别之处

如果有帮助的话,这里有大量注册自定义下载管理器的代码。这个问题和答案启发了我们:

在我的类中,源于
WebBrowser

protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
    var site = new DownloadWebBrowserSite(this);
    return site;
}
下载WebBrowserSite
中:

    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
是我的自定义下载管理器。其
下载
的实现如下

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);
}

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

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

[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响应(内容类型应用程序/包含文本内容的八位字节流)会导致问题。

您是否使用WinDBG查看AV具体发生的位置?就“应用程序/八位字节流有什么特别之处”而言,它是一种不明确的类型(会触发嗅探),而且很可能您已经为该类型注册了一个或多个MIME过滤器。查看HKCR\Protocols\.@JeffMeadows的子项,如果显示
IDownloadManager
的托管声明,可能会有所帮助。另一方面,您的代码和原始答案都不会在
marshall.QueryInterface
之后释放
punk
。使用
Marshall.Release
@Noseratio释放它什么时候调用
Marshall.Release
?我将编辑以显示
IDownloadManager
的声明@EricLaw中,唯一为该类型注册的MIME筛选器是mscorie-Cor MIME Fltr。我会给WinDBG看一看,看这是否有帮助。谢谢就在
QueryInterface
之后,当您不再需要
朋克时。使用
try/finally
。我知道这很粗鲁,但我想你不会愿意分享你的IDownloadManager的完整实现吧?我正在尝试创建一个定制的下载管理器。对不起,我还没有完整的实现。我只是想允许用户通过WebBrowser控件下载文件。我所做的实际上是打开用户的默认web浏览器来处理下载。