在.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上面的一个朋友的文章.
浙公网安备 33010602011771号