[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);
static int TestWinApi()
{
MessageBox(0, "Hello Win32 Api", "peter", 4);
Console.ReadLine();
return 0;
}
C # 如 何 调 用 非 托 管 代 码
sender
using System;
using System.Collections.Generic;
using System.Text;
using NamedPipeLib;
using System.Runtime.InteropServices;
namespace Client
{
/// <summary>
/// Sender(Client)
/// </summary>
class Program
{
static void Main(string[] args)
{
// 定义管道的名字
string pipeName = "\\\\.\\pipe\\MyPipe";
while (true)
{
Console.WriteLine("input:");
string msg = Console.ReadLine();
if (msg == "EXIT")
break;
#region package infomation
//定义转换类的一个对象并初始化
Converter Convert = new Converter();
//定义消息结构体
MyMessage m;
//初始化消息结构体
m = new MyMessage(msg);
m.cmd_type = 1633837924;
m.srcID = 1633837925;
m.dstID = 1633837926;
//使用转换类的对象的StructToBytes方法把m结构体转换成Byte
Byte[] msgBuffer = Convert.StructToBytes(m);
#endregion
IntPtr fileHandle;
while (true)
{
// 创建命名管道
fileHandle = NamedPipeNative.CreateFile(pipeName,
NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE,
0, null, NamedPipeNative.OPEN_EXISTING, 0, 0);
// 创建失败时,跳出循环
if (fileHandle.ToInt32() != NamedPipeNative.INVALID_HANDLE_VALUE)
{
break;
}
// 无法打开管道时,不再执行下面的操作
if (NamedPipeNative.GetLastError() != NamedPipeNative.ERROR_PIPE_BUSY)
{
Console.WriteLine("pipe is busing");
return;
}
if (!NamedPipeNative.WaitNamedPipe(pipeName, 20000))
{
Console.WriteLine("can't open pipe");
return;
}
}
uint pipeMode = NamedPipeNative.PIPE_READMODE_MESSAGE;
bool success = NamedPipeNative.SetNamedPipeHandleState(fileHandle, ref pipeMode, IntPtr.Zero, IntPtr.Zero);
if (!success)
{
Console.WriteLine("设置管道状态失败");
return;
}
// 定义信息的长度
uint len = (uint)msgBuffer.Length;
byte[] numReadWritten = new byte[4];
// 把数据写到管道
success = NamedPipeNative.WriteFile(fileHandle, BitConverter.GetBytes(len), 4, numReadWritten, 0);
// 写入数据失败时的处理
if (!success)
{
Console.WriteLine("写入数据失败");
return;
}
else
{
NamedPipeNative.WriteFile(fileHandle, msgBuffer, len, numReadWritten, 0);
}
// 关闭打开的管道
NamedPipeNative.CloseHandle(fileHandle);
}
}
}
}
reveiver
using System;
using System.Collections.Generic;
using System.Text;
using NamedPipeLib;
using System.Threading;
namespace Server
{
/// <summary>
/// Receive(Server)
/// </summary>
class Program
{
static void Main(string[] args)
{
while (true)
{
// 实例化跨网通讯,双向的可靠的管道
IntPtr pipeHandle = NamedPipeNative.CreateNamedPipe(
"\\\\.\\pipe\\MyPipe",
NamedPipeNative.PIPE_ACCESS_DUPLEX,
NamedPipeNative.PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_READMODE_MESSAGE,
NamedPipeNative.PIPE_UNLIMITED_INSTANCES,
1024,
1024,
0,
IntPtr.Zero);
// 返回前一个异常
uint u = NamedPipeNative.GetLastError();
// 创建实例失败时,返回INVALID_HANDLE_VALUE
if (pipeHandle.ToInt32() == NamedPipeNative.INVALID_HANDLE_VALUE)
{
Console.WriteLine("创建管道出错");
return;
}
// 启用命名管道服务器进程等待一个客户进程连接到命名管道实例。成功时返回true,失败时返回ERROR_PIPE_CONNECTED
bool connected = NamedPipeNative.ConnectNamedPipe(pipeHandle, null) ? true : (NamedPipeNative.GetLastError() == NamedPipeNative.ERROR_PIPE_CONNECTED);
// 成功启用命名管道服务器进程等待一个客户进程连接到命名管道实例
if (connected)
{
// 将ReadMessage方法排入队列以便执行,并指定包含该方法所用数据的对象pipeHandle。
// 此方法在有线程池线程变得可用时执行。
ThreadPool.QueueUserWorkItem(new WaitCallback(ReadMessage), pipeHandle);
}
else
{
// 失败时,关闭打开的pipeHandle对象
NamedPipeNative.CloseHandle(pipeHandle);
}
}
}
/// <summary>
/// 读取客户端数据
/// </summary>
/// <param name="arg"></param>
public static void ReadMessage(object arg)
{
// 取得管道对象
IntPtr pipeHandle = (IntPtr)arg;
byte[] numReadWritten = new byte[4];
byte[] intBytes = new byte[4];
NamedPipeNative.ReadFile(pipeHandle, intBytes, 4, numReadWritten, 0);
int len = BitConverter.ToInt32(intBytes, 0);
byte[] recBuffer=new byte[len];
NamedPipeNative.ReadFile(pipeHandle, recBuffer, (uint)len, numReadWritten, 0);
// 取得客户端发送的信息
//string str=Encoding.UTF8.GetString(recBuffer);
#region package infomation
//定义转换类的一个对象并初始化
Converter Convert = new Converter();
MyMessage m = new MyMessage();
MyMessage mm = (MyMessage)Convert.BytesToStruct(recBuffer, m.GetType());
Console.WriteLine("1"+mm.cmd_type);
Console.WriteLine("2"+mm.username);
Console.WriteLine("3"+mm.srcID);
Console.WriteLine("4"+mm.dstID);
#endregion
// 一个已被某客户端连接的管道句柄在被另一客户通过 ConnectNamedPipe建立连接之前,服务端必须用DisconnectNamedPipe函数对已存在的连接进行强行拆离。
// 服务端拆离管道会造成管道中数据的丢失,用FlushFileBuffers函数可以保证数据不被丢失。
NamedPipeNative.FlushFileBuffers(pipeHandle); // 刷新缓冲区的指定文件,并把所有缓冲数据写入到一个文件。
// 从客户端进程断开以服务器端命名的管道实例
NamedPipeNative.DisconnectNamedPipe(pipeHandle);
// 关闭打开的管道对象
NamedPipeNative.CloseHandle(pipeHandle);
}
}
}
namlib
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace NamedPipeLib
{
public static class NamedPipeNative
{
/// <summary>
/// 3
/// </summary>
public const uint PIPE_ACCESS_DUPLEX = 0x00000003;
/// <summary>
/// 2
/// </summary>
public const uint PIPE_READMODE_MESSAGE = 0x00000002;
/// <summary>
/// 4
/// </summary>
public const uint PIPE_TYPE_MESSAGE = 0x00000004;
/// <summary>
/// 0
/// </summary>
public const uint PIPE_WAIT = 0x00000000;
public const uint PIPE_UNLIMITED_INSTANCES = 255;
public const int INVALID_HANDLE_VALUE = -1;
public const ulong ERROR_PIPE_CONNECTED = 535;
/// <summary>
/// 1G
/// </summary>
public const uint GENERIC_WRITE = (0x40000000);
/// <summary>
/// 2G
/// </summary>
public const uint GENERIC_READ = (0x80000000);
public const uint OPEN_EXISTING = 3;
public const ulong ERROR_PIPE_BUSY = 231;
/// <summary>
/// 非托管代码调用 把win32要转成c#数据类型
/// </summary>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
String lpFileName, // file name
uint dwDesiredAccess, // access mode
uint dwShareMode, // share mode
SecurityAttributes attr, // SD
uint dwCreationDisposition, // how to create
uint dwFlagsAndAttributes, // file attributes
uint hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(
String lpName, // pipe name
uint dwOpenMode, // pipe open mode
uint dwPipeMode, // pipe-specific modes
uint nMaxInstances, // maximum number of instances
uint nOutBufferSize, // output buffer size
uint nInBufferSize, // input buffer size
uint nDefaultTimeOut, // time-out interval
IntPtr pipeSecurityDescriptor // SD
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ConnectNamedPipe(
IntPtr hHandle, // handle to named pipe
Overlapped lpOverlapped // overlapped structure
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(
IntPtr hHandle, // handle to file
byte[] lpBuffer, // data buffer
uint nNumberOfBytesToRead, // number of bytes to read
byte[] lpNumberOfBytesRead, // number of bytes read
uint lpOverlapped // overlapped buffer
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteFile(
IntPtr hHandle, // handle to file
byte[] lpBuffer, // data buffer
uint nNumberOfBytesToWrite, // number of bytes to write
byte[] lpNumberOfBytesWritten, // number of bytes written
uint lpOverlapped // overlapped buffer
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FlushFileBuffers(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DisconnectNamedPipe(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetNamedPipeHandleState(
IntPtr hHandle,
ref uint mode,
IntPtr cc,
IntPtr cd);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WaitNamedPipe(
String name,
int timeout);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetLastError();
}
[StructLayout(LayoutKind.Sequential)]
public class Overlapped
{
}
[StructLayout(LayoutKind.Sequential)]
public class SecurityAttributes
{
}
}
mymessage
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace NamedPipeLib
{
/// <summary>
/// define struct message
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyMessage
{
public UInt32 cmd_type;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string username;
public UInt32 dstID;
public UInt32 srcID;
public MyMessage(string s)
{
cmd_type = 0;
username = s;
dstID = 0;
srcID = 0;
}
}
}
cover
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace NamedPipeLib
{
public class Converter
{
public Byte[] StructToBytes(Object structure)
{
Int32 size = Marshal.SizeOf(structure);
//Console.WriteLine(size);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(structure, buffer, false);
Byte[] bytes = new Byte[size];
Marshal.Copy(buffer, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
public Object BytesToStruct(Byte[] bytes, Type strcutType)
{
Int32 size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
}
}