uruchamianie procesu cmd.exe natychmiast go konczy

0

Witam. Uruchamiam cmd.exe z parametrami itp itd (za pomocą createprocess i pipes). Po wykonaniu cmd.exe natychmiastowo się kończy. Da się zrobić tak, aby cmd.exe się nie kończyło, tylko oczekiwało na dalsze komendy?

0

system("START CMD.EXE");

0

wcale cmd.exe się nie kończy nie oszukuj! to twój wątek się kończy jak go nie zatrzymałeś i zamyka potomnego cmd

0

Tzn nie wiem czy do końca rozumiem. Generalnie to ja nie mam wątków, ale procesy (CreateProcess, a nie CreateThread). No i ja ich nie kończę, tzn czekam aż one same się skończą.

bool shell::runProgram(string program,string params,bool cmd,bool wait) {
	STARTUPINFO siStartInfo;
	BOOL bSuccess = FALSE; 

	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );


	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 
	siStartInfo.hStdError = outwrite;
	siStartInfo.hStdOutput = outwrite;
	siStartInfo.hStdInput = inread;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

	if (cmd) {
		program=" /C "+program+params;
		cout<<"program: "<<program<<endl<<endl;
		

		bSuccess = CreateProcess(
		  (LPSTR)"C:\\Windows\\System32\\cmd.exe", 
		  (LPSTR)program.c_str() ,     // command line 
		  NULL,          // process security attributes 
		  NULL,          // primary thread security attributes 
		  TRUE,          // handles are inherited 
		  0,             // creation flags 
		  NULL,          // use parent's environment 
		  NULL,          // use parent's current directory 
		  &siStartInfo,  // STARTUPINFO pointer 
		  &piProcInfo);  // receives PROCESS_INFORMATION 
	}
	else
		bSuccess = CreateProcess(
		  program.c_str(),
		  (LPSTR)params.c_str(),

		  NULL,          // process security attributes 
		  NULL,          // primary thread security attributes 
		  TRUE,          // handles are inherited 
		  0,             // creation flags 
		  NULL,          // use parent's environment 
		  NULL,          // use parent's current directory 
		  &siStartInfo,  // STARTUPINFO pointer 
		  &piProcInfo);  // receives PROCESS_INFORMATION 

	good=(bool)bSuccess;

	if (good) {
		if (wait)
			WaitForSingleObject(piProcInfo.hProcess,INFINITE);
	}

	return good;
}

potem sczytuję znaki z piperead.
Wywołuję to w głównym wątku, tzn w moim programie. On się też oczywiście nie kończy :)

Jeśli mógłbyś bardziej wytłumaczyć, byłbym zobowiązany ;-)

0

każdy proces musi mieć wątek główny, nawet jak nie wywołujesz CreateThread, to CreateProcess tworzy wątek główny tamtego programu

zobacz co się dzieje w debuggerze

0

ok. na innym forum znalazłem podpowiedź, że trzeba uruchomić cmd.exe z przełącznikiem /K. To się zgadza niby z tym co pisze o cmd.exe w internecie. Niestety nadal program się kończy :/

0

Kod nie uruchamia interpretera poleceń.

0

Trochę przerobiłem tę funkcję.

bool shell::runCmd(string params,bool wait) {
	STARTUPINFO siStartInfo;
	BOOL bSuccess = FALSE; 

	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 
	siStartInfo.hStdError = outwrite;
	siStartInfo.hStdOutput = outwrite;
	siStartInfo.hStdInput = inread;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES| STARTF_USESHOWWINDOW;
	siStartInfo.wShowWindow = SW_HIDE;

	siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
	siStartInfo.wShowWindow = SW_HIDE;

		bSuccess = CreateProcess(
		  NULL, 
		  (LPSTR)params.c_str() ,     // command line 
		  NULL,          // process security attributes 
		  NULL,          // primary thread security attributes 
		  TRUE,          // handles are inherited 
		  0,             // creation flags 
		  NULL,          // use parent's environment 
		  NULL,          // use parent's current directory 
		  &siStartInfo,  // STARTUPINFO pointer 
		  &piProcInfo);  // receives PROCESS_INFORMATION */

	good=(bool)bSuccess;

	if (good) {
		if (wait)
			WaitForSingleObject(piProcInfo.hProcess,INFINITE);
	}

	return good;
}

