Interactive command shell using createprocess

Hello,
I want to have a command prompt session using my program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
string ExecCmd(
	const char* cmd              // [in] command to execute
	)
{
	string strResult;
	HANDLE hPipeRead, hPipeWrite;

	SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
	saAttr.bInheritHandle = TRUE; // Pipe handles are inherited by child process.
	saAttr.lpSecurityDescriptor = NULL;

	// Create a pipe to get results from child's stdout.
	if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
		return strResult;

	STARTUPINFO si = { sizeof(STARTUPINFO) };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.hStdOutput = hPipeWrite;
	si.hStdError = hPipeWrite;
	si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing.
	// Requires STARTF_USESHOWWINDOW in dwFlags.


	PROCESS_INFORMATION pi = { 0 };

	BOOL fSuccess = CreateProcess(NULL, LPSTR(cmd), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
	if (!fSuccess)
	{
		
		CloseHandle(hPipeWrite);
		CloseHandle(hPipeRead);
		MessageBox(NULL, GetLastErrorAsString().c_str(), GetLastErrorAsString().c_str(), MB_OK); //return dummy;
		return strResult;
	}
	bool bProcessEnded = false;
	for (; !bProcessEnded;)
	{
		// Give some timeslice (50 ms), so we won't waste 100% CPU.
		bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;

		// Even if process exited - we continue reading, if
		// there is some data available over pipe.
		for (;;)
		{
			char buf[1024];
			DWORD dwRead = 0;
			DWORD dwAvail = 0;

			if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
				break;

			if (!dwAvail) // No data available, return
				break;

			if (!::ReadFile(hPipeRead, buf, min(sizeof(buf)-1, dwAvail), &dwRead, NULL) || !dwRead)
				// Error, the child process might ended
				break;

			buf[dwRead] = 0;
			strResult += buf;
		}
	} //for
	CloseHandle(hPipeWrite);
	CloseHandle(hPipeRead);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	//MessageBox(NULL, strResult.c_str(), strResult.c_str(), MB_OK);
	return strResult;
} //ExecCmd
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
string as = ExecCmd("cmd /K cd\ &&  c: && dir");
MessageBox(NULL, as.c_str(), as.c_str(), MB_OK); 
}

As you can see I can execute single command or multiple commands using &&
all is working fine, but I need to have a proper session where I can enter one command after another in same environment instead of having to send all commands at once. Just like I would as if by opening cmd.exe itself and entering commands
How may I go about this using my program?

thanks
Last edited on
Registered users can post here. Sign in or register to post.