none
msdn管理员您们好 RRS feed

  • 问题

  • 最近 在用.net开发的一个浏览器,经过数次测试,遇到个很棘手的问题,特此请教,不忘感激。

    是这样在我的newwindow事件

    (ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)这里ppdisp我知道是会话中滴cookie值,然而,经过这样的赋值ppdisp=SHDocVw.WebBrowser.Application以后浏览很正常,但是经过多次的newwindow3打开以后程序就崩溃了,我终于找到了原因,是我用同一个进程,多次调用和访问ppdisp对象所引发的ocx控件内存共享问题

    然后我又参照了一些内存共享滴例子,譬如CreateFileMapping和MapViewOfFile,用他们来传递ppdisp到另外一个进程,然而我在另外一个进程无法正确获取传递来的ppdisp,郁闷了,所以,请大神们帮忙,一下是简单的代码:备注:

     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern IntPtr CreateFileMapping(
                int hFile,
                IntPtr lpFileMappingAttributes,
                uint flProtect,
                uint dwMaximumSizeHigh,
                uint dwMaximumSizeLow,
                [MarshalAs(UnmanagedType.LPTStr)] string lpName);


            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr MapViewOfFile(
                IntPtr hFileMappingObject,
                FileMapAccess dwDesiredAccess,
                uint dwFileOffsetHigh,
                uint dwFileOffsetLow,
                uint dwNumberOfBytesToMap);

    进程一、

    webbrowser web=new webbrowser();

    web.newwindow3+=(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)=>{

    IntPtr m_hSharedMemoryFile = CreateFileMapping(-1, IntPtr.Zero, (uint)0x04, (uint)0, (uint)0x00800000, "MyBrowser");
                IntPtr m_pwData = MapViewOfFile(m_hSharedMemoryFile, FileMapAccess.FileMapAllAccess, (uint)0, (uint)0, (uint)0x00800000);


              //  IntPtr sp = Marshal.AllocCoTaskMem(16);
             //   Marshal.StructureToPtr(handles_1, sp, false);
                GCHandle handle = GCHandle.Alloc(ppdisp);
                IntPtr p1 = GCHandle.ToIntPtr(handle);
                CopyMemory(m_pwData, p1, 4);
               
                UnmapViewOfFile(m_pwData);

    //启动第二进程。。。

     System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo();

                //设置外部程序名 
                Info.FileName = "D:\\2\\rt\\rt\\obj\\Debug\\mybrowser.exe";
              
               
          
                Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
            
                System.Diagnostics.Process Proc = System.Diagnostics.Process.Start(Info);

    }

    进程二

    form1 f=new form();

    f.loaded+=load;

    void load(object sender, RoutedEventArgs e)

    {

    IntPtr m_hSharedMemoryFile = CreateFileMapping(-1, IntPtr.Zero, (uint)0x04, (uint)0, (uint)0x00800000, "MyBrowser");
                IntPtr m_pwData = MapViewOfFile(m_hSharedMemoryFile, FileMapAccess.FileMapAllAccess, (uint)0, (uint)0, (uint)0x00800000);

             


    IntPtr m_hSharedMemoryFile = CreateFileMapping(-1, IntPtr.Zero, (uint)0x04, (uint)0, (uint)0x00800000, "MyBrowser");
                IntPtr m_pwData = MapViewOfFile(m_hSharedMemoryFile, FileMapAccess.FileMapAllAccess, (uint)0, (uint)0, (uint)0x00800000);

            
                IntPtr p = Marshal.AllocCoTaskMem(Marshal.SizeOf(m_pwData));
                CopyMemory(p, m_pwData, Marshal.SizeOf(m_pwData));
               
                UnmapViewOfFile(m_pwData);

    ///然后  

    object ppdisp=GCHandle.FromIntPtr(p).Target;//这里报错

    }

    请问,我该如何传递我的ppdisp到另外一个进程,以便另外一个进程的webbrowser.application赋值于他

    2014年5月7日 0:35