void shell::createPipes() {
	SECURITY_ATTRIBUTES saAttr;  
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	CreatePipe( &outread, &outwrite, &saAttr, 0) ;
	SetHandleInformation(outread, HANDLE_FLAG_INHERIT, 0);
	CreatePipe(&inread, &inwrite, &saAttr, 0);
	SetHandleInformation(inread, HANDLE_FLAG_INHERIT, 0);
	CreatePipe(&erread, &erwrite, &saAttr, 0);
	SetHandleInformation(erread, HANDLE_FLAG_INHERIT, 0);
}

Jeśli tworzę proces wraz z rurami, cmd.exe kończy się po wykonaniu komendy. Jeśli bez rurek (w startupinfo nie będzie ustawionych flag), program się nie kończy. Zatem sądzę, że coś muszę źle robić z rurkami. Tylko co?

0

A że tak spytam, po co uruchamiasz cmd.exe ?

BTW, wątek nie pasuje do Newbie

Co do zamykania - nie zamknąłeś przypadkiem rurki tak jak w przykładzie na MSDN ?

//EDIT
Przerobiłem nieco ten przykładzik (http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx) w ten sposób, że przekierowałem IO uruchomionego dziecka (cmd.exe) na własne IO i śmiga aż miło.

http://pastebin.4programmers.net/60

//EDIT jeszcze raz
No i wszystko jasne:

cmd /? napisał(a)

Uruchamia nowe wystąpienie interpretera poleceń systemu Windows

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] ciąg]

/C Wykonuje polecenie określone przez ciąg i kończy działanie.

Polecenie które odpalasz to inny program tak ? To po co odpalasz ten program przez cmd ? Odpal program bezpośrednio przez CreateProcess.

0

Wywołuje przez cmd, bo chce, aby można było dodatkowe polecenia wpisywać dodatkowe komendy. Ludzie, jak czytacie jakiś temat, to czytajcie od początku, chyba że to jakiś rozrywkowy temat typu humor, czy śmieszne filmiki na YT.

0
Darkhog napisał(a)

Wywołuje przez cmd, bo chce, aby można było dodatkowe polecenia wpisywać dodatkowe komendy. [...]

spójrz na 2 pierwsze parametry CreateProcess(), dowiedz się czym się różnią, a okaże się, że można do CreateProcess przekazywać parametry

0

CreateProcess to funkcja, nie wzorzec, więc parametrów ni ma. O argumenty ci chodziło?

0
manfredek napisał(a)

CreateProcess to funkcja, nie wzorzec, więc parametrów ni ma. O argumenty ci chodziło?

pytasz się tak jakbyś nie wiedział :P

0

Dzięki adf88, działa.

I fakt, że nie chodziło mi o odpalanie innych aplikacji bo to już przerabiałem. Moim celem było wywołanie konsoli i możliwość interakcji z nią. Po co?

  1. Aby dowiedzieć się czegoś o rurkach. Jeszcze nigdy niczego z nimi nie napisałem. Ja lubię się uczyć programowania przez praktykę.
  2. Kolega pokazał mi program powercmd (o ile mi wiadomo płatny) i zacząłem się zastanawiać czy nie dam rady stworzyć czegoś podobnego. Jak widać nie obyło się bez pomocy.
  3. Czasami potrzebuję wykonać polecenie w cmd.exe a niestety na wynik operacji ma wpływ kodowanie. Z tego co rozumiem, ale mogę się mylić, to normalne okienkowe aplikacje mają windowsowy 1250, a cmd.exe latin2. Tak mogę sobie na początku wpisać chcp 1250 i w mojej aplikacji okienkowej wyniki z konsoli są w odpowiednim okienkowym kodowaniu, bez krzaczków.
    Pewnie można to zrobić w inny prostszy sposób, ale szczerze mówiąc teraz to mnie już mało obchodzi ;-)
  4. Irytuje mnie czasem, gdy nie mogę zaznaczyć ładnie tekstu na konsoli jak zwyczajnego tekstu, tylko jako "prostokąt".

Jeśli temat nie pasuje do newbie, a na początku temat wcale skomplikowany się nie wydawał, to można go przecież przenieść do c/c++ :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1