Create process without having keyboard and mouse, interaction and focus - c++

How to create/spawn Win32 process without mouse and keyboard focus and interaction?
Can some one mentioned most appropriate Win API function to create window process without having it display as top most window ,but stay behind in other opened windows?
(Assume you have to spawn/create a process of windowed(not fullscreen) Direct3D program executable and that program terminate by parent program therfore no need of user interaction but automated therefore when it gets created it should display behind other already opened windows).

Starting a process with a inactive SW_* value is not enough but if you are the foreground window you can also call LockSetForegroundWindow to disable SetForegroundWindow:
void backgroundcalc_simple()
{
LockSetForegroundWindow(LSFW_LOCK);
ShellExecute(NULL, NULL, TEXT("Calc"), NULL, NULL, SW_SHOWNA);
// Cannot unlock here without a hacky call to Sleep
}
If your application does not need SetForegroundWindow then you don't have to unlock but it is probably a good idea to do so anyway:
BOOL CALLBACK ProcessHasVisibleWindowProc(HWND hWnd, LPARAM Param)
{
if (IsWindowVisible(hWnd) && (WS_CAPTION & GetWindowLongPtr(hWnd, GWL_STYLE)))
{
DWORD thispid, *wantedpid = (DWORD*) Param;
if (GetWindowThreadProcessId(hWnd, &thispid) && thispid == *wantedpid)
{
*wantedpid = 0;
return FALSE;
}
}
return TRUE;
}
BOOL ProcessHasVisibleWindow(DWORD Pid)
{
if (!Pid) return FALSE;
EnumWindows(ProcessHasVisibleWindowProc, (LPARAM) &Pid);
return Pid == 0;
}
BOOL WaitForVisibleProcessWindow(DWORD Pid, DWORD Timeout)
{
DWORD start = GetTickCount();
for (;;)
{
if (ProcessHasVisibleWindow(Pid)) return TRUE;
if (GetTickCount() - start >= Timeout && Timeout != INFINITE) break;
Sleep(50);
}
return FALSE;
}
void backgroundcalc()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_FORCEOFFFEEDBACK|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNA;
WCHAR cmd[MAX_PATH];
lstrcpy(cmd, TEXT("Calc"));
LockSetForegroundWindow(LSFW_LOCK);
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
WaitForInputIdle(pi.hProcess, 3333);
WaitForVisibleProcessWindow(pi.dwProcessId, 1000*10);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
LockSetForegroundWindow(LSFW_UNLOCK);
}

Related

How close message box after closing parent process opened using CreateProcess()

