Automatically Resume a Suspended Windows Process - windows

I'm trying to write a windows batch file in order to resume a windows process that gets Suspended. I'm using pssuspend (from pstools) to resume the process. However, I'm trying to write windows batch file script that will continually get the status of a process (e.g. myExe.exe). If the script is not suspended, I would like for it to keep checking if it is suspended. If it is suspended, I would like it to run the pssuspend code. I'm unsure how to obtain the Suspend status. So far I have this:
if myExe.exe == "Suspend" (
pssuspend -r myExe.exe
suspend_fix.bat
) else (
suspend_fix.bat
)
Thanks for your help!

Windows services (that are created with the right attributes) can be suspended, but I am not sure how an executable can be suspended, or what exactly you mean by that.
If you mean that the program has been stopped, and when it does, you want to restart it, then here are a couple of code blocks that I have used to determine if a program is running:
1) by checking to see if the exe name exists, i.e., is running.
By the way, I recommend this one from my interpretation of your post:
BOOL ExeExists(char *exe)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (strstr(pe.szExeFile,exe))
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
2) by checking to see if the PID exists
BOOL PidExists(int pid)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (pe.th32ProcessID == pid)
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
By the way this is used to get the process ID (it is defined in winbase.h)
of the application making the call.
int GetProcessIdApp(void)
{
return GetProcessId(GetCurrentProcess());//defined in WinBase.h
}
Inside WinBase.h
WINBASEAPI
DWORD
WINAPI
GetProcessId(
__in HANDLE Process
);
In my scenario, An application broadcasts its PID at start up, such that
my monitoring program (the Windows service) can read it, then use it to make an ongoing determination of the application's status. If the app is discovered to be dead, and if other criteria indicate it should still be running, my service will start it back up.

Related

MFC: How to use MsgWaitForMultipleObjects() from the main thread to wait for multiple threads to complete that use SendMessage()?

I have a main thread that fires off several other threads to complete various items of work based on what the user choose from the main UI. Normally I'd use WaitForMultipleObjects() with bWaitAll set to TRUE. However, in this case those other threads will log output to another window that uses a mutex to ensure the threads only output one at a time. Part of that process uses SendMessage() to send get the text size and send the text to the windows which will hang if using WaitForMultipleObjects() since it's running from the main UI thread. So I moved over to use MsgWaitForMultipleObjects with QS_SENDMESSAGE flag, only it's problem is the logic for bWaitAll which states it will only return if all objects are signaled AND an input event occurred (instead of returning when all objects are signaled OR an input event occurred). Had the logic been OR this should have worked:
DWORD waitres=WAIT_FAILED;
while (1)
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
// mfc message pump
if (!theApp.PumpMessage()) {
// program end request
// TO DO
}
}
// MFC idel processing
LONG lidlecount = 0;
while (theApp.OnIdle(lidlecount++));
// our wait
waitres = ::MsgWaitForMultipleObjects(threadcount, threadhandles, TRUE, INFINITE, QS_SENDMESSAGE);
// check if ended due to message
if (waitres!=WAIT_OBJECT_0+threadcount) {
// no, exit loop
break;
}
}
Rather than fire off a thread that then fires off the other threads I wondered what is the correct way to handle this from the main thread? I thought about using bWaitAll FALSE then using WaitForMultipleObjects() with bWaitAll set to TRUE and the dwMilliseconds set to 0 (or 1) and checking the result to see if completed. If not, it would need to loop back to the top of the loop and then to MsgWaitForMultipleObjects() which when using bWaitAll FALSE could return right away if one of the many threads completed (say 1 thread of 10 completed, I could check as mentioned above if all completed, but when going back with bWaitAll FALSE it will just return and not wait).
So what is the proper way to handle waiting for multiple threads (that use SendMessage()) to complete in the main thread of an MFC application?
Thanks.
So what is the proper way to handle waiting for multiple threads to
complete
need create some structure, with reference count and pass pointer to this structure to every thread. here also probably exist sense have some common task data. and HWND of some window in main(GUI) thread. when worked thread exit - it release reference on object. when last thread exit - delete object and post some message to window, from main thread.
so we not need store thread handles (can just close it) and wait om multiple handles. instead we got some window message when all thread finish task
example of code
struct Task
{
HWND _hwnd;
LONG _dwRefCount = 1;
// some common task data probably ..
Task(HWND hwnd) : _hwnd(hwnd) {}
~Task() {
PostMessageW(_hwnd, WM_USER, 0, 0);// WM_USER as demo only
}
void AddRef(){
InterlockedIncrementNoFence(&_dwRefCount);
}
void Release(){
if (!InterlockedDecrement(&_dwRefCount)) delete this;
}
};
ULONG CALLBACK WorkThread(void* pTask)
{
WCHAR sz[16];
swprintf_s(sz, _countof(sz), L"%x", GetCurrentThreadId());
MessageBoxW(0, L"working...", sz, MB_ICONINFORMATION|MB_OK);
reinterpret_cast<Task*>(pTask)->Release();
return 0;
}
void StartTask(HWND hwnd, ULONG n)
{
if (Task* pTask = new Task(hwnd))
{
do
{
pTask->AddRef();
if (HANDLE hThread = CreateThread(0, 0, WorkThread, pTask, 0, 0))
{
CloseHandle(hThread);
}
else
{
pTask->Release();
}
} while (--n);
pTask->Release();
}
}

