c#读写共享内存操作函数封装

       c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。

        现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。

/// <summary>
        /// 写共享内存
        /// </summary>
        /// <param name="structSize">需要映射的文件的字节数量</param>
        /// <param name="obj">映射对象(简单类型、结构体等)</param>
        /// <param name="fileName">文件映射对象的名称</param>
        /// <param name="windowName">发送消息的窗口句柄</param>
        /// <param name="Msg">发送消息</param>
        /// <returns></returns>
        public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)
        {
            IntPtr hShareMemoryHandle = IntPtr.Zero;
            IntPtr hVoid = IntPtr.Zero;

            //判断参数的合法性
            if (structSize > 0 && fileName.Length > 0)
            {
                hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);
                if (hShareMemoryHandle == IntPtr.Zero)
                {
                    //创建共享内存失败,记log
                    MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());
                    return -2;
                }
                else
                {
                    if (ERROR_ALREADY_EXISTS == GetLastError())
                    {
                        //共享内存已经存在,记log
                        MessageBox.Show("共享内存已经存在");
                        return -3;
                    }
                }
                hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);
                if (hVoid == IntPtr.Zero)
                {
                    CloseHandle(hShareMemoryHandle);
                    //文件映射失败,记log
                    MessageBox.Show("文件映射失败");
                    return -4;
                }
                Marshal.StructureToPtr(obj, hVoid, false);
                //发送消息,通知接收
                IntPtr handle = FindWindow(null, windowName.Trim());
                if (handle == IntPtr.Zero)
                {
                    //查找窗口失败,记log
                    MessageBox.Show("查找窗口失败");
                    return -5;
                }
                else
                {
                    if (PostMessage(handle, (uint)Msg, 0, 0))
                    {
                        //发送消息成功
                        //MessageBox.Show("写共享内存,通知发送消息成功");
                    }
                }
            }
            else
            {
                //参数不合法,记log
                MessageBox.Show("共享内存已经存在");
                return -1;
            }
            return 0;
        }
  写共享内存函数并没有什么需要说明,完全按照:

创建共享内存文件(CreateFileMapping)---》映射文件视图到调用进程的地址空间(MapViewOfFile)---》写数据到共享内存(Marshal.StructureToPtr)----》发送消息通知需要读共享内存的窗口(PostMessage)

/// <summary>
        /// 读共享内存
        /// </summary>
        /// <param name="structSize">需要映射的文件的字节数量</param>
        /// <param name="type">类型</param>
        /// <param name="fileName">文件映射对象的名称</param>
        /// <returns>返回读到的映射对象</returns>
        public static Object ReadFromMemory(uint structSize, Type type, string fileName)
        {

            IntPtr hMappingHandle = IntPtr.Zero;
            IntPtr hVoid = IntPtr.Zero;

            hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
            if (hMappingHandle == IntPtr.Zero)
            {
                //打开共享内存失败,记log
                MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
                return null;
            }
            hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
            if (hVoid == IntPtr.Zero)
            {
                //文件映射失败,记log
                MessageBox.Show("文件映射失败——读共享内存");
                return null;
            }

            Object obj = Marshal.PtrToStructure(hVoid, type);

            if (hVoid != IntPtr.Zero)
            {
                UnmapViewOfFile(hVoid);
                hVoid = IntPtr.Zero;
            }
            if (hMappingHandle != IntPtr.Zero)
            {
                CloseHandle(hMappingHandle);
                hMappingHandle = IntPtr.Zero;
            }
            return obj;
        }

         读共享内存,上边代码是一种方式,这里是传入一个Type类型,这样就确保可以传入任何类型。当读到共享内存的数据时,采用

         public static object PtrToStructure(IntPtr ptr, Type structureType);

        函数,把非托管指针(共享内存获得的指针)转换为需要转换的Type类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。

       

/// <summary>
        /// 读共享内存
        /// </summary>
        /// <param name="structSize">需要映射的文件的字节数量</param>
        /// <param name="type">类型</param>
        /// <param name="fileName">文件映射对象的名称</param>
        /// <returns>返回读到的映射字节数据</returns>
        public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)
        {

            IntPtr hMappingHandle = IntPtr.Zero;
            IntPtr hVoid = IntPtr.Zero;

            hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
            if (hMappingHandle == IntPtr.Zero)
            {
                //打开共享内存失败,记log
                MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
                return null;
            }
            hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
            if (hVoid == IntPtr.Zero)
            {
                //文件映射失败,记log
                MessageBox.Show("文件映射失败——读共享内存");
                return null;
            }

            //Object obj = Marshal.PtrToStructure(hVoid, type);
            byte[] bytes = new byte[structSize];
            Marshal.Copy(hVoid, bytes, 0, bytes.Length);

            if (hVoid != IntPtr.Zero)
            {
                UnmapViewOfFile(hVoid);
                hVoid = IntPtr.Zero;
            }
            if (hMappingHandle != IntPtr.Zero)
            {
                CloseHandle(hMappingHandle);
                hMappingHandle = IntPtr.Zero;
            }
            return bytes;
        }
        此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。

 byte[] bytes = new byte[structSize];
Marshal.Copy(hVoid, bytes, 0, bytes.Length);

      调用简单例子部分代码如下:

注:passiveInfo是NotifyInfo结构体对象。

      写共享内存:

int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);

     读共享内存:

第一种情况调用:

passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);
      第二种情况调用:

byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");
passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));

      希望对你有帮助。

     转载请标注:http://blog.csdn.net/richerg85

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值