I want auto check bad or good for run my .exe files. For example for this binaries I have missing dll's, and when I use CreateProcess it's not return error and provide me system MessageBox("Dll is missing"). If I close it by hand, methods return exitCode STATUS_DLL_NOT_FOUND. I want that from some timeout all system message boxes will be closed with closing parent process and i can get my STATUS_DLL_NOT_FOUND. Me need full automatically work from my code.This code can closed opened sub dialogs, but can't close messageboxes.
int main()
{
HANDLE hJob;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
hJob = CreateJobObject(NULL, NULL);
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
TCHAR szCmdline[] = TEXT(" -R:mm");
si.cb = sizeof(si);
CreateProcess(
executableFiles[0].c_str(),
szCmdline,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB /*Important*/,
NULL,
NULL,
&si,
&pi);
AssignProcessToJobObject(hJob, pi.hProcess); // Does not work if without CREATE_BREAKAWAY_FROM_JOB
ResumeThread(pi.hThread);
if (WaitForSingleObject(pi.hProcess, 3000) == WAIT_TIMEOUT)
{
EnumWindows(&SendWMCloseMsg, pi.dwProcessId);
if (WaitForSingleObject(pi.hProcess, 2000) == WAIT_TIMEOUT)
{
TerminateProcess(pi.hProcess, 0);
DWORD dwExitCode = 0;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
const DWORD result = WaitForSingleObject(pi.hProcess, 2000);
if (result == WAIT_OBJECT_0)
{
if (dwExitCode == STATUS_DLL_NOT_FOUND)
{
std::cout << "Dll is missing" << std::endl;
}
}
else
{
std::cout << "bad case" << std::endl;
}
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(hJob);
return 0;
}
Call UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); before CreateProcess, and make sure that CREATE_DEFAULT_ERROR_MODE is not set in the dwCreationFlags parameter, so that the child process inherits the error mode of the parent. Per docs, this "does not display the critical-error-handler message box, instead, the system sends the error to the calling process".
Optionally SetErrorMode(oldErrorMode); after CreateProcess to restore the previous setting.

C++ - Launch Notepad from an MFC application and change its default title from "Untitled - Notepad" to something else

I am using the following piece of code on Windows to successfully open an instance of Notepad. How can I change its default title from "Untitled - Notepad" to something else?
SHELLEXECUTEINFO sei = { 0 };
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = my_hWnd; // this window's handle
sei.lpVerb = L"open";
sei.lpFile = L"notepad.exe";
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOW;
sei.hInstApp = NULL;
if (ShellExecuteEx(&sei))
{
// do some other stuff...
}
There is limited set of command line options in Notepad.exe to change the default filename. But you can specify the new filename like so, if it doesn't exist, a prompt will let you open it as a new document.
sei.lpFile = L"notepad.exe";
sei.lpParameters = L"\"Readme.txt\"";
Use CreateProcess() to create the Notepad process.
Use WaitForInputIdle() to wait until the window becomes available. (Note: this approach may not work reliably, follow this recommendation to implement the WinEvents approach).
Use EnumThreadWindows() on the main thread ID (obtained from PROCESS_INFORMATION) to get the Notepad window handle.
Finally, use SendMessage() with WM_SETTEXT on the window handle to change the window title to whatever you like.
BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
HWND hWndNp = hWnd;
SendMessageW(hWndNp, WM_SETTEXT, 0, (WPARAM)L"Hello");
return 0; // ...stop enum
}
int main() {
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessW(
NULL, _tcsdup(TEXT("notepad")),
NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi)
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return 0;
}
if (0 == WaitForInputIdle(pi.hProcess, 5000))
{
EnumThreadWindows(pi.dwThreadId,
EnumThreadWndProc, NULL);
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
This works for me
CString strFile("C:\\test.txt");
char sz[MAX_PATH];
wsprintf(sz, "Notepad.exe %s", strFile);
WinExec(sz, SW_SHOW);
Also you can set default file name or path.

::SendMessage(apphwnd, WM_GETTEXTLENGTH, 0, 0) return 0

I use ::CreateProcess to create a subprocess, and use ::EnumWindows(&EnumWindowsProc, processInfo.dwThreadId) to get the subprocess's window handle, assign this handle to a global variable apphwnd, then I use length = ::SendMessage(apphwnd, WM_GETTEXTLENGTH, 0, 0); but the length is sometimes is zero.
Why is my subprocess's window handle valid but the windowText sometimes has no value? When can I operate on the window handle correctly after CreateProcess is done?
Here is EnumWindowsProc code :
HWND apphwnd;
int CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param)
{
CString str;
DWORD pID;
DWORD TpID = GetWindowThreadProcessId(hwnd, &pID);//get process id
std::string hwndProcessName = GetProcessNameByHandle(hwnd);
if (TpID == (DWORD)param)
{
apphwnd = hwnd;//hwnd is the window handle
return false;
}
return true;
}
Here is my StartProcess function code:
PROCESS_INFORMATION StartProcess(LPCTSTR program, LPCTSTR args, int sleepTime = 500, STARTUPINFO *pstartupInfo = NULL, DWORD dwCreationFlags = 0, bool isWaitInput = false)
{
HANDLE hProcess = NULL;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
::ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
if(::CreateProcess(program, (LPTSTR)args,
NULL, // process security
NULL, // thread security
FALSE, // no inheritance
dwCreationFlags, // no startup flags
NULL, // no special environment
NULL, // default startup directory
&startupInfo,
&processInfo))
{
Sleep(500);
if (true)
{
WaitForInputIdle(processInfo.hProcess, INFINITE);
}
apphwnd = NULL;
hProcess = processInfo.hProcess;
while(true)
{
::EnumWindows(&EnumWindowsProc, processInfo.dwThreadId);//Iterate all windows
if (apphwnd)
{
break;
}
}
} /* success */
return processInfo;
}
Here is what Spy++ shows:

