{$APPTYPE CONSOLE}
uses Windows;
var hPipe:THandle;
si:STARTUPINFO;
pi:PROCESS_INFORMATION;
begin
hPipe:=CreateNamedPipe('\\.\pipe\SomeName',PIPE_ACCESS_DUPLEX,PIPE_WAIT,1,$100,$100,0,nil);
FillChar(si,SizeOf(si),0); si.cb:=SizeOf(si);
CreateProcess(nil,'Client.exe 1',nil,nil,false,0,nil,nil,si,pi);
CloseHandle(pi.hThread);
Sleep(2000); //This Sleep does nothing bad
ConnectNamedPipe(hPipe,nil);
WaitForSingleObjectEx(pi.hProcess,INFINITE,false);
DisconnectNamedPipe(hPipe);
CloseHandle(pi.hProcess);
CreateProcess(nil,'Client.exe 2',nil,nil,false,0,nil,nil,si,pi);
CloseHandle(pi.hThread);
Sleep(2000); //But not this one
ConnectNamedPipe(hPipe,nil);
WaitForSingleObjectEx(pi.hProcess,INFINITE,false);
DisconnectNamedPipe(hPipe);
CloseHandle(pi.hProcess);
CloseHandle(hPipe);
end.
Именованный пайп и CreateFile
Сервер:
Код:
Клиент:
Код:
{$APPTYPE CONSOLE}
uses Windows;
var hPipe:THandle;
Buf:array [0..99] of Char;
begin
hPipe:=CreateFile('\\.\pipe\SomeName',GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,nil,GetLastError(),0,@Buf,100,nil);
MessageBox(0,@Buf,nil,MB_ICONEXCLAMATION);
if hPipe=INVALID_HANDLE_VALUE then Write(':-(( ',ParamStr(1));
CloseHandle(hPipe);
end.
uses Windows;
var hPipe:THandle;
Buf:array [0..99] of Char;
begin
hPipe:=CreateFile('\\.\pipe\SomeName',GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,nil,GetLastError(),0,@Buf,100,nil);
MessageBox(0,@Buf,nil,MB_ICONEXCLAMATION);
if hPipe=INVALID_HANDLE_VALUE then Write(':-(( ',ParamStr(1));
CloseHandle(hPipe);
end.
Из-за первого Sleep'а ничего плохого, можно ставить любой период (CreateFile ждёт), но если период второго Sleep'а достаточен, чтобы клиентский CreateFile был вызван раньше серверного ConnectNamedPipe, то ничего хорошего: hPipe=INVALID_HANDLE_VALUE, FormatMessage от GetLastError: "Все копии канала заняты".
Cервер может принять клиента при наличии свободных экземпляров пайпа в любое время после первого вызова ConnectNamedPipe. Выходит, что при вызове второго ConnectNamedPipe'а, если есть Sleep, клиент уже подсоединился. Но GetLastError немного разъясняет ситуацию. Надо только проверить, если он даёт ERROR_PIPE_CONNECTED, то не нужно ждать соединения – оно уже есть к моменту вызова ConnectNamedPipe'а.