答案

  • CreateFilemapping的参数设置对了吗

    参考下面的例子

     public class ShareMemoryProvider
        {
            const String FILEMAP_NAME = "TestFileMapping";
            const int ERROR_ALREADY_EXISTS = 183;   //共有内存已经作成
            // 
            const UInt32 FILE_MAP_WRITE = 0x02;
            const UInt32 PAGE_READWRITE = 0x04;
    
            // API定义
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr CreateFileMapping(UIntPtr hFile,
                IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh,
                uint dwMaximumSizeLow, string lpName);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint
                dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern Boolean UnmapViewOfFile(IntPtr lpBaseAddress);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern Boolean CloseHandle( IntPtr hObject );
    
            #region 变量
            // 句柄和指针定义 
            public static IntPtr mhShareMemory = IntPtr.Zero;
            public static IntPtr mpAddr = IntPtr.Zero;
            public stShareMemory shData;
    
            #endregion
    
            #region 公共内存数据作成
            public unsafe bool CreateShareMemory()
            {
                try
                {
                    mhShareMemory = CreateFileMapping((UIntPtr)0xFFFFFFFF, // 文件句柄 
                        IntPtr.Zero,        // 安全属性
                        PAGE_READWRITE,     // 保护属性(R/W) 
                        0,                  // 上位长度 
                        1024,               // 下位长度 
                        FILEMAP_NAME );     // 对象名 
    
                    int retval = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                    mpAddr = MapViewOfFile(mhShareMemory, FILE_MAP_WRITE, 0, 0, 0);
    
                    if (retval == ERROR_ALREADY_EXISTS)
                    {
                        object obj = 
                        	System.Runtime.InteropServices.Marshal.PtrToStructure(mpAddr, typeof(stShareMemory));
                        shData = (stShareMemory)obj;
                    }
                    else
                    {
                        shData = new stShareMemory();
                        System.Runtime.InteropServices.Marshal.StructureToPtr(shData, mpAddr, true);
                    }
                }
                catch (Exception ex)
                {
                    ex.ToString();
                }
                return false;
            }
    
            // 释放内存
            public unsafe void releaseShareMemory()
            {
                if ( mhShareMemory != IntPtr.Zero )
                {
                    if ( mpAddr != IntPtr.Zero )
                        UnmapViewOfFile( mpAddr );
                    CloseHandle( mhShareMemory );
                    mhShareMemory = IntPtr.Zero;
                }
            }
    
            // 数据取得
            public unsafe void getShareMemory()
            {
                object obj = 
                	System.Runtime.InteropServices.Marshal.PtrToStructure(mpAddr, typeof(stShareMemory));
                shData = (stShareMemory)obj;
            }
    
            // 数据设定
            public unsafe void setShareMemory()
            {
                System.Runtime.InteropServices.Marshal.StructureToPtr(shData, mpAddr, true);
            }
    
            #endregion
        }
    }


    2014年5月8日 6:19