Getting process information of every process

I am trying to create a program that any normal user can run on windows and generate a process list of all processes, including the executable location. I have used CreateToolhelp32Snapshot() to get all process names, pid, ppid. But having issues getting the image path. Everything I do results in pretty much Access Denied.
I have tried ZwQueryInformationProcess, GetProcessImageFileName, etc. and also using OpenProcess to get the handle to each process. I can get the handle by using PROCESS_QUERY_LIMITED_INFORMATION, but any other option doesn't work. I am lost and have been at this for a few days. Can anyone point me in the right direction?
This is the code that works for non-admin user on Windows. Use the szExeFile member of PROCESSENTRY32 to get the path:
HANDLE hProcessSnap = NULL;
HANDLE hProcess = NULL;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass = 0;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return;
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // clean the snapshot object
return;
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// do something with the pe32 struct.
// pe32.szExeFile -> path of the file
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);

Detect "suspended" Windows 8/10 process

UWP (or "Metro") apps in Windows 8/10 can be suspended when they are not in the foreground. Apps in this state continue to exist but no longer consume CPU time. It looks like this change was introduced to improve performance on low-power/storage devices like tablets and phones.
What is the most elegant and simple method to detect a process in this state?
I can see 2 possible solutions at the moment:
Call NtQuerySystemInformation() and the enumerate each process and each thread. A process is "suspended" if all threads are in the suspended state. This approach will require a lot of code and critically NtQuerySystemInformation() is only semi-documented and could be removed in a future OS. NtQueryInformationProcess() may also offer a similar solution with the same problem.
Call GetProcessTimes() and record the counters for each process. Wait some longish time (minutes) and check again. If the process counters haven't changed then assume the process is suspended. I admit this is a hack but maybe could work if the time period is long enough.
Is there a more elegant way?
for this exist PROCESS_EXTENDED_BASIC_INFORMATION - meaning of flags in it described in this answer. you are need IsFrozen flag. so you need open process with PROCESS_QUERY_LIMITED_INFORMATION access (for do this for all processes, you will be need have SE_DEBUG_PRIVILEGE enabled in token). and call NtQuerySystemInformation with ProcessBasicInformation and PROCESS_EXTENDED_BASIC_INFORMATION as input. for enumerate all processes we can use NtQuerySystemInformation with SystemProcessInformation. of course possible and use CreateToolhelp32Snapshot + Process32First + Process32Next but this api very not efficient, compare direct call to NtQuerySystemInformation
also possible enumerate all threads in process and check it state and if state wait - wait reason. this is very easy, because all this information already returned by single call to NtQuerySystemInformation with SystemProcessInformation. with this we not need open processes. usually both this ways give the same result (for suspended/frozen) processes, but however use IsFrozen is most correct solution.
void PrintSuspended()
{
BOOLEAN b;
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);
ULONG cb = 0x1000;
NTSTATUS status;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PBYTE buf = new BYTE[cb])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PBYTE pb;
SYSTEM_PROCESS_INFORMATION* spi;
};
pb = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
if (!spi->UniqueProcessId)
{
continue;
}
if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
(ULONG)(ULONG_PTR)spi->UniqueProcessId))
{
PROCESS_EXTENDED_BASIC_INFORMATION pebi;
if (0 <= NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pebi, sizeof(pebi), 0) &&
pebi.Size >= sizeof(pebi))
{
if (pebi.IsFrozen)
{
DbgPrint("f:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
}
}
CloseHandle(hProcess);
}
if (ULONG NumberOfThreads = spi->NumberOfThreads)
{
SYSTEM_THREAD_INFORMATION* TH = spi->TH;
do
{
if (TH->ThreadState != StateWait || TH->WaitReason != Suspended)
{
break;
}
} while (TH++, --NumberOfThreads);
if (!NumberOfThreads)
{
DbgPrint("s:%x %wZ\n", spi->UniqueProcessId, spi->ImageName);
}
}
} while (NextEntryOffset = spi->NextEntryOffset);
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}

