C# 使用IPersistStreamInit从WPF WebBrowser控件获取HTML源代码
我正在尝试获取已加载到WPFWebBrowser控件中的网页的HTML源代码。唯一的方法似乎是将WebBrowser.Document实例强制转换为IPersistStreamInit(我必须自己定义,因为它是一个COM接口),并调用IPersistStreamInit.Save方法,传递一个 实现一个IStream(同样是一个COM接口),它将持久化 将文档发送到流。嗯,有点像:我总是得到流的前4千字节,而不是整个文档,我不知道为什么 以下是IPersistStreamInit的代码:C# 使用IPersistStreamInit从WPF WebBrowser控件获取HTML源代码,c#,wpf,com,webbrowser-control,com-interop,C#,Wpf,Com,Webbrowser Control,Com Interop,我正在尝试获取已加载到WPFWebBrowser控件中的网页的HTML源代码。唯一的方法似乎是将WebBrowser.Document实例强制转换为IPersistStreamInit(我必须自己定义,因为它是一个COM接口),并调用IPersistStreamInit.Save方法,传递一个 实现一个IStream(同样是一个COM接口),它将持久化 将文档发送到流。嗯,有点像:我总是得到流的前4千字节,而不是整个文档,我不知道为什么 以下是IPersistStreamInit的代码: usi
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
namespace PayPal.SkyNet.BpiTool.Interop
{
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
SuppressUnmanagedCodeSecurity,
Guid("7FD52380-4E07-101B-AE2D-08002B2EC713")]
public interface IPersistStreamInit
{
void GetClassID(out Guid pClassID);
[PreserveSig]
int IsDirty();
void Load([In, MarshalAs(UnmanagedType.Interface)] IStream pstm);
void Save([In, MarshalAs(UnmanagedType.Interface)] IStream pstm, [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
void GetSizeMax([Out, MarshalAs(UnmanagedType.LPArray)] long pcbSize);
void InitNew();
}
}
以下是IStream实现的代码:
using System;
using System.IO;
using System.Runtime.InteropServices.ComTypes;
namespace PayPal.SkyNet.BpiTool.Interop
{
public class ComStream : IStream
{
private Stream _stream;
public ComStream(Stream stream)
{
this._stream = stream;
}
public void Commit(int grfCommitFlags)
{
}
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{
}
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
this._stream.Read(pv, (int)this._stream.Position, cb);
}
public void Revert()
{
}
public void SetSize(long libNewSize)
{
this._stream.SetLength(libNewSize);
}
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG();
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{
}
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{
this._stream.Write(pv, 0, cb);
}
public void Clone(out IStream outputStream)
{
outputStream = null;
}
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
this._stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
}
}
}
现在我有一节课来总结这一切。因为我不想重新发布mshtml互操作程序集,所以我选择了后期绑定——而且在VB中后期绑定更容易,所以我在VB中进行了后期绑定。代码如下:
Option Strict Off
Option Explicit Off
Imports System.IO
Public Class HtmlDocumentWrapper : Implements IDisposable
Private htmlDoc As Object
Public Sub New(ByVal htmlDoc As Object)
Me.htmlDoc = htmlDoc
End Sub
Public Property Document As Object
Get
Return Me.htmlDoc
End Get
Set(value As Object)
Me.htmlDoc = Nothing
Me.htmlDoc = value
End Set
End Property
Public ReadOnly Property DocumentStream As Stream
Get
Dim str As Stream = Nothing
Dim psi As IPersistStreamInit = CType(Me.htmlDoc, IPersistStreamInit)
If psi IsNot Nothing Then
str = New MemoryStream
Dim cStream As New ComStream(str)
psi.Save(cStream, False)
str.Position = 0
End If
Return str
End Get
End Property
End Class
现在我应该能够使用所有这些:
private void Browser_Navigated(object sender, NavigationEventArgs e)
{
HtmlDocumentWrapper doc = new HtmlDocumentWrapper();
doc.Document = Browser.Document;
using (StreamReader sr = new StreamReader(doc.DocumentStream))
{
using (StreamWriter sw = new StreamWriter("test.txt"))
{
//BOOM! Only 4kb of HTML source
sw.WriteLine(sr.ReadToEnd());
sw.Flush();
}
}
}
谁都知道,为什么我没有得到整个HTML资源?非常感谢您的帮助
问候
阿恩这只是一个猜测:
该流没有已知长度,因为它可能仍在下载。您需要阅读它,直到它显示EOF。将您的代码从浏览器中移动。导航到Browser.LoadCompleted,正如盛江在上面正确指出的那样,它可以工作。您是否尝试使用MSHTML获取HTML文档,这将更容易。使用MSHTML的AFAI无法让我访问完整的源代码,我确实需要完整的源代码。另一个问题:这是来自一个面向客户的应用程序的代码,该应用程序将被数百万用户使用,我不想重新发布Interop.MSHTML-鉴于所有不同的IE版本,这在过去一直是一个脆弱的解决方案。看看这是否能给你一些帮助不,这没有帮助,WPF是一个不同的野兽。导航=装载完成