全部回复

  • 你好:

    Windows Forms应用程序和WPF都有自己的WebBrowser控件,这个控件是对SHDocVw.Webbrowser的扩展,基本满足常用的功能需求,在新建窗口的时候也不会出现你说的这个问题。你是出于什么原因而不使用这个控件的呢?

    Winform的WebBrowser控件在新建窗口的时候应该是共享现有的cookie的,如果你不满足封装好的WebBrowser控件的NewWindow事件而非要使用SHDocVw.WebBrowser的newwindow3事件的话可以按照下面代码中的做法,将Winform的WebBrowser控件的实例转换为SHDocVw.WebBrowser,然后捕获其newwindow3事件,这样创建出来的新页面仍然是共享现有的cookie的。

    System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
    SHDocVw.WebBrowser axBrowser = (SHDocVw.WebBrowser)webBrowser.ActiveXInstance;
    
    axBrowser.NewWindow3 += new DWebBrowserEvents2_NewWindow3EventHandler(Browser_NewWindow3);

    更多信息可以参考以下文章:

    How to easily capture the NewWindow3 event and detect a JavaScript window.close() call with System.Windows.Forms.WebBrowser

    Extended .NET 2.0 WebBrowser Control


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年5月8日 3:18
    版主
  • 感谢您的答复,可能您还不了解我的意思,其实无论是wpf还是winform如果只通过url传递cookie是无法共享的那么,您可以看看我以前的提问

    http://social.msdn.microsoft.com/Forums/zh-CN/9424967c-36eb-47a4-8397-756d78da461d/webbrowser-control?forum=267

    所以在不使用windows api internetSetCookieEx或者internetGetCookieEx,必须使用ppdisp传递的会话托管指针,但是如果在同一个进程频繁的传递ppdisp=axwebbrowser.application的话,会导致程序崩溃,因此在参考其他浏览器浏览多个选项卡的时候,他们都是用了一对一进程调用,所以我的问题是怎么把ref object ppdisp 传递到另外一个进程,使得另外一个进程共享ppdisp对象,那么这个速度也快而且也不影响我的程序更改。随便举个例子啊谢谢

    2014年5月8日 3:42
  • CreateFilemapping的参数设置对了吗

    参考下面的例子

     public class ShareMemoryProvider
        {
            const String FILEMAP_NAME = "TestFileMapping";
            const int ERROR_ALREADY_EXISTS = 183;   //共有内存已经作成
            // 
            const UInt32 FILE_MAP_WRITE = 0x02;
            const UInt32 PAGE_READWRITE = 0x04;
    
            // API定义
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr CreateFileMapping(UIntPtr hFile,
                IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh,
                uint dwMaximumSizeLow, string lpName);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint
                dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern Boolean UnmapViewOfFile(IntPtr lpBaseAddress);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern Boolean CloseHandle( IntPtr hObject );
    
            #region 变量
            // 句柄和指针定义 
            public static IntPtr mhShareMemory = IntPtr.Zero;
            public static IntPtr mpAddr = IntPtr.Zero;
            public stShareMemory shData;
    
            #endregion
    
            #region 公共内存数据作成
            public unsafe bool CreateShareMemory()
            {
                try
                {
                    mhShareMemory = CreateFileMapping((UIntPtr)0xFFFFFFFF, // 文件句柄 
                        IntPtr.Zero,        // 安全属性
                        PAGE_READWRITE,     // 保护属性(R/W) 
                        0,                  // 上位长度 
                        1024,               // 下位长度 
                        FILEMAP_NAME );     // 对象名 
    
                    int retval = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                    mpAddr = MapViewOfFile(mhShareMemory, FILE_MAP_WRITE, 0, 0, 0);
    
                    if (retval == ERROR_ALREADY_EXISTS)
                    {
                        object obj = 
                        	System.Runtime.InteropServices.Marshal.PtrToStructure(mpAddr, typeof(stShareMemory));
                        shData = (stShareMemory)obj;
                    }
                    else
                    {
                        shData = new stShareMemory();
                        System.Runtime.InteropServices.Marshal.StructureToPtr(shData, mpAddr, true);
                    }
                }
                catch (Exception ex)
                {
                    ex.ToString();
                }
                return false;
            }
    
            // 释放内存
            public unsafe void releaseShareMemory()
            {
                if ( mhShareMemory != IntPtr.Zero )
                {
                    if ( mpAddr != IntPtr.Zero )
                        UnmapViewOfFile( mpAddr );
                    CloseHandle( mhShareMemory );
                    mhShareMemory = IntPtr.Zero;
                }
            }
    
            // 数据取得
            public unsafe void getShareMemory()
            {
                object obj = 
                	System.Runtime.InteropServices.Marshal.PtrToStructure(mpAddr, typeof(stShareMemory));
                shData = (stShareMemory)obj;
            }
    
            // 数据设定
            public unsafe void setShareMemory()
            {
                System.Runtime.InteropServices.Marshal.StructureToPtr(shData, mpAddr, true);
            }
    
            #endregion
        }
    }


    2014年5月8日 6:19
  • 好的感谢您的答复 我在试试
    2014年5月8日 23:13