小弟想把内存中的mht格式数据(byte[])不通过临时文件加载到WebBrowser中,听说IE异步可插入协议扩展可实现这个要求。(其实我现在还没弄清楚到底是IE异步可插入协议扩展能实现要求,还是要用MIME过滤,网上说扩展是用来hook URL及给IE提供数据,但MIME 过滤则是IE先获取数据,用户再修定后最终提交。因此小弟认为扩展是我需要的。只是不清楚IE如何识边我提供给它的数据类型,通过URL最后的文件扩展名么?比如"MyProt://test.mht")事情得一步步来,现在问题是我扩展都实现不了,首当其冲问题是无法实现临时注册协议,异常如下:System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
在 APP_Mht.IInternetSession.RegisterNameSpace(IClassFactory pCF, Guid& rclsid, String pwzProtocol, UInt32 cPatterns, String ppwzPatterns, UInt32 dwReserved)
在 APP_Mht.MhtHandler.Register()下面是偶的代码(用来生成一个COM DLL)麻烦大家纠正其中错误,谢谢!
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace APP_Mht
{
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("00000001-0000-0000-C000-000000000046"),]
public interface IClassFactory
{
void CreateInstance(IntPtr pUnkOuter,ref Guid riid,out IntPtr ppvObject);
void LockServer(bool fLock);
} public class HRESULT
{
public static UInt32 S_OK = 0;
public static UInt32 S_FALSE = 1;
public static UInt32 INET_E_DEFAULT_ACTION = 0x800C0011;
} public enum PARSEACTION
{
PARSE_CANONICALIZE = 1,
PARSE_FRIENDLY = PARSE_CANONICALIZE + 1,
PARSE_SECURITY_URL = PARSE_FRIENDLY + 1,
PARSE_ROOTDOCUMENT = PARSE_SECURITY_URL + 1,
PARSE_DOCUMENT = PARSE_ROOTDOCUMENT + 1,
PARSE_ANCHOR = PARSE_DOCUMENT + 1,
PARSE_ENCODE = PARSE_ANCHOR + 1,
PARSE_DECODE = PARSE_ENCODE + 1,
PARSE_PATH_FROM_URL = PARSE_DECODE + 1,
PARSE_URL_FROM_PATH = PARSE_PATH_FROM_URL + 1,
PARSE_MIME = PARSE_URL_FROM_PATH + 1,
PARSE_SERVER = PARSE_MIME + 1,
PARSE_SCHEMA = PARSE_SERVER + 1,
PARSE_SITE = PARSE_SCHEMA + 1,
PARSE_DOMAIN = PARSE_SITE + 1,
PARSE_LOCATION = PARSE_DOMAIN + 1,
PARSE_SECURITY_DOMAIN = PARSE_LOCATION + 1,
PARSE_ESCAPE = PARSE_SECURITY_DOMAIN + 1,
PARSE_UNESCAPE = PARSE_ESCAPE + 1,
} public enum QUERYOPTION
{
QUERY_EXPIRATION_DATE = 1,
QUERY_TIME_OF_LAST_CHANGE = QUERY_EXPIRATION_DATE + 1,
QUERY_CONTENT_ENCODING = QUERY_TIME_OF_LAST_CHANGE + 1,
QUERY_CONTENT_TYPE = QUERY_CONTENT_ENCODING + 1,
QUERY_REFRESH = QUERY_CONTENT_TYPE + 1,
QUERY_RECOMBINE = QUERY_REFRESH + 1,
QUERY_CAN_NAVIGATE = QUERY_RECOMBINE + 1,
QUERY_USES_NETWORK = QUERY_CAN_NAVIGATE + 1,
QUERY_IS_CACHED = QUERY_USES_NETWORK + 1,
QUERY_IS_INSTALLEDENTRY = QUERY_IS_CACHED + 1,
QUERY_IS_CACHED_OR_MAPPED = QUERY_IS_INSTALLEDENTRY + 1,
QUERY_USES_CACHE = QUERY_IS_CACHED_OR_MAPPED + 1,
QUERY_IS_SECURE = QUERY_USES_CACHE + 1,
QUERY_IS_SAFE = QUERY_IS_SECURE + 1,
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79eac9ec-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetProtocolInfo
{
[PreserveSig()] UInt32 ParseUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
/* [in] */ PARSEACTION ParseAction,
UInt32 dwParseFlags,
IntPtr pwzResult,
UInt32 cchResult,
out UInt32 pcchResult,
UInt32 dwReserved);
[PreserveSig()] UInt32 CombineUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzBaseUrl,
[ MarshalAs(UnmanagedType.LPWStr)] string pwzRelativeUrl,
UInt32 dwCombineFlags,
IntPtr pwzResult,
UInt32 cchResult,
out UInt32 pcchResult,
UInt32 dwReserved);
[PreserveSig()] UInt32 CompareUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl1,
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl2,
UInt32 dwCompareFlags);
[PreserveSig()] UInt32 QueryInfo(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
QUERYOPTION OueryOption,
UInt32 dwQueryFlags,
IntPtr pBuffer,
UInt32 cbBuffer,
ref UInt32 pcbBuf,
UInt32 dwReserved);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetSession
{
void CreateBinding(); // Not Implemented
void GetCache(); // Not Implemented
void GetSessionOption(); // Not Implemented
void RegisterMimeFilter([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
void RegisterNameSpace([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
UInt32 cPatterns, [MarshalAs(UnmanagedType.LPWStr)] string ppwzPatterns, UInt32 dwReserved);
void SetCache(); // Not Implemented
void SetSessionOption(); // Not Implemented
void UnregisterMimeFilter(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
void UnregisterNameSpace(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E5-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocolSink
{
void Switch(IntPtr pProtocolData);
void ReportProgress(UInt32 ulStatusCode, [MarshalAs(UnmanagedType.LPWStr)] string szStatusText);
void ReportData(UInt32 grfBSCF, UInt32 ulProgress, UInt32 ulProgressMax);
void ReportResult(Int32 hrResult, UInt32 dwError, [MarshalAs(UnmanagedType.LPWStr)] string szResult);
} [ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocol : IInternetProtocolRoot
{
void LockRequest(Int32 dwOptions);
[PreserveSig]
Int32 Read(IntPtr pv, UInt32 cb, out UInt32 pcbRead);
void Seek(Int64 dlibMove, UInt32 dwOrigin, out UInt64 plibNewPosition);
void UnlockRequest();
} [ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E3-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocolRoot
{
void Abort(Int32 hrReason, Int32 dwOptions);
void Continue(IntPtr pProtocolData);
void Resume();
void Start([MarshalAs(UnmanagedType.LPWStr)] string szUrl, IInternetProtocolSink pOIProtSink,
IntPtr pOIBindInfo, UInt32 grfPI, IntPtr dwReserved);
void Suspend();
void Terminate(Int32 dwOptions);
}
[Guid("EFA14C17-7854-4fe2-AF94-856A9714A7B7")]
public interface IMhtHandler : IInternetProtocol, IInternetProtocolRoot, IInternetProtocolInfo
{ } [Guid("B59A934A-A06D-4fa1-9AD3-49AEA12235A4"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMhtHandler_Events
{
}
public enum PI_FLAGS:uint
{
PI_PARSE_URL = 0x00000001,
PI_FILTER_MODE = 0x00000002,
PI_FORCE_ASYNC = 0x00000004,
PI_USE_WORKERTHREAD = 0x00000008,
PI_MIMEVERIFICATION = 0x00000010,
PI_CLSIDLOOKUP = 0x00000020,
PI_DATAPROGRESS = 0x00000040,
PI_SYNCHRONOUS = 0x00000080,
PI_APARTMENTTHREADED = 0x00000100,
PI_CLASSINSTALL = 0x00000200,
PI_PASSONBINDCTX = 0x00002000,
PI_NOMIMEHANDLER = 0x00008000,
PI_LOADAPPDIRECT = 0x00004000,
PD_FORCE_SWITCH = 0x00010000,
PI_PREFERDEFAULTHANDLER = 0x00020000
}
public enum BSCF : uint
{
BSCF_FIRSTDATANOTIFICATION = 0,
BSCF_INTERMEDIATEDATANOTIFICATION = 1,
BSCF_LASTDATANOTIFICATION = 2,
BSCF_DATAFULLYAVAILABLE = 3,
BSCF_AVAILABLEDATASIZEUNKNOWN = 4,
}-- 下面继续
在 APP_Mht.IInternetSession.RegisterNameSpace(IClassFactory pCF, Guid& rclsid, String pwzProtocol, UInt32 cPatterns, String ppwzPatterns, UInt32 dwReserved)
在 APP_Mht.MhtHandler.Register()下面是偶的代码(用来生成一个COM DLL)麻烦大家纠正其中错误,谢谢!
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace APP_Mht
{
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("00000001-0000-0000-C000-000000000046"),]
public interface IClassFactory
{
void CreateInstance(IntPtr pUnkOuter,ref Guid riid,out IntPtr ppvObject);
void LockServer(bool fLock);
} public class HRESULT
{
public static UInt32 S_OK = 0;
public static UInt32 S_FALSE = 1;
public static UInt32 INET_E_DEFAULT_ACTION = 0x800C0011;
} public enum PARSEACTION
{
PARSE_CANONICALIZE = 1,
PARSE_FRIENDLY = PARSE_CANONICALIZE + 1,
PARSE_SECURITY_URL = PARSE_FRIENDLY + 1,
PARSE_ROOTDOCUMENT = PARSE_SECURITY_URL + 1,
PARSE_DOCUMENT = PARSE_ROOTDOCUMENT + 1,
PARSE_ANCHOR = PARSE_DOCUMENT + 1,
PARSE_ENCODE = PARSE_ANCHOR + 1,
PARSE_DECODE = PARSE_ENCODE + 1,
PARSE_PATH_FROM_URL = PARSE_DECODE + 1,
PARSE_URL_FROM_PATH = PARSE_PATH_FROM_URL + 1,
PARSE_MIME = PARSE_URL_FROM_PATH + 1,
PARSE_SERVER = PARSE_MIME + 1,
PARSE_SCHEMA = PARSE_SERVER + 1,
PARSE_SITE = PARSE_SCHEMA + 1,
PARSE_DOMAIN = PARSE_SITE + 1,
PARSE_LOCATION = PARSE_DOMAIN + 1,
PARSE_SECURITY_DOMAIN = PARSE_LOCATION + 1,
PARSE_ESCAPE = PARSE_SECURITY_DOMAIN + 1,
PARSE_UNESCAPE = PARSE_ESCAPE + 1,
} public enum QUERYOPTION
{
QUERY_EXPIRATION_DATE = 1,
QUERY_TIME_OF_LAST_CHANGE = QUERY_EXPIRATION_DATE + 1,
QUERY_CONTENT_ENCODING = QUERY_TIME_OF_LAST_CHANGE + 1,
QUERY_CONTENT_TYPE = QUERY_CONTENT_ENCODING + 1,
QUERY_REFRESH = QUERY_CONTENT_TYPE + 1,
QUERY_RECOMBINE = QUERY_REFRESH + 1,
QUERY_CAN_NAVIGATE = QUERY_RECOMBINE + 1,
QUERY_USES_NETWORK = QUERY_CAN_NAVIGATE + 1,
QUERY_IS_CACHED = QUERY_USES_NETWORK + 1,
QUERY_IS_INSTALLEDENTRY = QUERY_IS_CACHED + 1,
QUERY_IS_CACHED_OR_MAPPED = QUERY_IS_INSTALLEDENTRY + 1,
QUERY_USES_CACHE = QUERY_IS_CACHED_OR_MAPPED + 1,
QUERY_IS_SECURE = QUERY_USES_CACHE + 1,
QUERY_IS_SAFE = QUERY_IS_SECURE + 1,
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79eac9ec-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetProtocolInfo
{
[PreserveSig()] UInt32 ParseUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
/* [in] */ PARSEACTION ParseAction,
UInt32 dwParseFlags,
IntPtr pwzResult,
UInt32 cchResult,
out UInt32 pcchResult,
UInt32 dwReserved);
[PreserveSig()] UInt32 CombineUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzBaseUrl,
[ MarshalAs(UnmanagedType.LPWStr)] string pwzRelativeUrl,
UInt32 dwCombineFlags,
IntPtr pwzResult,
UInt32 cchResult,
out UInt32 pcchResult,
UInt32 dwReserved);
[PreserveSig()] UInt32 CompareUrl(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl1,
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl2,
UInt32 dwCompareFlags);
[PreserveSig()] UInt32 QueryInfo(
[ MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
QUERYOPTION OueryOption,
UInt32 dwQueryFlags,
IntPtr pBuffer,
UInt32 cbBuffer,
ref UInt32 pcbBuf,
UInt32 dwReserved);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetSession
{
void CreateBinding(); // Not Implemented
void GetCache(); // Not Implemented
void GetSessionOption(); // Not Implemented
void RegisterMimeFilter([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
void RegisterNameSpace([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
UInt32 cPatterns, [MarshalAs(UnmanagedType.LPWStr)] string ppwzPatterns, UInt32 dwReserved);
void SetCache(); // Not Implemented
void SetSessionOption(); // Not Implemented
void UnregisterMimeFilter(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
void UnregisterNameSpace(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E5-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocolSink
{
void Switch(IntPtr pProtocolData);
void ReportProgress(UInt32 ulStatusCode, [MarshalAs(UnmanagedType.LPWStr)] string szStatusText);
void ReportData(UInt32 grfBSCF, UInt32 ulProgress, UInt32 ulProgressMax);
void ReportResult(Int32 hrResult, UInt32 dwError, [MarshalAs(UnmanagedType.LPWStr)] string szResult);
} [ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocol : IInternetProtocolRoot
{
void LockRequest(Int32 dwOptions);
[PreserveSig]
Int32 Read(IntPtr pv, UInt32 cb, out UInt32 pcbRead);
void Seek(Int64 dlibMove, UInt32 dwOrigin, out UInt64 plibNewPosition);
void UnlockRequest();
} [ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E3-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocolRoot
{
void Abort(Int32 hrReason, Int32 dwOptions);
void Continue(IntPtr pProtocolData);
void Resume();
void Start([MarshalAs(UnmanagedType.LPWStr)] string szUrl, IInternetProtocolSink pOIProtSink,
IntPtr pOIBindInfo, UInt32 grfPI, IntPtr dwReserved);
void Suspend();
void Terminate(Int32 dwOptions);
}
[Guid("EFA14C17-7854-4fe2-AF94-856A9714A7B7")]
public interface IMhtHandler : IInternetProtocol, IInternetProtocolRoot, IInternetProtocolInfo
{ } [Guid("B59A934A-A06D-4fa1-9AD3-49AEA12235A4"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMhtHandler_Events
{
}
public enum PI_FLAGS:uint
{
PI_PARSE_URL = 0x00000001,
PI_FILTER_MODE = 0x00000002,
PI_FORCE_ASYNC = 0x00000004,
PI_USE_WORKERTHREAD = 0x00000008,
PI_MIMEVERIFICATION = 0x00000010,
PI_CLSIDLOOKUP = 0x00000020,
PI_DATAPROGRESS = 0x00000040,
PI_SYNCHRONOUS = 0x00000080,
PI_APARTMENTTHREADED = 0x00000100,
PI_CLASSINSTALL = 0x00000200,
PI_PASSONBINDCTX = 0x00002000,
PI_NOMIMEHANDLER = 0x00008000,
PI_LOADAPPDIRECT = 0x00004000,
PD_FORCE_SWITCH = 0x00010000,
PI_PREFERDEFAULTHANDLER = 0x00020000
}
public enum BSCF : uint
{
BSCF_FIRSTDATANOTIFICATION = 0,
BSCF_INTERMEDIATEDATANOTIFICATION = 1,
BSCF_LASTDATANOTIFICATION = 2,
BSCF_DATAFULLYAVAILABLE = 3,
BSCF_AVAILABLEDATASIZEUNKNOWN = 4,
}-- 下面继续
[ComVisible(true)]
public class ClassFactory : IClassFactory
{
private const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110);
private const int E_NOINTERFACE = unchecked((int)0x80004002);
private readonly Guid IID_MhtHandler = new Guid("{2E3C7BAD-1051-4622-9C4C-215182C6BF58}"); public ClassFactory()
{} public void LockServer(bool fLock)
{} public void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
{
ppvObject = new IntPtr();
if (pUnkOuter != IntPtr.Zero)
{
Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION);
}
if (riid == IID_MhtHandler)
{
MhtHandler mh = new MhtHandler();
ppvObject = Marshal.GetComInterfaceForObject(mh, typeof(IMhtHandler));
}
else
{
Marshal.ThrowExceptionForHR(E_NOINTERFACE);
}
}
}
[Guid("2E3C7BAD-1051-4622-9C4C-215182C6BF58"), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IMhtHandler_Events))]
public class MhtHandler : IMhtHandler
{
public const string ProcotolName = "InfiKeeper"; public const int INET_E_INVALID_REQUEST = unchecked((int)0x800C000C);
public const int S_OK = 0x00000000;
public const int S_FALSE = 0x00000001;
public const int E_FAIL = unchecked((int)0x80004005);
public const int E_POINTER = unchecked((int)0x80004005); public static byte[] buffer = new byte[0];
public static uint pos = 0;
public IInternetProtocolSink ProtSink; public void LockRequest(Int32 dwOptions)
{
throw new COMException("", S_OK);
} public Int32 Read(IntPtr pv, UInt32 cb, out UInt32 pcbRead)
{
if( (buffer.Length - pos) <= cb)
{
Marshal.Copy(buffer, (int)pos, pv, (int)(buffer.Length - pos));
pcbRead = (uint)(buffer.Length - pos);
pos = 0;
ProtSink.ReportResult(S_OK, 0, null);
return S_FALSE;
}
else
{
Marshal.Copy(buffer, (int)pos, pv, (int)cb);
pos += cb;
pcbRead = cb;
return S_OK;
}
}
public void Seek(Int64 dlibMove, UInt32 dwOrigin, out UInt64 plibNewPosition)
{
plibNewPosition = new ulong();
throw new COMException("", E_FAIL);
} public void UnlockRequest()
{
throw new COMException("", S_OK);
} public void Abort(Int32 hrReason, Int32 dwOptions)
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Continue(IntPtr pProtocolData)
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Resume()
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Start([MarshalAs(UnmanagedType.LPWStr)] string szUrl, IInternetProtocolSink pOIProtSink,
IntPtr pOIBindInfo, UInt32 grfPI, IntPtr dwReserved)
{
if ((grfPI & 0x00000001) != 0)
{ throw new COMException("", S_OK); } if (pOIProtSink == null)
{ throw new COMException("", E_POINTER); } ProtSink = pOIProtSink; pOIProtSink.ReportData(2, 0, (uint)buffer.Length);
pOIProtSink.ReportData(3, 0, (uint)buffer.Length);
throw new COMException("", S_OK);
} public void Suspend()
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Terminate(Int32 dwOptions)
{
throw new COMException("", S_OK);
} #region IInternetProtocolInfo 实现
public string DirectoryFromBaseUrl(string Url)
{
int loc = Url.LastIndexOf('/');
if (loc < 0)
return String.Empty;
return Url.Substring(0, loc + 1);
} public string VirtualDirctoryFromBaseUrl(string Url)
{
int loc = Url.LastIndexOf('/');
if (loc < 0)
return String.Empty;
return Url.Substring(0, loc);
} public UInt32 ParseUrl(string pwzUrl, PARSEACTION ParseAction, UInt32 dwParseFlags, IntPtr pwzBuffer, UInt32 cchResult, out UInt32 pcchResult, UInt32 dwReserved)
{
pcchResult = 0;
return HRESULT.INET_E_DEFAULT_ACTION;
} public UInt32 CombineUrl(string pwzBaseUrl, string pwzRelativeUrl, UInt32 dwCombineFlags, IntPtr pwzBuffer, UInt32 cchResult, out UInt32 pcchResult, UInt32 dwReserved)
{
string temp = null;
if (pwzRelativeUrl.Substring(0, 1) != "/")
temp = DirectoryFromBaseUrl(pwzBaseUrl) + pwzRelativeUrl;
else
temp = VirtualDirctoryFromBaseUrl(pwzBaseUrl) + pwzRelativeUrl;
if (pwzRelativeUrl.IndexOf(":") > 0)
temp = pwzRelativeUrl;
if (temp.Length > cchResult)
{
pcchResult = 0;
return HRESULT.S_FALSE;
}
Marshal.Copy(temp.ToCharArray(), 0, pwzBuffer, temp.Length);
Marshal.WriteInt32(pwzBuffer, temp.Length * 2, 0);
pcchResult = (UInt32)temp.Length + 1;
return HRESULT.S_OK;
} public UInt32 CompareUrl(string pwzUrl1, string pwzUrl2, UInt32 dwCompareFlags)
{
return (UInt32)pwzUrl1.CompareTo(pwzUrl2);
} public UInt32 QueryInfo(string pwzUrl, QUERYOPTION OueryOption, UInt32 dwQueryFlags, IntPtr pBuffer, UInt32 cbBuffer, ref UInt32 pcbBuf, UInt32 dwReserved)
{
return HRESULT.INET_E_DEFAULT_ACTION;
}
#endregion [DllImport("urlmon.dll")]
private static extern void CoInternetGetSession(int sessionMode,
out IInternetSession session, int reserved); #region 注册协议
public void Register()
{
IInternetSession session;
CoInternetGetSession(0, out session, 0);
Guid guid = new Guid("2E3C7BAD-1051-4622-9C4C-215182C6BF58");
session.RegisterNameSpace(new ClassFactory(), ref guid, "InfiKeeper", 0, null, 0);
} public void UnRegister()
{
IInternetSession session;
CoInternetGetSession(0, out session, 0);
session.UnregisterNameSpace(new ClassFactory(), "InfiKeeper");
}
#endregion
}//end class
}
未能添加对urlmon.dll的引用,这不是一个有效的程序集或COM组件,只有具有扩展名dll的程序集和COM组件才能被引用
看来是你的urlmon没注册,先注册然后添加引用就行了。
首先是把网页数据保存为mht格式数据。虽然这不是本贴的问题,但这符合“从头说起”原则。我遍历google,只找到一个JAVA版的源代码和一个大概性的C#实现方案(源码要500¥)。
http://www.diybl.com/course/4_webprogram/asp.net/asp_netshl/2008510/115460.html
http://blog.csdn.net/dongle2001/archive/2008/06/17/2557434.aspx经过对它们的反复研究,我实现了用C#把网页数据保存为mht格式(文件或字节数组)有了保存方案,接下来就是还原了。最简单的方法是把mht数据写入临时文件,然后用IE来navigate之。但是我不想采用临时文件。再次遍历google,发现需要使用IE异步可插入协议。这也是我贴子开头所问的。其实经过对IE异步可插入协议的逐步了解,我发现,对于实现“把网页全部内容保存为一个字节数组,反之把字节数组还原为网页”,根本不需要通过mht来做桥梁。我的最终解决方案是:把网页各部分数据直接保存到一个字节数组中,同时用另一个数据结构来记录各部分数据的名称、类型、在数组中编移及长度。然后把这个结构也化为一个字节数组。两个字节数组一起放入数据库。还原时从数据库中先把前面的"数据结构"还原。然后就是IE异步协议的表演了,它会向你索取数据,我根据“数据结构”中记录的信息从存放网页信息的那个字节数组中取出数据提交给IE。总而言之,把网页保存为字节数组有一套相对固定的代码流程。而把字节数组还原为网页则重在对IE异步可插入协议的理解。相关资料:http://blog.csdn.net/oulix/archive/2008/02/21/2111022.aspx另外一个客观困难是:windows XP及IE 6是win32,特别是IE采用的COM技术是和C++紧密联系的产物。C#操作它们需要通过一系列转换,而且网上相关资料也不多。我一直认为自己写的是披着C#外衣的VC代码。--- 为啥不用VC?因为偶没学MFC,从win32API直接跳跃到C#了,跨跃式发展嘛:)接下来,我贴一些代码。
public class ContentPart
{
string content_type;
string charset;
string content_transfer_encoding;
string content_location;
byte[] data;
string stringData; public ContentPart()
{
data = new byte[0];
stringData = "";
} public string Content_Type
{
get
{ return content_type; }
set
{ content_type = value; }
} public string Charset
{
get
{ return charset; }
set
{ charset = value;}
} public string Content_Transfer_Encoding
{
get
{ return content_transfer_encoding; }
set
{ content_transfer_encoding = value; }
} public string Content_Location
{
get
{ return content_location; }
set
{ content_location = value; }
} public byte[] Data
{
get
{ return data; }
set
{ data = value; }
} public string StringData
{
get
{ return stringData; }
set
{ stringData = value; }
} /// <summary>
/// 检测对象是否包含完整的数据成员
/// </summary>
/// <returns></returns>
public bool IsValid()
{
if (content_type == null || content_transfer_encoding == null
|| content_location == null || (data.Length == 0 && stringData.Length == 0))
{ return false; }
else
{ return true; }
}//end fun public byte[] GetContent()
{
byte[] b;
string head = "";
byte[] result = new byte[0]; if (content_type == null || content_transfer_encoding == null || content_location == null)
{ throw new SaveWebPageException("文字头不完整", 980000); }
else
{
head += ("Content-Type: " + content_type + "\r\n") ;
if (charset != null)
{ head += ("charset=" + "\"" + charset + "\"\r\n" ); }
head += ("Content-Transfer-Encoding: " + content_transfer_encoding + "\r\n");
head += ("Content-Location: " + content_location +"\r\n\r\n");
b = System.Text.Encoding.GetEncoding("GB2312").GetBytes(head);
} if (data.Length == 0 && stringData.Length == 0)
{ throw new SaveWebPageException("数据为空", 980001); }
else if (data.Length != 0)
{
string ss = Convert.ToBase64String(data);
byte[] bb = Encoding.Default.GetBytes(ss);
result = new byte[b.Length + bb.Length];
b.CopyTo(result, 0);
bb.CopyTo(result, b.Length);
}
else if (stringData.Length != 0)
{
byte[] data2 = System.Text.Encoding.GetEncoding(charset).GetBytes(stringData);
result = new byte[b.Length + data2.Length];
b.CopyTo(result, 0);
data2.CopyTo(result, b.Length);
}
return result;
}//end fun
}//end class
public class SaveWebPage
{
ArrayList ContentParts = new ArrayList();
WebBrowser ControlObj;
string URL;
Uri baseUri;
ProgressBar Schedule;
ArrayList _toBeDownloaded = new ArrayList();
WebClient wc = new WebClient();
//ControlObj必需已经加载完毕文档
public SaveWebPage(WebBrowser ControlObj)
{
mshtml.IHTMLDocument2 doc;
doc = (mshtml.IHTMLDocument2)ControlObj.Document.DomDocument;
mshtml.IHTMLBaseElement baseElem = doc.all.item("base", 0) as mshtml.IHTMLBaseElement;
this.ControlObj = ControlObj;
URL = ControlObj.Url.ToString(); if (baseElem != null)
{
baseUri = new Uri(baseElem.href);
}
baseUri = new Uri(doc.location.href);
}
public String makeAbsoluteURL( Uri strWeb, String innerURL)
{
// TODO Auto-generated method stub
//去除后缀
int pos = innerURL.IndexOf('?');
if (pos != -1)
{ innerURL = innerURL.Substring(0, pos); } if (innerURL != null && innerURL.ToLower().IndexOf("http") == 0)
{ return innerURL; } Uri linkUri = null;
if (Uri.TryCreate(strWeb, innerURL, out linkUri))
{ return linkUri.AbsoluteUri; }
else
{ return ""; }
}//end fun
/// <summary>
/// 为了使用IE异步协议,让路径都具有http前辍
/// </summary>
/// <param name="location"></param>
/// <returns></returns>
public string MakeLocation(string location)
{
string s = "http://";
if (!string.Equals("http", location.Substring(0, 4)))
{
if (string.Equals("about:blank", location))
{
location = "blank/";
}
s += location;
return s;
}
else
{ return location; }
}//end fun
public string url
{
get
{ return this.URL; }
}
private string ProcessCssUrls(string content, Uri URI)
{
Regex reg = new Regex(@"url\((?<href>[^\)]*)\)", RegexOptions.IgnoreCase);
MatchCollection mc = reg.Matches(content);
foreach (Match m in mc)
{
if (m.Groups["href"].Value.IndexOf("//") <= 0)
{
string t = makeAbsoluteURL(URI, m.Groups["href"].Value);
content = content.Replace("url(" + m.Groups["href"].Value + ")", "url(" + t + ")");
}
}
return content;
}//end fun
private void SaveHTMLDocument(HtmlDocument ControlDoc)
{
mshtml.IHTMLDocument2 doc;
doc = (mshtml.IHTMLDocument2)ControlDoc.DomDocument;
string AbsoluteURL; mshtml.IHTMLElementCollection scripts = doc.all.tags("script") as mshtml.IHTMLElementCollection;
foreach (mshtml.IHTMLScriptElement e in scripts)
{
if (e.src == null)
{ continue; } if(!string.Equals("about:blank",URL))
{ AbsoluteURL = makeAbsoluteURL(baseUri, e.src); }
else
{ AbsoluteURL = e.src; }
if ( AbsoluteURL.Length != 0 )
{
e.src = AbsoluteURL;
_toBeDownloaded.Add(AbsoluteURL);
}
} mshtml.IHTMLElementCollection imgs = doc.all.tags("img") as mshtml.IHTMLElementCollection;
foreach (mshtml.IHTMLImgElement e in imgs)
{
if (e.src == null)
{ continue; } if (!string.Equals("about:blank", URL))
{ AbsoluteURL = makeAbsoluteURL(baseUri, e.src); }
else
{ AbsoluteURL = e.src; } if (AbsoluteURL.Length != 0)
{
e.src = AbsoluteURL;
_toBeDownloaded.Add(AbsoluteURL);
}
} //HTMLWindow2和MSHTML.IHTMLWindow2是不同的,在VS2005新增加的,应该说是包装了原来的IHTMLWindow2 接口
HTMLWindow2 fb;
HTMLFrameElement fe;
object x = 0;
for(int i=0;i<doc.frames.length;++i)
{
x = i;
fb = (HTMLWindow2)doc.frames.item(ref x);
try
{ fe = (HTMLFrameElement)fb.frameElement; }
catch (System.UnauthorizedAccessException)
{ continue; }
if (fe.src == null)
{ continue; } if (!string.Equals("about:blank", URL))
{ AbsoluteURL = makeAbsoluteURL(baseUri, fe.src); }
else
{ AbsoluteURL = fe.src; } if (AbsoluteURL.Length != 0)
{
fe.src = AbsoluteURL;
_toBeDownloaded.Add(AbsoluteURL);
}
} /*The FRAMESET element is a container for the FRAME element.
An HTML document can contain either the FRAMESET element or the BODY element, but not both.
FRAMESET页面和普遍的Web页面有些不同。虽然仍旧以<HTML>和包含标题的<HEAD>标记连同其他脚本开始
但是其内容仅仅是表示的各个页面的版式设计。因此,不再需要有<BODY>元素,只需要<FRAMESET>标记。
*/ //要下载的CSS文件地址包含在link标签中
mshtml.IHTMLElementCollection links = doc.all.tags("link") as mshtml.IHTMLElementCollection;
foreach (mshtml.IHTMLLinkElement e in links)
{
if (e.href == null)
{ continue; } if (!string.Equals("about:blank", URL))
{ AbsoluteURL = makeAbsoluteURL(baseUri, e.href); }
else
{ AbsoluteURL = e.href; } if (AbsoluteURL.Length != 0)
{
e.href = AbsoluteURL;
_toBeDownloaded.Add(AbsoluteURL);
}
}
mshtml.IHTMLElementCollection anchors = doc.all.tags("a") as mshtml.IHTMLElementCollection;
foreach (mshtml.IHTMLAnchorElement e in anchors)
{
if (e.href == null)
{ continue; } if (!string.Equals("about:blank", URL))
{ AbsoluteURL = makeAbsoluteURL(baseUri, e.href); }
else
{ AbsoluteURL = e.href; } e.href = AbsoluteURL;
} wc.Headers["Referer"] = URL;//当前页面的url,克服某些网站的防盗链措施
wc.CachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);
string contentType;
byte[] data = new byte[0];
Encoding enc;
for (int i = 0; i < _toBeDownloaded.Count; ++i)
{
try
{
//这里用时很长
data = wc.DownloadData((string)_toBeDownloaded[i]); contentType = wc.ResponseHeaders["content-type"];
enc = wc.Encoding; if (((string)_toBeDownloaded[i]).ToLower().EndsWith(".css") || contentType.ToLower().EndsWith("css"))
{
string content = enc.GetString(data);
content = ProcessCssUrls(content, new Uri((string)_toBeDownloaded[i]));//替换Css文件里的 url() 里的图片URL(从相对路径改为绝对路径,原理同上,这里自己解析CSS语法也不太难)
data = enc.GetBytes(content);//获得数据
} ContentPart cp = new ContentPart();
cp.Content_Type = contentType;
cp.Content_Transfer_Encoding = "base64";
cp.Data = data;
cp.Content_Location = (string)_toBeDownloaded[i]; if (cp.IsValid())
{ ContentParts.Add(cp); }
}
catch (Exception)
{
continue;
}
}//end for for (int i = 0; i < ControlDoc.Window.Frames.Count;++i )
{
try
{ SaveHTMLDocument(ControlDoc.Window.Frames[i].Document); }
catch (System.UnauthorizedAccessException)
{ continue; }
}
}//end fun
{
WebPageDateInfo wi = new WebPageDateInfo();
MemoryStream ms = new MemoryStream();
int CurPos = 0; SaveHTMLDocument(ControlObj.Document); //以下获取CharSet的代码来自网络
string dt = "";
try
{ dt = this.ControlObj.DocumentText; }
catch (System.IO.FileNotFoundException e_)
{ throw new SaveWebPageException(e_.Message, 9800031); } Match charSetMatch = Regex.Match(dt, "<meta([^<]*)charset=([^<]*)\"", RegexOptions.IgnoreCase | RegexOptions.Multiline);
string CharSet = charSetMatch.Groups[2].Value; bool charChange = false;
if (string.Equals(CharSet, "unicode"))
{
CharSet = "utf-16";
charChange = true;
}
StreamReader sr = new StreamReader(this.ControlObj.DocumentStream, System.Text.Encoding.GetEncoding(CharSet), true);
string sHtml = sr.ReadToEnd(); if (charChange)
{
CharSet = "utf-8";
sHtml.Replace("charset=unicode", "charset=utf-8");
byte[] temp1 = System.Text.Encoding.GetEncoding("utf-16").GetBytes(sHtml);
byte[] temp2 = Encoding.Convert(System.Text.Encoding.GetEncoding("utf-16"), System.Text.Encoding.GetEncoding("utf-8"), temp1);
sHtml = System.Text.Encoding.GetEncoding("utf-8").GetString(temp2);
} byte[] htmlDate = System.Text.Encoding.GetEncoding(CharSet).GetBytes(sHtml); ms.Write(htmlDate, 0, htmlDate.Length);
wi.Add("text/html", MakeLocation(this.URL), 0, htmlDate.Length);
CurPos += htmlDate.Length; for (int i = 0; i < ContentParts.Count; ++i)
{
byte[] dd = ((ContentPart)ContentParts[i]).Data;
ms.Write(dd, 0, dd.Length);
wi.Add(((ContentPart)ContentParts[i]).Content_Type, MakeLocation(((ContentPart)ContentParts[i]).Content_Location), CurPos, dd.Length);
CurPos += dd.Length;
} ms.WriteByte(13);
ms.Position = 0; byte[] result = Tools.StreamToBytes(ms);
date = result;
info = wi.ToBytes();
}//end fun }//end class
//异常类
public class SaveWebPageException : Exception
{
public int errorCode; public int ErrorCode
{
get
{ return errorCode; }
} public SaveWebPageException(string message, int ErrorCode)
: base(message)
{
this.errorCode = ErrorCode;
}
}//end class
public enum PI_FLAGS : uint
{
PI_PARSE_URL = 0x00000001,
PI_FILTER_MODE = 0x00000002,
PI_FORCE_ASYNC = 0x00000004,
PI_USE_WORKERTHREAD = 0x00000008,
PI_MIMEVERIFICATION = 0x00000010,
PI_CLSIDLOOKUP = 0x00000020,
PI_DATAPROGRESS = 0x00000040,
PI_SYNCHRONOUS = 0x00000080,
PI_APARTMENTTHREADED = 0x00000100,
PI_CLASSINSTALL = 0x00000200,
PI_PASSONBINDCTX = 0x00002000,
PI_NOMIMEHANDLER = 0x00008000,
PI_LOADAPPDIRECT = 0x00004000,
PD_FORCE_SWITCH = 0x00010000,
PI_PREFERDEFAULTHANDLER = 0x00020000
} public enum BSCF : uint
{
BSCF_FIRSTDATANOTIFICATION = 0,
BSCF_INTERMEDIATEDATANOTIFICATION = 1,
BSCF_LASTDATANOTIFICATION = 2,
BSCF_DATAFULLYAVAILABLE = 3,
BSCF_AVAILABLEDATASIZEUNKNOWN = 4,
} public class HRESULT
{
public static UInt32 S_OK = 0;
public static UInt32 S_FALSE = 1;
public static UInt32 INET_E_DEFAULT_ACTION = 0x800C0011;
} public enum TYMED : uint //Should be UInt32 but you can only use C# keywords here.
{
TYMED_HGLOBAL = 1,
TYMED_FILE = 2,
TYMED_ISTREAM = 4,
TYMED_ISTORAGE = 8,
TYMED_GDI = 16,
TYMED_MFPICT = 32,
TYMED_ENHMF = 64,
TYMED_NULL = 0
} public struct STGMEDIUM
{
[MarshalAs(UnmanagedType.U4)]
public TYMED enumType;
public IntPtr u;
[MarshalAs(UnmanagedType.IUnknown)]
public object pUnkForRelease;
} public enum BINDVERB : uint
{
BINDVERB_GET = 0,
BINDVERB_POST = 1,
BINDVERB_PUT = 2,
BINDVERB_CUSTOM = 3,
} public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
} public struct BINDINFO
{
public UInt32 cbSize;
[MarshalAs(UnmanagedType.LPWStr)]
public string szExtraInfo;
public STGMEDIUM stgmedData;
public UInt32 grfBindInfoF;
[MarshalAs(UnmanagedType.U4)]
public BINDVERB dwBindVerb;
[MarshalAs(UnmanagedType.LPWStr)]
public string szCustomVerb;
public UInt32 cbStgmedData;
public UInt32 dwOptions;
public UInt32 dwOptionsFlags;
public UInt32 dwCodePage;
public SECURITY_ATTRIBUTES securityAttributes;
public Guid iid;
[MarshalAs(UnmanagedType.IUnknown)]
public object pUnk;
public UInt32 dwReserved;
} public struct _tagPROTOCOLDATA
{
public uint grfFlags;
public uint dwState;
public IntPtr pData;
public uint cbData;
} public struct _LARGE_INTEGER
{
public Int64 QuadPart;
} public struct _ULARGE_INTEGER
{
public UInt64 QuadPart;
} [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E1-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetBindInfo
{
void GetBindInfo(out UInt32 grfBINDF, [In, Out] ref BINDINFO pbindinfo);
void GetBindString(UInt32 ulStringType, [MarshalAs(UnmanagedType.LPWStr)] ref string ppwzStr, UInt32 cEl, ref UInt32 pcElFetched);
} [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79EAC9E5-BAF9-11CE-8C82-00AA004BA90B")]
public interface IInternetProtocolSink
{
void Switch(ref _tagPROTOCOLDATA pProtocolData);
void ReportProgress(UInt32 ulStatusCode, [MarshalAs(UnmanagedType.LPWStr)] string szStatusText);
void ReportData(BSCF grfBSCF, UInt32 ulProgress, UInt32 ulProgressMax);
void ReportResult(Int32 hrResult, UInt32 dwError, [MarshalAs(UnmanagedType.LPWStr)] string szResult);
} [Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B"),
ComImport, TypeLibType((short)0),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetProtocol
{
//[PreserveSig()]
void Start([MarshalAs(UnmanagedType.LPWStr)] string szUrl,
IInternetProtocolSink pOIProtSink, IInternetBindInfo pOIBindInfo, uint grfPI, uint dwReserved); void Continue([In] ref _tagPROTOCOLDATA pProtocolData);
void Abort(uint hrReason, uint dwOptions);
void Terminate(uint dwOptions);
void Suspend();
void Resume(); //[PreserveSig()]
void Read(IntPtr pv, uint cb, out uint pcbRead);
void Seek(_LARGE_INTEGER dlibMove, uint dwOrigin, [Out] out _ULARGE_INTEGER plibNewPosition);
void LockRequest(uint dwOptions);
void UnlockRequest();
}
[ComVisible(true)]
[Guid("f975d010-3a14-4631-b6b1-3c9d20124f60"), ClassInterface(ClassInterfaceType.AutoDispatch)]
public class MhtHandler : IInternetProtocol
{
private const int S_OK = 0x00000000;
private const int S_FALSE = 0x00000001;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_POINTER = unchecked((int)0x80004005);
private const int INET_E_ERROR_FIRST = unchecked((int)0x800C0002);
private const int INET_E_INVALID_URL = unchecked((int)0x800C0002);
private const int INET_E_NO_SESSION = unchecked((int)0x800C0003);
private const int INET_E_CANNOT_CONNECT = unchecked((int)0x800C0004);
private const int INET_E_RESOURCE_NOT_FOUND = unchecked((int)0x800C0005);
private const int INET_E_OBJECT_NOT_FOUND = unchecked((int)0x800C0006);
private const int INET_E_DATA_NOT_AVAILABLE = unchecked((int)0x800C0007);
private const int INET_E_DOWNLOAD_FAILURE = unchecked((int)0x800C0008);
private const int INET_E_AUTHENTICATION_REQUIRED = unchecked((int)0x800C0009);
private const int INET_E_NO_VALID_MEDIA = unchecked((int)0x800C000A);
private const int INET_E_CONNECTION_TIMEOUT = unchecked((int)0x800C000B);
private const int INET_E_INVALID_REQUEST = unchecked((int)0x800C000C);
private const int INET_E_UNKNOWN_PROTOCOL = unchecked((int)0x800C000D);
private const int INET_E_SECURITY_PROBLEM = unchecked((int)0x800C000E);
private const int INET_E_CANNOT_LOAD_DATA = unchecked((int)0x800C000F);
private const int INET_E_CANNOT_INSTANTIATE_OBJECT = unchecked((int)0x800C0010);
private const int INET_E_USE_DEFAULT_PROTOCOLHANDLER = unchecked((int)0x800C0011);
private const int INET_E_QUERYOPTION_UNKNOWN = unchecked((int)0x800C0013);
private const int INET_E_REDIRECT_FAILED = unchecked((int)0x800C0014);
private const int INET_E_REDIRECT_TO_DIR = unchecked((int)0x800C0015);
private const int INET_E_CANNOT_LOCK_REQUEST = unchecked((int)0x800C0016); private const uint BINDSTATUS_FINDINGRESOURCE = 1;
private const uint BINDSTATUS_CONNECTING = BINDSTATUS_FINDINGRESOURCE + 1;
private const uint BINDSTATUS_REDIRECTING = BINDSTATUS_CONNECTING + 1;
private const uint BINDSTATUS_BEGINDOWNLOADDATA = BINDSTATUS_REDIRECTING + 1;
private const uint BINDSTATUS_DOWNLOADINGDATA = BINDSTATUS_BEGINDOWNLOADDATA + 1;
private const uint BINDSTATUS_ENDDOWNLOADDATA = BINDSTATUS_DOWNLOADINGDATA + 1;
private const uint BINDSTATUS_BEGINDOWNLOADCOMPONENTS = BINDSTATUS_ENDDOWNLOADDATA + 1;
private const uint BINDSTATUS_INSTALLINGCOMPONENTS = BINDSTATUS_BEGINDOWNLOADCOMPONENTS + 1;
private const uint BINDSTATUS_ENDDOWNLOADCOMPONENTS = BINDSTATUS_INSTALLINGCOMPONENTS + 1;
private const uint BINDSTATUS_USINGCACHEDCOPY = BINDSTATUS_ENDDOWNLOADCOMPONENTS + 1;
private const uint BINDSTATUS_SENDINGREQUEST = BINDSTATUS_USINGCACHEDCOPY + 1;
private const uint BINDSTATUS_CLASSIDAVAILABLE = BINDSTATUS_SENDINGREQUEST + 1;
private const uint BINDSTATUS_MIMETYPEAVAILABLE = BINDSTATUS_CLASSIDAVAILABLE + 1;
private const uint BINDSTATUS_CACHEFILENAMEAVAILABLE = BINDSTATUS_MIMETYPEAVAILABLE + 1; public static byte[] date = new byte[0];
public static byte[] info = new byte[0];
public static uint pos = 0;
public IInternetProtocolSink ProtSink;
WebPageDateInfo wdi = new WebPageDateInfo(); public static bool online = false;//指示数据是从date获取还是从网上获取
int dateStart;
int dateLength; public void LockRequest(uint dwOptions)
{
throw new COMException("", S_OK);
} public void Read(IntPtr pv, uint cb, out uint pcbRead)
{
if (!online && dateLength > 0 && (dateStart + dateLength <= date.Length))
{
byte[] buffer = new byte[dateLength];
Buffer.BlockCopy(date, dateStart, buffer, 0, dateLength); //MessageBox(0, string.Format("{0:d}", buffer.Length ), "", 0); if ((dateLength - pos) <= cb)
{
Marshal.Copy(buffer, (int)pos, pv, (int)(buffer.Length - pos));
pcbRead = (uint)(buffer.Length - pos);
pos = 0;
dateStart = 0;
dateLength = 0;
ProtSink.ReportResult(S_OK, 0, null);
//return S_FALSE;
throw new COMException("", S_FALSE);
}
else
{
Marshal.Copy(buffer, (int)pos, pv, (int)cb);
pos += cb;
pcbRead = cb;
//return S_OK;
throw new COMException("", S_OK);
}
}
else
{
pcbRead = 0;
ProtSink.ReportResult(S_OK, 0, null);
//return S_FALSE;
throw new COMException("", S_FALSE);
}
}//end fun public void Seek(_LARGE_INTEGER dlibMove, uint dwOrigin, [Out] out _ULARGE_INTEGER plibNewPosition)
{
plibNewPosition = new _ULARGE_INTEGER();
throw new COMException("", E_FAIL);
} public void UnlockRequest()
{
throw new COMException("", S_OK);
} public void Abort(uint hrReason, uint dwOptions)
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Continue([In] ref _tagPROTOCOLDATA pProtocolData)
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Resume()
{
throw new COMException("", INET_E_INVALID_REQUEST);
} [DllImport("user32")]
static extern int MessageBox(int hWnd, string text, string caption, int type); public void Start([MarshalAs(UnmanagedType.LPWStr)] string szUrl,
IInternetProtocolSink pOIProtSink, IInternetBindInfo pOIBindInfo, uint grfPI, uint dwReserved)
{
string type = "";
//MessageBox(0, string.Format("{0:d}/{1:d}", date.Length,info.Length), szUrl, 0); if ((grfPI & 0x00000001) != 0)
{ throw new COMException("", S_OK); } if (pOIProtSink == null)
{ throw new COMException("", E_POINTER); } if (online)
{ throw new COMException("", INET_E_USE_DEFAULT_PROTOCOLHANDLER); } ProtSink = pOIProtSink; if(wdi.Count == 0 && info.Length > 0)
{
wdi.FromBytes(info);
} if (wdi.Count > 0)
{
if (wdi.Get(szUrl, ref type,out dateStart, out dateLength))
{
/*
pOIProtSink.ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, type);
pOIProtSink.ReportData(BSCF.BSCF_FIRSTDATANOTIFICATION |
BSCF.BSCF_LASTDATANOTIFICATION |
BSCF.BSCF_DATAFULLYAVAILABLE, 0, (uint)dateLength);
*/
pOIProtSink.ReportData(BSCF.BSCF_LASTDATANOTIFICATION, 0, (uint)dateLength);
//pOIProtSink.ReportData(BSCF.BSCF_DATAFULLYAVAILABLE, 0, (uint)dateLength);
throw new COMException("", S_OK);
}
}
}//end fun public void Suspend()
{
throw new COMException("", INET_E_INVALID_REQUEST);
} public void Terminate(uint dwOptions)
{
throw new COMException("", S_OK);
} }//end class
[assembly: Guid("f975d010-3a14-4631-b6b1-3c9d20124f60")]该GUID值和MhtHandler的应该相同.另外DLL注册:做一个批处理文件,内容类似:call "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat"
gacutil /i APP_Mht.dll
regasm APP_Mht.dll
在应用程序中注册IE临时扩展协议(我最开始的提问) [DllImport("urlmon.dll")]
private static extern void CoInternetGetSession(uint sessionMode,
ref IInternetSession session, uint reserved); [DllImport("ole32.dll", ExactSpelling = true, CharSet =
CharSet.Unicode)]
public static extern int CoGetClassObject(
ref Guid rclsid, CLSCTX dwClsContext,
IntPtr pServerInfo, ref Guid riid,
[Out, MarshalAs(UnmanagedType.Interface)] out
object ppv); public const uint CLSCTX_INPROC_SERVER = 1;
public const uint CLSCTX_INPROC_HANDLER = 2;
public const uint CLSCTX_LOCAL_SERVER = 4;
public const uint CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER; public enum CLSCTX
{
INPROC_SERVER = 0x1,
INPROC_HANDLER = 0x2,
LOCAL_SERVER = 0x4,
INPROC_SERVER16 = 0x8,
REMOTE_SERVER = 0x10,
INPROC_HANDLER16 = 0x20,
RESERVED1 = 0x40,
RESERVED2 = 0x80,
RESERVED3 = 0x100,
RESERVED4 = 0x200,
NO_CODE_DOWNLOAD = 0x400,
RESERVED5 = 0x800,
NO_CUSTOM_MARSHAL = 0x1000,
ENABLE_CODE_DOWNLOAD = 0x2000,
NO_FAILURE_LOG = 0x4000,
DISABLE_AAA = 0x8000,
ENABLE_AAA = 0x10000,
FROM_DEFAULT_CONTEXT = 0x20000,
ACTIVATE_32_BIT_SERVER = 0x40000,
ACTIVATE_64_BIT_SERVER = 0x80000
}; object ic;
Guid guid = new Guid("f975d010-3a14-4631-b6b1-3c9d20124f60");
Guid guid2 = new Guid("00000001-0000-0000-C000-000000000046"); CoGetClassObject(ref guid, CLSCTX.INPROC_SERVER | CLSCTX.LOCAL_SERVER, IntPtr.Zero, ref guid2, out ic); IInternetSession s = null;
CoInternetGetSession(0, ref s, 0); s.RegisterNameSpace((IClassFactory)ic, ref guid, "http", 0, null, 0);
作为学习异步可插协议的入门案例,特求指点.
http://stackoverflow.com/questions/2013050/asynchronous-pluggable-protocols