Waitforsingleobject works when trying to open Notepad++ but returns immediately with Firefox

I have the following code that opens an application using CreateProcess and waits for it for a few seconds and then closes it if its not been closed. The same code works OK on notepad++ for example, but not when I try to open Firefox.exe
BOOL CALLBACK SendWMCloseMsg(HWND hwnd, LPARAM lParam)
{
//never gets called when opening Firefox.exe
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == lParam)
SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 30000, NULL);
return TRUE;
}
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
WCHAR szFilename[] = L"C:\\Program Files\\Mozilla Firefox\\firefox.exe";
if (CreateProcess(NULL,
szFilename,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&si,
&pi))
{
CloseHandle(pi.hThread);
WaitForInputIdle(pi.hProcess, INFINITE);
auto a = WaitForSingleObject(pi.hProcess, 30000);
if (a == WAIT_TIMEOUT)
{
EnumWindows(&SendWMCloseMsg, pi.dwProcessId);
if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_TIMEOUT)
{
//never gets here.
TerminateProcess(pi.hProcess, 0);
}
}
//a vlaue is 0 and it never gets in the if statement.
CloseHandle(pi.hProcess);
}
return 0;
}
SendWMCloseMsg does not get called and when I remove the if statement and call EnumWindows(&SendWMCloseMsg, pi.dwProcessId);, it still does not find the correct processId.
What Am I doing wrong with this code and how to address this issue?
I'm using Windows 10, 64bit and VS2015
The answer is that the process you started with CreateProcess created a bunch of other processes - and then quit.
Your WaitForSingleObject completes successfully, and your program ends.

ReadConsoleInput read only first symbol after press Enter

Excuse me for my English, but I can't solve a problem. Now I am writing Remote Console. It uses QTcpSocket and functions for work with windows console. Almost work perfect, but when I try read from console I need first press Enter and only after this my first letter will read. If I want input second letter I need press Enter again. How can I read every letters that I write?
It's my constructor:
FreeConsole();
dwProcessId = 0 ;
dwErrorId = 0;
std::wstring path = L"cmd.exe";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
SECURITY_ATTRIBUTES security = {
sizeof(security), NULL, TRUE
};
if(CreateProcess(NULL, (LPWSTR)path.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
dwProcessId = pi.dwProcessId;
}
else
{
dwErrorId = GetLastError();
printf("CreateProcess failed (%d).\n", dwErrorId);
return;
}
Sleep(1000);
if(!AttachConsole(pi.dwProcessId))
{
dwErrorId = GetLastError();
printf( "AttachConsole failed (%d).\n", dwErrorId);
return;
}
and here function where i have a problem:
int Console::readInputFromConsole(DataIn& data)
{
data.inputRecords.resize(40);
HANDLE inputHandle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events = 0;
DWORD unread = 0;
DWORD fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
//fdwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
BOOL bMode = SetConsoleMode(inputHandle, fdwMode);
if(!bMode)
{
std::runtime_error("error with mode");
}
Sleep(20);
BOOL statusUnread = TRUE;
statusUnread = GetNumberOfConsoleInputEvents(inputHandle, &unread);
if(!statusUnread)
throw std::runtime_error("GetNumberOfConsoleInputEvents failed.");
data.inputRecords.resize(unread);
BOOL statusRead = TRUE;
statusRead = ReadConsoleInput(inputHandle, &data.inputRecords[0], unread, &events);
if(!statusRead)
throw std::runtime_error("ReadConsoleInput failed.");
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &data.consoleScreenBufferInfo);
return 0;
}
I solved problem. I just created unnecessary process on a client computer. It's very stupid, but in this way I just tried to start process in new window.