|
Posted on
2004-07-05 23:32
hbiftsaa
阅读( 3257)
评论()
编辑
收藏
举报
在.NET中,进行程序间通信,可以使用的方法很多,比如.NET Remoting,WebService.等等.. 但是使用上述方法太过于麻烦.不是很轻便..
在Win32中,一般要完成上述功能,方法也很多,一个比较通用的方法就是直接使用内存映射文件.Mapping File. .NET FX1.0提供了P/Invoke,可能通过这个来直接调用Win32的API.这里我来演示一下这个方法.
要使用P/Invoke,我们得加入这个命名空间: System.Runtime.InteropServices 然后使用DllImportAttribute来导入我们所要用的Win32 API:
DllImport#region DllImport [StructLayout(LayoutKind.Sequential)] private struct SECURITY_ATTRIBUTES { int nLength; int lpSecurityDescriptor; bool bInheritHandle; }
[DllImport("kernel32",CharSet = CharSet.Auto)] private static extern int CreateFileMapping( int hFile, int lpSecurityAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, [MarshalAs(UnmanagedType.LPTStr)] string lpName );
[DllImport("kernel32",CharSet = CharSet.Auto)] private static extern int OpenFileMapping( int dwDesiredAccess, bool bInheritHandle, [MarshalAs(UnmanagedType.LPTStr)] string lpName );
[DllImport("kernel32",CharSet = CharSet.Auto)] private static extern bool UnmapViewOfFile(int lpBaseAddress);
[DllImport("kernel32",CharSet = CharSet.Auto)] private static extern void CloseHandle(int Handle);
[DllImport("kernel32",CharSet = CharSet.Auto)] private static extern int MapViewOfFile( int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap ); #endregion 由于原始的API使用到了多个Enum,我们也实现这些个Enum,以方便以后的使用.
Mapping File Enum Info#region Mapping File Enum Info public enum ProtectionTypes:int { PageReadOnly = 0x2, PageReadWrite = 0x4, PageWriteCopy = 0x8 }
public enum SectionTypes:int { SecCommit = 0x8000000, SecImage = 0x1000000, SecNoCache = 0x10000000, SecReserve = 0x4000000 }
public enum AccessTypes:int { Copy = 0x1, Read = 0x4, Write = 0x2, Full = 0xF001F } #endregion 接下来,就是把这些函数进行封装了:) 这里,我把这些函数封装到一个Class中,其Class的定义如下:
SharedMemory#region SharedMemory public class SharedMemory : IDisposable { Private & Public Variable#region Private & Public Variable private const int INVALID_HANDLE_VALUE = -1; private int hMap = INVALID_HANDLE_VALUE; private int lpAddr = 0; private int size; private int length; public int MapHandle { get{return hMap;} } public int Address { get{return lpAddr;} }
public int Size { get{ return size;} }
public int Length { get{ return length;} } #endregion
Constructor#region Constructor public SharedMemory(){} public SharedMemory(int Size,string Name) : this( Size,Name,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full){} public SharedMemory(int Size, string Name, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access ) { Create(Size, Name, Protection, Section, Access); }
#endregion
Common Function#region Common Function public void Create( int Size,string Name) { Create( Size,Name,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full); }
public void Create( int Size, string Name,ProtectionTypes Protection, SectionTypes Section, AccessTypes Access) { Dispose(); size = Size; hMap = CreateFileMapping(INVALID_HANDLE_VALUE, 0, (int)Protection|(int)Section, 0, Size, Name); if(hMap ==0) { throw new ApplicationException("Can't Create MappingFile " + Name); } lpAddr = MapViewOfFile(hMap, (int)Access, 0, 0, Size); }
public void Open(int Size, string Name){this.Open(Size, Name, 0, AccessTypes.Read);} public void Open(int Size, string Name, AccessTypes Access){this.Open(Size, Name, 0, Access);} public void Open(int Size, string Name, int Offset){this.Open(Size, Name, Offset, AccessTypes.Read);} public void Open(int Size, string Name, int Offset, AccessTypes Access) { size = Size; hMap = OpenFileMapping((int)Access, false, Name); if(hMap == 0) { throw new ApplicationException("Can't Open MappingFile " + Name); } lpAddr = MapViewOfFile(hMap, (int)Access, 0, Offset, Size); }
public void CopyFrom(byte[] source,int startIndex,int length) { this.length = length; Marshal.Copy(source,startIndex,new IntPtr(Address),length); }
public void CopyFrom(byte[] source) { CopyFrom(source,0,source.Length); }
public void CopyFrom(string source) { byte[] temp = Encoding.Unicode.GetBytes(source); CopyFrom(temp,0,temp.Length); }
public void CopyTo(byte[] destination,int startIndex,int length) { Marshal.Copy( new IntPtr(Address),destination,startIndex,length); }
public byte[] CopyToBytes() { byte[] destination = new byte[Size]; CopyTo( destination,0,Size); return destination; }
public byte[] CopyToBytes(int startIndex,int length) { byte[] destination = new byte[Size]; CopyTo( destination,startIndex,length); return destination; }
public string CopyToString(out string destination) { destination = CopyToString(); return destination; }
public string CopyToString() { byte[] temp = new byte[Size]; CopyTo(temp,0,temp.Length); return Encoding.Unicode.GetString(temp).Trim(); }
public void Close() { Dispose(); }
public void Dispose() { if( lpAddr != 0 ) { UnmapViewOfFile(lpAddr); } if( hMap != 0 && hMap != INVALID_HANDLE_VALUE ) { CloseHandle(hMap); } } #endregion }
#endregion 注意: 加入上述DllImport函数. 通过这个方法,我们就可以直接使用MappingFile了. 示例代码如下:
public void Test(){ SharedMemory sm = new SharedMemory(); sm.Create(1024,"hbifts"); sm.CopyFrom("hoho.i love cnblogs"); SharedMemory sm1 = new SharedMemory(); sm1.Open(1024,"hbifts"); Console.WriteLine(sm1.CopyToString()); } 到现在为止,关于Win32的MappingFile API就已封装好了~ 我们可以直接在.NET应用程序中使用了:) 下载 : SharedMemory注: 此代码参考于Gotdotnet上面的一个朋友的文章.
|