|
|
Posted on
2004-07-05 23:32
hbiftsaa
阅读( 3281)
评论()
收藏
举报
在.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上面的一个朋友的文章.
|