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

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

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

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

 

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 写共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="obj">映射对象(简单类型、结构体等)</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <param name="windowName">发送消息的窗口句柄</param>  
  8.         /// <param name="Msg">发送消息</param>  
  9.         /// <returns></returns>  
  10.         public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)  
  11.         {  
  12.             IntPtr hShareMemoryHandle = IntPtr.Zero;  
  13.             IntPtr hVoid = IntPtr.Zero;  
  14.   
  15.             //判断参数的合法性  
  16.             if (structSize > 0 && fileName.Length > 0)  
  17.             {  
  18.                 hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);  
  19.                 if (hShareMemoryHandle == IntPtr.Zero)  
  20.                 {  
  21.                     //创建共享内存失败,记log  
  22.                     MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());  
  23.                     return -2;  
  24.                 }  
  25.                 else  
  26.                 {  
  27.                     if (ERROR_ALREADY_EXISTS == GetLastError())  
  28.                     {  
  29.                         //共享内存已经存在,记log  
  30.                         MessageBox.Show("共享内存已经存在");  
  31.                         return -3;  
  32.                     }  
  33.                 }  
  34.                 hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);  
  35.                 if (hVoid == IntPtr.Zero)  
  36.                 {  
  37.                     CloseHandle(hShareMemoryHandle);  
  38.                     //文件映射失败,记log  
  39.                     MessageBox.Show("文件映射失败");  
  40.                     return -4;  
  41.                 }  
  42.                 Marshal.StructureToPtr(obj, hVoid, false);  
  43.                 //发送消息,通知接收  
  44.                 IntPtr handle = FindWindow(null, windowName.Trim());  
  45.                 if (handle == IntPtr.Zero)  
  46.                 {  
  47.                     //查找窗口失败,记log  
  48.                     MessageBox.Show("查找窗口失败");  
  49.                     return -5;  
  50.                 }  
  51.                 else  
  52.                 {  
  53.                     if (PostMessage(handle, (uint)Msg, 0, 0))  
  54.                     {  
  55.                         //发送消息成功  
  56.                         //MessageBox.Show("写共享内存,通知发送消息成功");  
  57.                     }  
  58.                 }  
  59.             }  
  60.             else  
  61.             {  
  62.                 //参数不合法,记log  
  63.                 MessageBox.Show("共享内存已经存在");  
  64.                 return -1;  
  65.             }  
  66.             return 0;  
  67.         }  

  写共享内存函数并没有什么需要说明,完全按照:

 

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

 

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射对象</returns>  
  8.         public static Object ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.   
  31.             if (hVoid != IntPtr.Zero)  
  32.             {  
  33.                 UnmapViewOfFile(hVoid);  
  34.                 hVoid = IntPtr.Zero;  
  35.             }  
  36.             if (hMappingHandle != IntPtr.Zero)  
  37.             {  
  38.                 CloseHandle(hMappingHandle);  
  39.                 hMappingHandle = IntPtr.Zero;  
  40.             }  
  41.             return obj;  
  42.         }  

 

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

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

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

       

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射字节数据</returns>  
  8.         public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             //Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.             byte[] bytes = new byte[structSize];  
  31.             Marshal.Copy(hVoid, bytes, 0, bytes.Length);  
  32.   
  33.             if (hVoid != IntPtr.Zero)  
  34.             {  
  35.                 UnmapViewOfFile(hVoid);  
  36.                 hVoid = IntPtr.Zero;  
  37.             }  
  38.             if (hMappingHandle != IntPtr.Zero)  
  39.             {  
  40.                 CloseHandle(hMappingHandle);  
  41.                 hMappingHandle = IntPtr.Zero;  
  42.             }  
  43.             return bytes;  
  44.         }  

        此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。

 

 

[csharp] view plaincopy
  1. byte[] bytes = new byte[structSize];  
  2. arshal.Copy(hVoid, bytes, 0, bytes.Length);  

 

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

注:passiveInfo是NotifyInfo结构体对象。

      写共享内存:

 

[csharp] view plaincopy
  1. int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);  

 

     读共享内存:

第一种情况调用:

 

[csharp] view plaincopy
  1. passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);  

      第二种情况调用:

 

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

 

 

      希望对你有帮助。

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

上一篇:Java知识点.线程-线程安全


下一篇:mysql日志监控