首页 C++与C#进程通信案例[附源码]

C++与C#进程通信案例[附源码]

举报
开通vip

C++与C#进程通信案例[附源码]C++与C#进程通信案例[附源码] 最新C++与C#进程通信案例源码,欢迎在线学习c++ 教程.“命名管道”是一种简单的进程间通信(IPC)机制。命名管道可在同一台计算机的不同进程之间, 或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数 据通信。用命名管道来设计应用程序实际非常简单,并不需要事先深入掌握基层 网络传送协议(如TCP/IP或IPX)的知识。因为命名管道利用了微软网络提供 者(MSNP)重定向器,通过一个网络,在各进程间建立通信。这样一来,应用程 序便不必关心网络协议的细节。 ...

C++与C#进程通信案例[附源码]
C++与C#进程通信 案例 全员育人导师制案例信息技术应用案例心得信息技术教学案例综合实践活动案例我余额宝案例 [附源码] 最新C++与C#进程通信案例源码,欢迎在线学习c++ 教程.“命名管道”是一种简单的进程间通信(IPC)机制。命名管道可在同一台计算机的不同进程之间, 或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数 据通信。用命名管道来设计应用程序实际非常简单,并不需要事先深入掌握基层 网络传送 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 (如TCP/IP或IPX)的知识。因为命名管道利用了微软网络提供 者(MSNP)重定向器,通过一个网络,在各进程间建立通信。这样一来,应用程 序便不必关心网络协议的细节。 命令管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系 统”(NamedPipeFileSystem,NPFS)接口。因此,客户机和服务器应用可利用标 准的Win32文件系统API函数(如ReadFile和WriteFile)来进行数据的收发。通过这些API函数,应用程序便可直接利用Win32文件系统命名规范,以及 WindowsNT/Windows2000文件系统的安全机制。NPFS依赖于MSNP重定向器在网上进行命名管道数据的发送和接收。这样一来,便可实现接口的“与协议无关” 特性:若在自己开发的应用程序中使用命名管道在网上不同的进程间建立通信, 程序员不必关心基层网络传送协议(如TCP和IPX等等)的细节。 命名管道最大的特点便是建立一个简单的客户机/服务器程序设计体系。在 这个体系结构中,在客户机与服务器之间,数据既可单向传递,亦可双向流动。 对命名管道 服务器和客户机来说,两者的区别在于:服务器是唯一一个有权创 建命名管道的进程,也只有它才能接受管道客户机的连接请求。对一个客户机应 用来说,它只能同 一个现成的命名管道服务器建立连接。在客户机应用和服务 器应用之间,一旦建好连接,两个进程都能对 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 的Win32函数,在管道上进行数据的读取与写入。这些函数包括ReadFile和WriteFile等等。 要想实现一个命名管道服务器,要求必须开发一个应用程序,通过它创建命 名管道的一个或多个“实例”,再由客户机进行访问。对服务器来说,管道实例 实际就是一个句柄,用于从本地或远程客户机应用接受一个连接请求。按下述步 骤行事,便可写出一个最基本的服务器应用: 1)使用API函数CreateNamedPipe,创建一个命名管道实例句柄。 2)使用API函数ConnectNamedPipe,在命名管道实例上监听客户机连接请 求。 3)使用API函数ReadFile,从客户机接收数据;使用API函数WriteFile,将数据发给客户机。 4)使用API函数DisconnectNamedPipe,关闭命名管道连接。 5)使用API函数CloseHandle,关闭命名管道实例句柄。 首先,我们的服务器进程需要使用CreateNamedPipe这个API调用,创建一个命名管道实例。 下面给出CreateNamedPipe()的函数原型: HANDLE CreateNamedPipe(LPCTSTR lpName, //指向管道名称的指针 DWORD dwOpenMode, //管道打开模式 DWORD dwPipeMode, //管道模式 DWORD nMaxInstances, //最大实例数 DWORD nOutBufferSize, //输出缓存大小 DWORD nInBufferSize, //输入缓存大小 DWORD nDefaultTimeOut,//超时设置 LPSECURITY_ATTRIBUTES lpSecurityAttributes //安全属性指针 ); 其中几个主要参数如下: lpName是管道的名称,命名管道的命名采用如下 格式 pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载 : \\ServerName\Pipe\PipeName 其中,第一部分\\ServerName指定了服务器的名字,命名管道服务即在此 服务器创建,而且要由它对进入的连接请求进行“监听”,其字串部分可 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示为 一个小数点”.”(表示本机)、星号(当前网络字段)、域名或是一个真正的 服务;第二部分\Pipe是一个不可变化的硬编码字串,以指出该文件是从属于 NPFS,不区分大小写;第三部分\PipeName则是应用程序可以唯一定义及标识一 个命名管道的名字,而且可以设置多级目录。 dwOpenMode参数用于指示一个管道创建好之后,它的传输方向、I/O控制以及安全模式。PIPE_ACCESS_标志决定了在客户机与服务器之间,数据在管道上的 流动方向。可用PIPE _ACCESS_DUPLEX标志以双向传输方式打开一个管道。也就 是说,在客户机与服务器之间,数据可以双向传输。除此以外,亦可使用 PIPE_ACCESS_INBOUND或者PIPE_ACCESS_OUTBOUND标志,以单向传输方式打开 一个管道。也就是说,数据只能从客户机传向服务器,或从服务器传向客户机。 dwPipeMod命名管道提供了两种基本的通信模式:字节模式 (PIPE_TYPE_BYTE)和消息模式(PIPE_TYPE_MESSAGE)。 在字节模式中,信息以连续字节流的形式在客户与服务器之间流动,这也就意味着,对于客户机应用 和服务器应用,在任何一个特定的时间段内,都无法准确知道有 多少字节从管道中读出或写入。在这种通信模式中,一方在向管道写入某个数量的字节后,并 不能保证管道另一方能读出等量的字节。对于消息模式,客户机和服务 器则是通过一系列不连续的数据包进行数据的收发。从管道发出的每一条消息都必须作 为一条完整的消息读入。 其他的函数及其参数含义详见msdn,此处不一一讲解。 服务器调用该函数,如果在已定义超时值变为零以前,有一个实例管道可以 使用,则创建成功并返回管道句柄,以此侦听来自客户机的连接请求。 实现一个命名管道客户机时,要求开发一个应用程序,令其建立与某个命名 管道服务器的连接。注意客户机不可创建命名管道实例。然而,客户机可打开来 自服务器的、现成的实例。下述步骤讲解了如何编写一个基本的客户机应用: 1)用API函数WaitNamedPipe,等候一个命名管道实例可供自己使用。 2)用API函数CreateFile,建立与命名管道的连接。 3)用API函数WriteFile和ReadFile,分别向服务器发送数据,或从中接收 数据。 4)用API函数CloseHandle,关闭打开的命名管道会话。 建立一个连接之前,客户机需要用WaitNamedPipe函数,检查是否存在一个 现成的命名管道实例。WaitNamedPipe成功完成后,客户机需要用CreateFile这个API函数,打开指向服务器命名管道实例的一个句柄。 简单说来,服务器调用CreateNamedPipe来创建管道,如果在已定义超时值 变为零以前,有一个实例管道可以使用,则创建成功并返回管道句柄,以此侦听 来自客户机的连接请求。另一方面,客户机通过函数WaitNamedPipe()使服务器进程等待来自客户的实例连接。如果在超时值变为零以前,有一个管道可供连 接使用,则函数将成功返回,并通过调用CreateFile()或CallNamedPipe()来呼叫对服务器的连接。此时服务器将接受客户的连接请求,成功建立连接,服 务器调用的等待客户机建立连接的ConnectNamedPipe()函数也将成功返回。 然后,管道两端就可以进行通信了。 从调用时序上看,首先是客户机通过WaitNamedPipe()使服务器的CreateFile()在限时时间内创建实例成功,然后双方通过ConnectNamedPipe()和CreateFile()成功连接,在返回用以通信的文件句柄后,客户、服务 双方即可进行通信。 在建立了连接后,客户机与服务器即可通过ReadFile()和WriteFile()并利用得到的管道句柄,以文件读写的形式彼此间进行信息交换。当客户与服务 器的通信结束,或是由于某种原因一方需要断开时,由客户机调用CloseFile()函数关闭打开的管道句柄,服务器随即调用DisconnectNamedPipe()函数。当然,服务器也可以通过单方面调用DisconnectNamedPipe()来终止连接。在终止连接后调用函数CloseHandle()来关闭此管道。 下篇将给出的程序清单即是按照上述方法实现的命名管道服务器和客户机 进行通信的程序实现代码 我采用的是C#开发的一个windows应用程序(pipe_server_csharp)作为服务器端,而MFC开发的应用程序(NamedPipeClient_vc)作为客户端。客户端 和服务器端要进行频繁的大量的通信,常见的是文本信息和曲线数据,例如,一 共有10条曲线,每条曲线有1000000条double数据。 服务器端: 服务器端是用在VS2005中用C#开发的一个名为pipe_server_csharp的应用程序,只有一个名为frmServer的主界面。 由于管道的相关API函数都是属于 kernel32.dll函数,C#中不能直接调用,所 以必须将所要用到的API函数全部封装在一个类NamedPipeNative中。 至于如 何调用这些API函数,有兴趣的朋友可以上网搜索,或者看我的另一篇文章《C# 中怎么调用命名管道的WinAPI》。 NamedPipeNative类中几个主要函数如下(大家可以对比这些重写的API函 数和原来的函数有什么变化): [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 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 // handle to template file ); [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 ); 还有其他一些常量: public const uint PIPE_ACCESS_DUPLEX = 0x00000003; public const uint PIPE_ACCESS_OUTBOUND = 0x00000002; public const uint PIPE_TYPE_BYTE = 0x00000000; public const uint PIPE_TYPE_MESSAGE = 0x00000004; 在此不一一列举了。 封装之后,在C#中就可以直接调用这些函数和常量了。 另外,创建了一个类CMyPipe,封装了服务器管道的属性和方法,如创建管 道,读写数据等: namespace pipe_server_csharp { public class CMyPipe { private string m_PipeName;//管道名全称 public string PipeName { get { return m_PipeName; } set { m_PipeName = value; } } private IntPtr m_HPipe;//管道句柄 public IntPtr HPipe { get { return m_HPipe; } set { m_HPipe = value; } } public CMyPipe()//无参构造函数 { m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; m_PipeName = "\\\\.\\pipe\\robinTest"; } public CMyPipe(string pipeName)//有参构造函数 { m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; m_PipeName = pipeName; } ~CMyPipe()//析构函数 { Dispose(); } public void Dispose() { lock (this) { if (m_HPipe != (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE) { NamedPipeNative.CloseHandle(m_HPipe); m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; } } } public void CreatePipe()//创建管道 { m_HPipe = NamedPipeNative.CreateNamedPipe(m_PipeName, NamedPipeNative.PIPE_ACCESS_DUPLEX, // 数据双工通信 NamedPipeNative. PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_WAIT, 100, // 最大实例个数 128, // 流出数据缓冲大小 128, // 流入数据缓冲大小 150, // 超时,毫秒 IntPtr.Zero // 安全信息 ); if (m_HPipe.ToInt32() == NamedPipeNative.INVALID_HANDLE_VALUE) { frmServer.ActivityRef.AppendText("创建命名管道失败" ); frmServer.ActivityRef.AppendText(Environment.NewLine); return; } frmServer.ActivityRef.AppendText("创建命名管道完毕" ); frmServer.ActivityRef.AppendText(Environment.NewLine); } public void ReadCurveData()//读取曲线数据 { int nCurvesToRead = 0; nCurvesToRead = ReadInt(HPipe);//先读取需要读取的曲线条数,如 frmServer.CurveDataList.Clear(); for (int j = 1; j <= nCurvesToRead; j++) { string curveName = ReadString(HPipe);//读取该曲线名称 int nCount = 0; nCount = ReadInt(HPipe);//读取该曲线的数据总数(数组大小) double[] readData = new double[nCount]; for (int i = 0; i < nCount; i++) { readData[i] = ReadDouble(HPipe);//顺序读取曲线的数据 } CCurve newCurve = new CCurve(); newCurve.CurveName = curveName; newCurve.CurveData = readData; frmServer.CurveDataList.Add(newCurve); } } public void ReadTextInfo()//读取文本信息 { string textInfo = ReadString(HPipe);//读取该曲线名称 frmServer.ActivityRef.AppendText(textInfo + Environment.NewLine); frmServer.ActivityRef.AppendText(Environment.NewLine); } public void ReadData() { //read data int flag = -1; flag = ReadInt(HPipe);//获取当前要读取的数据的信息 if (flag == 0)//flag==0表示读取曲线数据 { ReadCurveData(); } else if (flag == 1)//flag==1表示读取文本信息 { ReadTextInfo(); } } //写字符串,由于字符串的大小不同,所以先将字符串的大小写入,然后写字符串内容,对应的, //在c++端,读字符串时先读取字符数组大小,从而给字符数组开辟相应的空间,然后读取字符串内容。 public bool WriteString(IntPtr HPipe, string str) { byte[] Val = System.Text.Encoding.UTF8.GetBytes(str); byte[] dwBytesWrite = new byte[4]; int len = Val.Length; byte[] lenBytes = System.BitConverter.GetBytes(len); if (NamedPipeNative.WriteFile(HPipe, lenBytes, 4, dwBytesWrite, 0)) return (NamedPipeNative.WriteFile(HPipe, Val, (uint)len, dwBytesWrite, 0)); else return false; } public string ReadString(IntPtr HPipe) { string Val = ""; byte[] bytes = ReadBytes(HPipe); if (bytes != null) { Val = System.Text.Encoding.UTF8.GetString(bytes); } return Val; } public byte[] ReadBytes(IntPtr HPipe) { //传字节流 byte[] szMsg = null; byte[] dwBytesRead = new byte[4]; byte[] lenBytes = new byte[4]; int len; if (NamedPipeNative.ReadFile(HPipe, lenBytes, 4, dwBytesRead, 0))//先读大小 { len = System.BitConverter.ToInt32(lenBytes, 0); szMsg = new byte[len]; if (!NamedPipeNative.ReadFile(HPipe, szMsg, (uint)len, dwBytesRead, 0)) { //frmServer.ActivityRef.AppendText("读取数据失败"); return null; } } return szMsg; } public float ReadFloat(IntPtr HPipe) { float Val = 0; byte[] bytes = new byte[4]; //单精度需4个字节存储 byte[] dwBytesRead = new byte[4]; if (!NamedPipeNative.ReadFile(HPipe, bytes, 4, dwBytesRead, 0)) { //frmServer.ActivityRef.AppendText("读取数据失败"); return 0; } Val = System.BitConverter.ToSingle(bytes, 0); return Val; } public double ReadDouble(IntPtr HPipe) { double Val = 0; byte[] bytes = new byte[8]; //双精度需8个字节存储 byte[] dwBytesRead = new byte[4]; if (!NamedPipeNative.ReadFile(HPipe, bytes, 8, dwBytesRead, 0)) { //frmServer.ActivityRef.AppendText("读取数据失败"); return 0; } Val = System.BitConverter.ToDouble(bytes, 0); return Val; } public int ReadInt(IntPtr HPipe) { int Val = 0; byte[] bytes = new byte[4]; //整型需4个字节存储 byte[] dwBytesRead = new byte[4]; if (!NamedPipeNative.ReadFile(HPipe, bytes, 4, dwBytesRead, 0)) { //frmServer.ActivityRef.AppendText("读取数据失败"); return 0; } Val = System.BitConverter.ToInt32(bytes, 0); return Val; } } } 主程序,读取和显示通信信息: public partial class frmServer : Form { public static System.Windows.Forms.TextBox ActivityRef;//显示信息 public static ArrayList CurveDataList = new ArrayList();//存储数据 public static string PipeName = "robinTest"; public static string ServeName = "."; public static string FullPipeName = "\\\\"+ServeName+"\\pipe\\"+PipeName;//管道全名 public static CMyPipe ThePipe;//管道实例 private Thread hThread;//线程 public int ReadInt(IntPtr HPipe) { int Val = 0; byte[] bytes = new byte[4]; //整型需4个字节存储 byte[] dwBytesRead = new byte[4]; if (!NamedPipeNative.ReadFile(HPipe, bytes, 4, dwBytesRead, 0)) { //frmServer.ActivityRef.AppendText("读取数据失败"); return 0; } Val = System.BitConverter.ToInt32(bytes, 0); return Val; } } } 主程序,读取和显示通信信息: public partial class frmServer : Form { public static System.Windows.Forms.TextBox ActivityRef;//显示信息 public static ArrayList CurveDataList = new ArrayList();//存储数据 public static string PipeName = "robinTest"; public static string ServeName = "."; public static string FullPipeName = "\\\\"+ServeName+"\\pipe\\"+PipeName;//管道全名 public static CMyPipe ThePipe; //管道实例 private Thread hThread; //线程 客户机端: 客户端是在VS6.0中用MFC开发的一个单界面应用程序,名为 CString PipeName = "robinTest"; NamedPipeClient_vc。在vc6.0中可以直接调用API函数,不需要封装。 CString ServerName = "."; 当然,按照惯例,还是将客户端的命名管道相关的属性和方法封装成类 CString FullPipeName="\\\\"+ServerName+"\\pipe\\"+PipeName; CMyPipe,如下: CMyPipe::CMyPipe() { m_pThread=NULL; } CMyPipe::~CMyPipe() { if(m_pThread) { if(TerminateThread(m_pThread->m_hThread,0)) { if(m_pThread) delete m_pThread; m_pThread = NULL; } } } //客户端和服务器端建立连接 void CMyPipe::ClientCreateFile() { BOOL ret = ::WaitNamedPipe(FullPipeName, 5000); if (!ret) { //ClientMsg="管道忙或者没有启动……\n"; return; } m_hPipe = ::CreateFile(FullPipeName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hPipe == INVALID_HANDLE_VALUE) { char szErr[256] = ""; DWORD dwErr = GetLastError(); sprintf(szErr, "%l", dwErr); //ClientMsg=szErr; return; } //ClientMsg="打开管道了\n"; } //写字符串 void CMyPipe::WriteString(char *szMsg) { DWORD dwSize = strlen(szMsg)+1, dwBytesWritten = 0; BOOL ret =WriteFile(m_hPipe, &dwSize, 4, &dwBytesWritten, NULL); if (ret) { BOOL ret2=WriteFile(m_hPipe, szMsg, dwSize, &dwBytesWritten, NULL); } } //写单精度 void CMyPipe::WriteFloat(float szMsg) { DWORD dwSize = 4, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL); } //写双精度 void CMyPipe::WriteDouble(double szMsg) { DWORD dwSize = 8, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL); } //写整型 void CMyPipe::WriteInt(int szMsg) { DWORD dwSize = 4, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL); } void CMyPipe::ClosePipe() { CloseHandle(m_hPipe); } //读字符串 char * CMyPipe::ReadString() { char *readStr; DWORD drSize=0, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &drSize, 4, &dwBytesRead, NULL); if (ret) { readStr=new char[drSize]; BOOL ret2=ReadFile(m_hPipe, readStr, drSize, &dwBytesRead, NULL); } return readStr; } int CMyPipe::ReadInt() { int intRead=0; DWORD drSize=4, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &intRead, drSize, &dwBytesRead, NULL); return intRead; } float CMyPipe::ReadFloat() { float floatRead=0; DWORD drSize=4, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &floatRead, drSize, &dwBytesRead, NULL); return floatRead; } double CMyPipe::ReadDouble() { double floatRead=0; DWORD drSize=8, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &floatRead, drSize, &dwBytesRead, NULL); return floatRead; } 而主程序NamedPipeClient_vcDlg.cpp如下: CMyPipe thePipe; //连接服务器管道 void CNamedPipeClient_vcDlg::OnOpen() { // TODO: Add your control notification handler code here thePipe.ClientCreateFile(); } //发送数据 void CNamedPipeClient_vcDlg::OnWrite() { // TODO: Add your control notification handler code here WriteData(); } //关闭管道 void CNamedPipeClient_vcDlg::OnClose() { // TODO: Add your control notification handler code here thePipe.ClosePipe(); } //写曲线数据(注意写入的顺序,读的时候也要按照这个顺序) void CNamedPipeClient_vcDlg::WriteCurveData() { int nCurvesToWrite=10; thePipe.WriteInt(nCurvesToWrite);//先写入要传递的曲线总条数 for (int j = 1; j <= nCurvesToWrite; j++) { char *curveName= "curve";// thePipe.WriteString(curveName);//写该曲线名称 int nCount = 10000;//该曲线的数据总数(数组大小) thePipe.WriteInt(nCount); double *writeData=new double[nCount]; for (int i = 0; i < nCount; i++) { writeData[i]=i;//给每个曲线数据赋初值 thePipe.WriteDouble(writeData[i]);//顺序写曲线的数据 } } } //写文本信息 void CNamedPipeClient_vcDlg::WriteTextInfo(char *textInfo) { thePipe.WriteString(textInfo); } void CNamedPipeClient_vcDlg::WriteData() { int flag=1;//传递的信息的标识,0表示曲线数据,1表示文本信息 if (flag==0) { thePipe.WriteInt(flag); WriteCurveData(); } else if (flag==1) { thePipe.WriteInt(flag); char * charWrite="hedafasfddsafdsafdsafdsafdsafsafdsafdsafdsafsaaaa"; WriteTextInfo(charWrite); } } 最新C++与C#进程通信案例源码,欢迎在线学习c++ 教程.
本文档为【C++与C#进程通信案例[附源码]】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_447713
暂无简介~
格式:doc
大小:56KB
软件:Word
页数:25
分类:生活休闲
上传时间:2018-01-15
浏览量:46