interaktion zwischen 2 programmen

Hast Du vielleicht vergessen, auf der Client - Seite nach dem öffnen der Pipe mit CreateFile(...) auf die Pipe zu warten (mit WaitNamedPipe(...)), bis sie vom Server erzeugt wurde?
 
hm...ich bin grad noch am rumprobieren, an dem Warten liegts glaub ich net, hab dazu aber noch ne frage: wieso gibt folgender Code, gleich am Anfang die Fehlermeldung aus, ohne die angegebenen 5000 Millisekunden zu warten?

Code:
while(1)
   {
   HPipe = CreateFile("\\\\.\\pipe\\pipe1", GENERIC_READ |
					  GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
   if(HPipe != INVALID_HANDLE_VALUE)
	 {
	 Edit1->Text = "Pipe successfully opened";
	 break;
	 }
   if(!WaitNamedPipe("\\\\.\\pipe\\pipe1", 5000))
	 {
	 Edit1->Text = "Could not open pipe";
	 break;
	 }
 
Wenn ich das richtig sehe, dann brichst Du die Schleife ab, wenn CreateFile ein gültiges Handle zurückgibt. Wenn das Handle ungültig ist, dann gehst Du weiter zum Warten. Das schlägt fehl, weil schon das CreateFile fehlgeschlagen ist.
Was ist denn die Fehlernummer bein Fehlschlagen von CreateFile?
 
der error-code ist 2 (ERROR_FILE_NOT_FOUND)
aber selbst wenn ich nur folgenden Code hab, wartet er nicht 5 Sekunden, sondern gibt sofort die Fehlermeldung aus:

Code:
while(1)
{
if(!WaitNamedPipe("\\\\.\\pipe\\pipe1", 5000))
	 {
	 Edit1->Text = "Could not open pipe";
	 break;
	 }
}
 
Ich glaube, ich hab's.
Das WaitNamedPipe kommt sofort zurück, wenn die Pipe auf der Serverseite noch nicht Erzeugt ist (CreateNamedPipe). Wenn die Pipe erzeugt, aber noch nicht verbunden ist (ConnectNamedPipe), dann wartet die Wartefunktion auf der Client-Seite, bis der Server ConnectNamedPipe aufruft oder Timeout auftritt. Erst, wenn verbunden ist, kann der Client CreateFile aufrufen. Also so könnte es funktionieren:
1. Server CreateNamedPipe
2. Client WaitNamedPipe
3. Server ConnectNamedPipe
4. Client CreateFile

Ich werde das mal bei Gelegenheit selber ausprobieren, habe aber momentan keine Zeit.
 
mein jetziger stand:
SERVER:

Code:
HANDLE HPipe;
HPipe = CreateNamedPipe("\\\\.\\pipe\\pipe1", PIPE_ACCESS_DUPLEX, 
										 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE |
										 PIPE_WAIT, 1, 500, 500, 30000, NULL);
String datei = "Test.exe";
// system(datei.c_str());
bool fConnected;
fConnected = ConnectNamedPipe(HPipe, NULL) ?
	 true : (GetLastError() == ERROR_PIPE_CONNECTED);
if(fConnected)
  {
  unsigned long BytesRead;
  char chRequest[100];
  bool fSuccess;
  while(1)
  {
  fSuccess = ReadFile(HPipe,chRequest,100+1,&BytesRead,NULL);
  if(!fSuccess || BytesRead == 0)
	break;
  }
  Label1->Caption = chRequest;
  }
else Label1->Caption = GetLastError();


CLIENT:

Code:
HANDLE HPipe;
while(1)
{
HPipe = CreateFile("\\\\.\\pipe\\pipe1", GENERIC_READ | GENERIC_WRITE, 0, 
							  NULL, OPEN_EXISTING, 0, NULL);
if(HPipe != INVALID_HANDLE_VALUE)
  {
  Label1->Caption = "Pipe successfully opened";
  break;
  }
if(!WaitNamedPipe("\\\\.\\pipe\\pipe1", 5000))
  {
  Label1->Caption = GetLastError();
  break;
  }
}
bool fSuccess;
unsigned long dwMode = PIPE_READMODE_MESSAGE;
fSuccess = SetNamedPipeHandleState(HPipe, &dwMode, NULL, NULL);
if(!fSuccess)
  Label2->Caption = "SetNamedPipeHandleState failed";
unsigned long WrittenBytes;
fSuccess = WriteFile(HPipe,"Dies ist ein Test",17+1,&WrittenBytes,NULL);
if(!fSuccess)
  Label3->Caption = "WriteFile failed";
CloseHandle(HPipe);



Dieser Code funktioniert einwandfrei, solange ich den Client manuell starte. Wenn er allerdings mithilfe der blauen auskommentierten Zeile vom Server automatisch gestartet wird, dann meldet der Server den Error-Code 232 (ERROR_NO_DATA - The pipe is being closed)
Ich hoffe es kann mir jemand helfen?
 
Zuletzt bearbeitet:
Ich hab meinen Denkfehler gefunden. Das erste Programm stoppt, sobald es das zweite aufgerufen hat. Es läuft erst weiter, wenn das zweite Programm wieder geschlossen ist.
Wie kann man am leichtesten beide Programme gleichzeitig laufen lassen? Über einen Thread?
 
Mit CreateProcess. Da kannst Du es dann aber auch so machen, daß Du im Server unbenannte Pipes erzeugst und deren Handles in der StartupInfo übergibst. Dafür habe ich auch einen Beispielcode, der ein Programm startet und dessen Ausgaben übernimmt, um sie selber auszugeben:
Code:
BOOL ProcessCommandLine(char * pcCommandLine)
    {
    	STARTUPINFO si;
    	PROCESS_INFORMATION pi;
    	SECURITY_ATTRIBUTES sa;
    	HANDLE hReadPipe, hWritePipe;
    	DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwSizeLow, dwSizeHigh, dwError;
    	char cReadLine[MAX_LINE_LENGTH];
    	BOOL bDoRead = TRUE, bOK = TRUE;
    	MSG AppMsg;
    	LPVOID lpEnvironment = NULL;
    
    	ZeroMemory(&si, sizeof(si));
    	si.cb = sizeof(si);
    
    	//Pipes erzeugen
    	sa.nLength=sizeof(sa);
    	sa.bInheritHandle=TRUE;
    	sa.lpSecurityDescriptor=NULL;
    	bOK = CreatePipe(&hReadPipe, &hWritePipe, &sa, 1048576);
    	if(!bOK)
    	{
    		//FEHLER
    		dwError = GetLastError();
    		bOK = FALSE;
 		goto PROCESS_END_NOPIPE; //ja, ich weiß: niemals goto verwenden. Wollte aber nicht so viele if's schachteln
    	}
    
    	//Pipes eintragen
    	si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    	si.hStdOutput = hWritePipe;
    	si.hStdError = hWritePipe;
    	si.wShowWindow = SW_SHOWMINNOACTIVE;
    
    	//Prozess starten
    	bOK = CreateProcess(NULL,
    			pcCommandLine,
    			NULL,
    			NULL,
    			TRUE,
    			NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
    			lpEnvironment,
    			NULL,
    			&si,
    			&pi);
    	if(!bOK)
    	{
    		//FEHLER
    		dwError = GetLastError();
 		goto PROCESS_END_NOPROC; //ja, ich weiß: niemals goto verwenden. Wollte aber nicht so viele if's schachteln
    	}
    
    	//Auf Ende warten und Messages lesen
    	while(dwWaitResult != WAIT_OBJECT_0)
    	{
    		dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
    		while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
    		{
    			ZeroMemory(cReadLine, MAX_LINE_LENGTH);
 			if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
    			{
    				if(dwBytesRead)
    				{
 		 		//hier können die Daten in cReadLine ausgewertet werden
    				}
    			}
    			else
    			{
    				dwBytesRead = GetLastError();
    			}
    		}
    		//Applikations-Messagequeue verarbeiten
    		if(PeekMessage(&AppMsg, 0, 0, 0, PM_NOREMOVE))
    		{
    			GetMessage(&AppMsg, 0, 0, 0);
    			TranslateMessage(&AppMsg);
    			DispatchMessage(&AppMsg);
    		}
    	}
    
    	bOK = GetExitCodeProcess(pi.hProcess, &dwExitCode);
    	if(bOK)
    	{
    		if(dwExitCode != 0)
    		{
    			bOK = FALSE;
    		}
    	}
    	else
    	{
    		//FEHLER
    		dwError = GetLastError();
    		bOK = FALSE;
    	}
    
    
    	//Close handles
    	CloseHandle(pi.hProcess);
    	CloseHandle(pi.hThread);
    
    PROCESS_END_NOPROC:
    	CloseHandle(hWritePipe);
    	CloseHandle(hReadPipe);
    
    	if(lpEnvironment != NULL)
    		delete[] lpEnvironment;
    
    PROCESS_END_NOPIPE:
    
    	return bOK;
 }
So funktioniert das aber eben nur, wenn Du das Client - Programm vom Server aus startest. Wenn Du es per Hand starten willst, mußt Du NamedPipes nehmen.
Die goto's kannst Du vermeiden, wenn Du try-catch-Blöcke verwendest und im Fehlerfall eine Exception auswirfst.
EDIT:
Wenn Du bidirektionalen Datenverkehr willst, mußt Du 2 Pipes erzeugen, das Leseende der 2. Pipe an si.hStdInput übergeben und in ihr Schreibende Deine Daten schreiben.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück