jim*_*nes 10 c# webbrowser-control download-manager winforms
我正在使用Systems.Windows.Forms.Webbrowser控件,需要覆盖下载管理器.我按照这里的说明继承了表单和覆盖CreateWebBrowserSiteBase()
/// <summary>
/// Browser with download manager
/// </summary>
public class MyBrowser : WebBrowser
{
/// <summary>
/// Returns a reference to the unmanaged WebBrowser ActiveX control site,
/// which you can extend to customize the managed <see ref="T:System.Windows.Forms.WebBrowser"/> control.
/// </summary>
/// <returns>
/// A <see cref="T:System.Windows.Forms.WebBrowser.WebBrowserSite"/> that represents the WebBrowser ActiveX control site.
/// </returns>
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
var manager = new DownloadWebBrowserSite(this);
manager.FileDownloading += (sender, args) =>
{
if (FileDownloading != null)
{
FileDownloading(this, args);
}
};
return manager;
}
}
Run Code Online (Sandbox Code Playgroud)
在DownloadWebBrowserSite,我实现IServiceProvider提供IDownloadManager时请求.
/// <summary>
/// Queries for a service
/// </summary>
/// <param name="guidService">the service GUID</param>
/// <param name="riid"></param>
/// <param name="ppvObject"></param>
/// <returns></returns>
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if ( (guidService == Constants.IID_IDownloadManager && riid == Constants.IID_IDownloadManager ))
{
ppvObject = Marshal.GetComInterfaceForObject(_manager, typeof(IDownloadManager));
return Constants.S_OK;
}
ppvObject = IntPtr.Zero;
return Constants.E_NOINTERFACE;
}
Run Code Online (Sandbox Code Playgroud)
这DownloadManager取自上面的例子.
/// <summary>
/// Intercepts downloads of files, to add as PDFs or suppliments
/// </summary>
[ComVisible(true)]
[Guid("bdb9c34c-d0ca-448e-b497-8de62e709744")]
[CLSCompliant(false)]
public class DownloadManager : IDownloadManager
{
/// <summary>
/// event called when the browser is about to download a file
/// </summary>
public event EventHandler<FileDownloadEventArgs> FileDownloading;
/// <summary>
/// Return S_OK (0) so that IE will stop to download the file itself.
/// Else the default download user interface is used.
/// </summary>
public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, IntPtr pBindInfo,
string pszHeaders, string pszRedir, uint uiCP)
{
// Get the display name of the pointer to an IMoniker interface that specifies the object to be downloaded.
string name;
pmk.GetDisplayName(pbc, null, out name);
if (!string.IsNullOrEmpty(name))
{
Uri url;
if (Uri.TryCreate(name, UriKind.Absolute, out url))
{
if ( FileDownloading != null )
{
FileDownloading(this, new FileDownloadEventArgs(url));
}
return Constants.S_OK;
}
}
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
问题是pmk.GetDisplayName返回初始URL,而不是要下载的项的URL.如果URI指向动态页面,例如http://www.example.com/download.php,我没有获得要下载的实际文件.我需要从标题中获取URL,以便获得我应该下载的实际文件.
Google表示我必须创建一个IBindStatusCallback也实现IHttpNegotiate并IServiceProvider响应的实现IID_IHttpNegotiate,以便我可以看到IHttpNegotiate.OnResponse.我设法实现了这一点,然而,QueryService似乎只是要求IID_IInternetProtocol而且永远不会IID_IHttpNegotiate.
任何建议都会很棒.
您错过了对CreateBindCtx的调用.
将以下内容添加到您的DownloadManager:
[DllImport("ole32.dll")]
static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
Run Code Online (Sandbox Code Playgroud)
然后确保在注册回调之前调用此方法.我在你的Download()方法中实现了这个,如下所示:
public int Download(IMoniker pmk, IBindCtx pbc, uint dwBindVerb, int grfBINDF, IntPtr pBindInfo,
string pszHeaders, string pszRedir, uint uiCP)
{
// Get the display name of the pointer to an IMoniker interface that specifies the object to be downloaded.
string name;
pmk.GetDisplayName(pbc, null, out name);
if (!string.IsNullOrEmpty(name))
{
Uri url;
if (Uri.TryCreate(name, UriKind.Absolute, out url))
{
Debug.WriteLine("DownloadManager: initial URL is: " + url);
CreateBindCtx(0, out pbc);
RegisterCallback(pbc, url);
BindMonikerToStream(pmk, pbc);
return MyBrowser.Constants.S_OK;
}
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
有了这个,您的IHttpNegotiate实现将被调用,您将有权访问响应头.
| 归档时间: |
|
| 查看次数: |
5497 次 |
| 最近记录: |