小弟想把内存中的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,
    }-- 下面继续

解决方案 »

  1.   


       [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  
    }
      

  2.   

    不要自己手动定义com声明,直接把urlmon.dll作为com引用添加到项目引用里。
      

  3.   

    无法引用urlmon.dll 提示:
    未能添加对urlmon.dll的引用,这不是一个有效的程序集或COM组件,只有具有扩展名dll的程序集和COM组件才能被引用
      

  4.   


    看来是你的urlmon没注册,先注册然后添加引用就行了。
      

  5.   

    我怎么感觉好像再搞BHO呢??可以扩展ie协议!
      

  6.   

    感谢所有回贴及关注此贴的朋友:经过艰苦的努力,我已经解决了问题,本回复后将结贴。我的初衷是把网页全部内容保存为一个字节数组,反之把字节数组还原为网页。这么做是为了便于和数据库交互。众所周知,网页包含丰富的数据信息。我们用IE保存网页时,一般会在目标位置生成一个html文件和一个文件夹。因此要把网页数据全部放到字节数组里是没有直接方法可用的。由于IE可以把网页数据全部封装到一个mht文件里面,所以我就想以mht格式作为桥梁来实现我的目标。
    首先是把网页数据保存为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#了,跨跃式发展嘛:)接下来,我贴一些代码。
      

  7.   

    保存网页数据为字节数组<1>
        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
      

  8.   

    论坛禁止一个用户连续回复三次,偶只好换个马甲继续贴代码了。保存网页数据为字节数组<2>  -- 代码选自我工程中
       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
      

  9.   

    保存网页数据为字节数组 <3>  -- 代码选自我工程中        public void CreateDate(out byte[] date,out byte[] info)
            {
                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
      

  10.   

    又到发言次数限制了,脱了马甲。。前面几贴代码大概介绍了把网页保存为字节数组,下面贴的是使用IE异步协议,把字节数组中数据提交给IE。IE异步可插入协议是让你用一个DLL来实现的。在C#环境下,各种转换比较麻烦。由于代码量大,一个回复所允许的字数又有限,所以我难以把所有代码都贴上来。说一下关键地方:一些重要的接口,数据结构在C#中的声明:
        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();
        }
      

  11.   


        [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  
      

  12.   

    另外说一个注意事项:// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
    [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);
      

  13.   

    非常感谢Win32FanEx,正在了解这方面的资料,偶是用vb.net,不知道能不能实现
      

  14.   

    最近在研究这个,我有几个问题请教楼主: 1.关于临时的异步可插协议这一部分,是否需要生成 dll ?2.如何在主窗体的构造函数中添加对临时协议的注册语句, ICalssFactory、ProtocolHandler 等,先创建哪一个的实例?3.网上有一个经典的ASPX永久的异步可插协议(http://www.codeproject.com/KB/aspnet/AspxProtocol.aspx)实现,其中提供了一个简单的echo协议,可以单独提取出来(这几个文件:ComSupport.cs 、EchoProtocol.cs、ProtocolBase.cs、ProtocolSupport.cs),文件都不用修改,直接编译成dll成功,测试通过,注册之后,浏览 echo:abcdefg 会直接在浏览器中输出 abcdefg ,请教该如何修改成 临时的 echo 协议 ?问题较多,还望不吝赐教,非常感谢 !
      

  15.   

    上述echo协议,我打算在.Net 2.0的 WebBrowser 中实现,C# 语言,
    作为学习异步可插协议的入门案例,特求指点.
      

  16.   

    通过这里解决:
    http://stackoverflow.com/questions/2013050/asynchronous-pluggable-protocols