Local Hook not working

I have an application and wish to monitor MSWord keypressing (LOCAL HOOK), but I cant figure out how to find the pid to be used! The bellow CODE WORKS GOOD with global hook (pid = 0) and with (pid = GetCurrentThreadId). But doesn´t work with GetWindowThreadProcessId:
HWND hWindow = FindWindowEx(NULL,NULL,String("Notepad").w_str(),NULL);
if (!hWindow) {
ShowMessage("hWindow fail");
return;
}
unsigned long pid;
GetWindowThreadProcessId(hWindow ,&pid);
//pid = GetCurrentThreadId();
if (!hWindow) {
ShowMessage("pid fail");
return;
}
String s = "HookDLL.dll";
DllHandle=LoadLibrary(s.w_str());
HOOKFCT_2 InstHook=reinterpret_cast<HOOKFCT_2> (GetProcAddress(DllHandle,"InstallHook"));
if(!InstHook(pid, (void *)(callIt) ))
{
Label1->Caption="Unable to install mouse hook!";
}
else Label1->Caption="Mouse hook installed!";
I will be very, very gratefuLl for any light on the problem...
Notice:
I wish a hook to MSWord only.
The above code works, failling only when trying to hook on another application (i.e.: not using pid=0 or pid=GetCurrentThreadId), resulting in = "Unable to install mouse hook!".
I already try FindWindow, FindWindowEx, GetForegroundWindow, GetActiveWindow; since not of this works, I belive the problem is GetWindowThreadProcessId.
SetWindowsHookEx requires thread ID, not process ID. Pass thread ID instead:
DWORD threadID = GetWindowThreadProcessId(hWindow, 0);
if(!InstHook(threadID, (void *)(callIt) )) {...}

Windows API - ShellExecuteEx() didn't wait on USB drive and CD drive

I am writing a master installer with the following ShellExecuteEx() function that call a few Advanced Installer created installers (installing multiple products) one by one through a loop construct.
// Shell Execute
bool CFileHelper::ShellExecute(CString strCommandPath, CString strOptions)
{
CString strQCommandPath = CString(_T("\"")) + strCommandPath + CString(_T("\"")); //place the command in the quote to handle path with space
LPWSTR szInstallerPath = strQCommandPath.GetBuffer();
LPWSTR szOptions = strOptions.GetBuffer(MAX_PATH);
SHELLEXECUTEINFO ShellInfo; // Name structure
memset(&ShellInfo, 0, sizeof(ShellInfo)); // Set up memory block
ShellInfo.cbSize = sizeof(ShellInfo); // Set up structure size
ShellInfo.hwnd = 0; // Calling window handle
ShellInfo.lpVerb = _T("open");
ShellInfo.lpFile = szInstallerPath;
ShellInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //| SEE_MASK_NOASYNC | SEE_MASK_WAITFORINPUTIDLE;
ShellInfo.lpParameters = szOptions;
bool res = ShellExecuteEx(&ShellInfo); // Call to function
if (!res)
{
//printf( "CreateProcess failed (%d).\n", GetLastError() );
CString strMsg = CString(_T("Failed to execute command ")) + strCommandPath + CString(_T("!"));
AfxMessageBox(strMsg);
return false;
}
WaitForSingleObject(ShellInfo.hProcess, INFINITE); // wait forever for process to finish
//WaitForInputIdle(ShellInfo.hProcess, INFINITE);
CloseHandle( ShellInfo.hProcess);
strQCommandPath.ReleaseBuffer();
strOptions.ReleaseBuffer();
return true;
}
The function work every well when I have this master installer and other individual product installers on hard drive.
However, if I move all of them to either USB drive or CD, the ShellExecuteEx() didn't wait for the previous product installer to complete its task. So all product installers get lunched at once; giving me the error message "Another installation is in progress. You must complete that installation before continuing this one.".
One thing puzzle me is why it works on hard drive but not on USB drive and CD drive. I need to distribute the products on CD.
Putting Sleep(500) before WaitForSingleObject(ShellInfo.hProcess, INFINITE) didn't help as well.
Work from the assumption that this is real. The installer might have noticed it was started from a removable drive and copied itself to the hard disk. Launched that copy and quit. This avoids trouble when the user pops out the media, that produces a very low-level paging fault that the process itself cannot catch. The Windows dialog isn't great and may well run counter to the installer's request to insert the next disk.
Verify this guess by comparing the process ID of the process you started vs the one you see running in Taskmgr.exe. Reliably fixing this ought to be quite a headache.

Resources