Listenfeld problem

revenge86

Erfahrenes Mitglied
Hallo @ all,

wie kann ich in C++, über einen Button
einen DosBefehl (z.b ipconfig/all) auführen und die Ausgabe in ein Listenfeld schreiben?

Bedanke mich schon mal im Vorraus.

gruß revenge 86
 
In der Aktionsroutine des Buttons machst Du folgendes:
1. Eine Pipe erzeugen, um die Ausgaben zu bekommen
2. Mit CreateProcess einen neuen Prozeß starten, welcher den Befehl ausführt. Da gibst Du auch die Pipe mit an, damit die Standardausgabe in die Pipe umgelenkt wird.
3. In einer Schleife warten, bis der Prozess beendet ist und unterdessen die Daten aus der Pipe lesen und in das Listcontrol schreiben.
du solltest Dich also mal mit der CreateProcess-Methode auseinandersetzen und damit, was sie alles kann.
 
Code:
BOOL StartProcessExample()
 {
 	STARTUPINFO si;
 	PROCESS_INFORMATION pi;
 	SECURITY_ATTRIBUTES sa;
 	HANDLE hReadPipe, hWritePipe;
 	char * pcCommandLine = "ipconfig /all";
 	DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwError;
 	char cReadLine[MAX_LINE_LENGTH];
 	BOOL bDoRead = TRUE, bOK = TRUE;
 	MSG AppMsg;
 
 	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,
 						NULL,
 						NULL,
 						&si,
 						?);
 	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)
 	{
 		//Prozess beendet?
 		dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
 		//Ausgaben aus der Pipe lesen
 		while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
 		{
 			ZeroMemory(cReadLine, MAX_LINE_LENGTH);
 		if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
 			{
 				if(dwBytesRead)
 				{
     		        pBottomView->LogProcessMessage(CString(cReadLine), pCommand);
 				}
 			}
 			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)
 		{
 			//Prozeßrückgabe != 0
 			//...
 		}
 	}
 	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:
 
 	GetParentFrame()->UpdateWindow();
 
 	return bOK;
 }
 
mmh ich versteh nur bahnhof. Aber ich habe bis jetzt nur schlichte Konsolenprogramme geproggt. Und das ist jetz mein erstes MFC Programm ;-]

Ich will über einen Button IP Info, den Dos Befehl ipconfig/all ausführen und diesen dann in ein Listenfeld namens IDC_Ausgabe ausgeben lassen.
 
Verstehen mußt Du's schon selber. Ich weiß nicht, was ich da noch mehr erklären könnte.
Aber für Deinen Zweck solltest Du den Code 1:1 übernehmen können. Einfach in deine Button-Funktion reinkopieren.
Nur die Zeile
Code:
pBottomView->LogProcessMessage(CString(cReadLine), pCommand);
mußt Du austauschen und dort den Text aus cReadLine (die Ausgabe von 'ipconfig /all') ins Listenfeld schreiben.
Weißt Du denn, was eine Pipe ist?
 
Hmm eine Pipe verbindet doch zwei Prozesse?
Soweit richtig. Hier wird mittels einer Pipe die Standardausgabe des gestarteten Programms (normalerweise die Ausgabe auf der Konsole) umgeleitet. Beim Erzeugen einer Pipe werden immer 2 Handles erzeugt, eines für das Lese-Ende und eines für das Schreib-Ende der Pipe. Eine Pipe ist immer unidirektional. Das Schreib-Handle der Pipe wird als neue Standardausgabe an das gestartete Programm übergeben und schreibt seine Ausgaben dorthinein. Das Lese-Handle wird dann verwendet, um die Daten aus der Pipe wieder auszulesen. Mit GetFileSize(...) schaue ich in meinem Code vor dem Lesen, ob etwas in der Pipe ist und wenn ja, wieviel Bytes es sind.
 
Zurück