C++ get windows title using process name - c++

edit: how can i get windows title using processname? for example get current title of chrome.exe

You can get title of specific windows using it's process ID.
If you know the name of executed file(ex: Chrome.exe), you can get Handle with FindWindowEX() or get PID "Chrome.exe" with CreateToolHelp32Snapshot.
Then use EnumWindows to get HWND using HANDLE.
struct param_enum
{
unsigned long ulPID;
HWND hWnd_out;
};
HWND find_specific_window(unsigned long process_id)
{
param_enum param_data;
param_data.ulPID = process_id;
param_data.hWnd_out = 0;
EnumWindows(enum_windows_callback, (LPARAM)&param_data);
get_window_title(process_id, param_data.hWnd_out);
return param_data.hWnd_out;
}
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
param_enum& param_data = *(param_enum*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (param_data.ulPID != process_id)
{
return TRUE;
}
param_data.hWnd_out = handle;
return FALSE;
}
---------------------------Get Handle---------------------------
HANDLE GetHandleFromProcessPath(TCHAR* szExeName, DWORD& dwPID)
{
HANDLE hExeName = INVALID_HANDLE_VALUE;
HANDLE hSnap = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE != hSnap)
{
if (Process32First(hSnap, &pe32))
{
do
{
//!!! Attention pe32.szExeFile always return exe file name. not window title.
if (NULL != _tcsstr(pe32.szExeFile, szExeName))
{
hExeName = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pe32.th32ProcessID);
dwPID = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe32));
}
}
return hExeName;
}

Completing the answer of "G.Alexander" and and the comment of Skewjo
the get_window_title code is incomplete. So, worked for me, by removing it and calling find_specific_window like below:
wchar_t* caption = new wchar_t[MAX_PATH*2];
HWND h = find_specific_window(processID);
GetWindowTextW(h, caption, MAX_PATH*2);

Related

How can DOM elements be retrieved from a C++ program?

I would need to get all elements of webpage displayed in IE from a c++ program.
I tried to see with spy++ but there's only the IEFrame.
So I'm thinking about using the developement tool (F12 in IE), I heard there's a way to automat it, a good idea ?
Thanks
You can get an IHtmlDocument2 reference from an IE's window handle, even out-of-process. This is documented here https://support.microsoft.com/en-us/help/249232/how-to-get-ihtmldocument2-from-a-hwnd, but not really supported by Microsoft.
However it looks like it still works today, I've tested it with a Windows 10 box, and IE is now a frozen app, so not going to change any time soon.
Once you have the proper HWND for Internet Explorer, than you can get the DOM with a code like this. Make sure IE and your program run at the same security level
The DOM is the same as when you're coding IE inprocess (host, activex, etc.), however for security reasons, some things may not work :
void DoSomeDomOperations(HWND hwnd)
{
UINT msg = RegisterWindowMessage(L"WM_HTML_GETOBJECT");
LRESULT result = 0;
SendMessageTimeout(hwnd, msg, NULL, NULL, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&result);
if (!result)
return;
// get main document object
IHTMLDocument2 *doc = NULL;
ObjectFromLresult(result, IID_IHTMLDocument2, NULL, (void**)&doc);
if (!doc)
return;
// get document's url
BSTR url = NULL;
doc->get_URL(&url);
wprintf(L"url:%s\n", url);
SysFreeString(url);
// get body element
IHTMLElement *element = NULL;
doc->get_body(&element);
if (element)
{
BSTR text = NULL;
element->get_innerText(&text);
wprintf(L"text:%s\n", text);
SysFreeString(text);
element->Release();
}
// etc.
// etc.
doc->Release();
}
And here is a full sample console app that scans all current IE processes running:
BOOL CALLBACK GetIEServerWindowProc(HWND hwnd, LPARAM lParam)
{
// enumerate all child windows to find IE's COM server
wchar_t className[100];
GetClassName(hwnd, className, 100);
if (!wcscmp(className, L"Internet Explorer_Server"))
{
*((HWND*)lParam) = hwnd;
return FALSE;
}
return TRUE;
}
HWND GetIEServerWindow(HWND hwnd)
{
HWND serverHwnd = NULL;
EnumChildWindows(hwnd, GetIEServerWindowProc, (LPARAM)&serverHwnd);
return serverHwnd;
}
struct IEServer
{
DWORD processId;
HWND serverHwnd;
};
BOOL CALLBACK GetIEProcessServerWindowProc(HWND hwnd, LPARAM lParam)
{
DWORD processId = ((IEServer*)lParam)->processId;
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid == processId)
{
HWND serverHwnd = GetIEServerWindow(hwnd);
if (serverHwnd)
{
((IEServer*)lParam)->serverHwnd = serverHwnd;
return FALSE;
}
}
return TRUE;
}
HWND GetIEProcessServerWindow(DWORD processId)
{
IEServer ie = { processId, NULL };
EnumWindows(GetIEProcessServerWindowProc, (LPARAM)&ie);
return ie.serverHwnd;
}
void EnumerateIEProcesses()
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE)
return;
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(h, &process))
{
do
{
// we only consider IE processes
if (!wcscmp(process.szExeFile, L"iexplore.exe"))
{
HWND serverHwnd = GetIEProcessServerWindow(process.th32ProcessID);
if (serverHwnd)
{
DoSomeDomOperations(serverHwnd);
}
}
} while (Process32Next(h, &process));
}
CloseHandle(h);
}
int main()
{
CoInitialize(NULL);
EnumerateIEProcesses();
CoUninitialize();
return 0;
}

How to find out if the process is crashed using c++ winapi?

When error occurs in the program, on the screen we can see something like this:
Is there anyway to determine this situation using c++ winapi? I have aldready tried to use this code to find out if the main thread of the procces is suspend. But it doesn't.
I also tried to send timeot messages(code below) but result is always true, even if error window have appeared.
typedef struct tagENUMINFO
{
// In Parameters
DWORD PId;
// Out Parameters
HWND hWnd;
HWND hEmptyWnd;
HWND hInvisibleWnd;
HWND hEmptyInvisibleWnd;
} ENUMINFO, *PENUMINFO;
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
DWORD pid = 0;
PENUMINFO pInfo = (PENUMINFO)lParam;
TCHAR szTitle[_MAX_PATH+1];
// sanity checks
if (pInfo == NULL)
// stop the enumeration if invalid parameter is given
return(FALSE);
// get the processid for this window
if (!::GetWindowThreadProcessId(hWnd, &pid))
// this should never occur :-)
return(TRUE);
// compare the process ID with the one given as search parameter
if (pInfo->PId == pid)
{
// look for the visibility first
if (::IsWindowVisible(hWnd))
{
// look for the title next
if (::GetWindowText(hWnd, szTitle, _MAX_PATH) != 0)
{
pInfo->hWnd = hWnd;
// we have found the right window
return(FALSE);
}
else
pInfo->hEmptyWnd = hWnd;
}
else
{
// look for the title next
if (::GetWindowText(hWnd, szTitle, _MAX_PATH) != 0)
{
pInfo->hInvisibleWnd = hWnd;
}
else
pInfo->hEmptyInvisibleWnd = hWnd;
}
}
// continue the enumeration
return(TRUE);
}
HWND GetMainWindow(DWORD PId)
{
ENUMINFO EnumInfo;
// set the search parameters
EnumInfo.PId = PId;
// set the return parameters to default values
EnumInfo.hWnd = NULL;
EnumInfo.hEmptyWnd = NULL;
EnumInfo.hInvisibleWnd = NULL;
EnumInfo.hEmptyInvisibleWnd = NULL;
// do the search among the top level windows
::EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)&EnumInfo);
// return the one found if any
if (EnumInfo.hWnd != NULL)
return(EnumInfo.hWnd);
else if (EnumInfo.hEmptyWnd != NULL)
return(EnumInfo.hEmptyWnd);
else if (EnumInfo.hInvisibleWnd != NULL)
return(EnumInfo.hInvisibleWnd);
else
return(EnumInfo.hEmptyInvisibleWnd);
}
DWORD GetProcessByExeName(char *ExeName)
{
DWORD Pid;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return false;
}
if (Process32First(hProcessSnap, &pe32))
{
do
{
if (strcmpi(pe32.szExeFile, ExeName) == 0)
{
CloseHandle(hProcessSnap);
return pe32.th32ProcessID;
}
} while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle(hProcessSnap);
return 0;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prev, LPSTR cmdline, int show)
{
HWND Hwnd;
LRESULT res;
DWORD PID;
PID=GetProcessByExeName("procces.exe");
Hwnd=GetMainWindow(PID);
res = SendMessageTimeout(Hwnd, WM_NULL, NULL, NULL, SMTO_ABORTIFHUNG, 3000,NULL);
//res == 1 always
}
Yes there is a way, all crash interceptors work this way, like the firefox crash reporter.
On windows you can use structured exception handling:
reference:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms680657(v=vs.85).aspx
and howto:
http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
extract:
LONG WINAPI MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionPtrs)
{
// Do something, for example generate error report
//..
// Execute default exception handler next
return EXCEPTION_EXECUTE_HANDLER;
}
void main()
{
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
// .. some unsafe code here
}
I found another solution. This error message has it's own procces WerFault.exe, we can simply destroy it with TerminateProcess() and the hang procces will be destroyed too. And then it is quite simple to notice that the required process does not exist.

EnumDesktopWindows Error: (183) Cannot create a file when that file already exists

Anyone know why returns 183 in call EnumDesktopWindows
This process is an service running in System LocalService
I'm trying to put the window in the top, because the process starts minimized.
Thank for Help
My Code:
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
DWORD dwPID;
GetWindowThreadProcessId( hwnd, &dwPID );
if( dwPID == lParam ) {
SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE );
SwitchToThisWindow(hwnd, true);
SetFocus( hwnd );
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam) {
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if(hDesk != NULL) {
if(!EnumDesktopWindows(hDesk,&EnumWindowsProc, lParam)) {
//This call returns (183) Cannot create a file when that file already exists
}
CloseDesktop(hDesk);
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation,FALSE,WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if(hWinStat) {
SetProcessWindowStation(hWinStat);
EnumDesktops(hWinStat,&EnumDesktopProc,lParam);
CloseWindowStation(hWinStat);
}
return TRUE;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bResult = FALSE;
DWORD dwSessionId,winlogonPid;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
//////////////////////////////////////////
// Find the winlogon process
////////////////////////////////////////
PROCESSENTRY32 procEntry;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return false;
procEntry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &procEntry))
return false;
do {
if (_wcsicmp(procEntry.szExeFile, L"winlogon.exe") == 0) {
// We found a winlogon process...make sure it's running in the console session
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId) {
winlogonPid = procEntry.th32ProcessID;
break;
}
}
} while (Process32Next(hSnap, &procEntry));
WTSQueryUserToken(dwSessionId,&hUserToken);
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL|SW_RESTORE;
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);
if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
|TOKEN_READ|TOKEN_WRITE,&hPToken))
{
return false;
}
if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
return false;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
return false;
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
return false;
LPVOID pEnv = NULL;
if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
else
pEnv = NULL;
// Launch the process in the client's logon session.
std::wstring params = aParams;
std::wstring path = aPath;
if(aMode == L"select") {
TCHAR infoBuffer[MAX_PATH];
GetSystemWindowsDirectory(infoBuffer, MAX_PATH);
std::wstring windowsDir(infoBuffer);
path = windowsDir+L"\\explorer.exe";
params = L" /n, /select,"+replaceString(aPath, L"\\\\", L"\\");
}
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
path.c_str(), // file to execute
params.length() > 0 ? stringToLPWSTR(wideToUtf8(params)) : NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
EnumWindowStations(&EnumWindowStationProc, (LPARAM)(pi.dwProcessId));
// End impersonation of client.
//GetLastError Shud be 0
int rv = GetLastError();
//Perform All the Close Handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
return !rv;
}
Error 183 is ERROR_ALREADY_EXISTS. EnumDesktopWindows() does not set that error, so it must be a carry-over from an earlier API call. If you read the documentation says this:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682615.aspx
You must ensure that the callback function sets SetLastError if it fails.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682614.aspx
If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for the caller to retrieve by calling GetLastError.
So try something more like this:
struct WndInfo
{
DWORD dwProcessID;
HWND hWnd;
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WndInfo *pInfo = (WndInfo*) lParam;
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if (dwPID == pInfo->dwProcessID)
{
pInfo->hWnd = hwnd;
SetLastError(0);
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam)
{
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if (hDesk != NULL)
{
if (!EnumDesktopWindows(hDesk, &EnumWindowsProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseDesktop(hDesk);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if (hWinStat != NULL)
{
SetProcessWindowStation(hWinStat);
if (!EnumDesktops(hWinStat, &EnumDesktopProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseWindowStation(hWinStat);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
HWND findWindowForProcess(DWORD PID)
{
WndInfo info;
info.dwProcessID = PID;
info.hWnd = NULL;
if (!EnumWindowStations(&EnumWindowStationProc, (LPARAM)&info))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
return info.hWnd;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
...
bResult = CreateProcessAsUser(...);
if (bResult)
{
HWND hWnd = findWindowForProcess(pi.dwProcessId);
if (hWnd != NULL)
{
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
SwitchToThisWindow(hWnd, TRUE);
SetFocus(hWnd);
}
}
...
}
With that said, since all you are really trying to do is execute a new process in a specific user session, you don't need to bother with all that enumeration logic. You don't need to find the WinLogon process at all, you already have the user's token from WTSQueryUserToken() so just duplicate+adjust that token as needed. And you are not doing anything useful in your window enumeration that the new process would not already do by default when it is started, so just get rid of that logic, too.
And then finally fix your error handling (or lack of) so you can close any handles that are open and not leak them.

Is there a way to check which process is recieving User input?

Is there a way to check which process is receiving user input from a complete list of all running processes? For example:
PROCESSENTRY32 procentry;
HANDLE hproc;
BOOL retval, ProcFound = false;
hproc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //GetsSnapshotOfAllProcesses
if(hproc == INVALID_HANDLE_VALUE)
{ // If Couldnt get snapshot
MessageBox(NULL, "Unable To Get Snapshot", "LoaderError", MB_OK);
return false;
}
procentry.dwSize = sizeof(PROCESSENTRY32); // Initialize
retval = Process32First(hproc, &procentry); //Copies Snapshot procentry
while(retval)
{
**if(UserInput == TRUE))**
{
return procentry.th32ProcessID; //
}
retval = Process32Next(hproc, &procentry); //
}
return 0;
}
Is there a function that will let me check which process is receiving user input?
if(UserInput == TRUE))
Also, is there a way to translate the processes to a string?
GetForegroundWindow() and GetWindowThreadProcessId() is the way to go:
DWORD dwProcessID = 0;
HWND hFGWnd = GetForegroundWindow();
if (hFGWnd != NULL)
GetWindowThreadProcessId(hFGWnd, &dwProcessID);
return dwProcessID;

Not able to Print the folder path in EditBox- MFC

I am using the following function ..instead of CFolderDialog.. to get the folder path...check my code below....am getting a run time error when i try toprint the folder path name in a edit box..
void
CSelfExtractorUIDlg::OnBnClickedButton1()
{
CDialog dlg;
HWND hwnd = NULL; LPCTSTR szCurrent =
(LPCTSTR)malloc(25*sizeof(TCHAR));
szCurrent = NULL; LPTSTR szPath =
(LPTSTR)malloc(25*sizeof(TCHAR)); BOOL
check =
BrowseForFolder(hwnd,szCurrent,szPath);
if( check == TRUE) {
dlg.SetDlgItemTextW(IDC_EDIT1,szPath);
}
}
BOOL BrowseForFolder(HWND hwnd,
LPCTSTR szCurrent, LPTSTR szPath) {
BROWSEINFO bi = { 0 }; LPITEMIDLIST
pidl; TCHAR szDisplay[256]; BOOL
retval;
//CoInitialize();
bi.hwndOwner = hwnd;
bi.pszDisplayName = szDisplay;
bi.lpszTitle = TEXT("Please
choose a folder."); bi.ulFlags
= BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; bi.lpfn
= BrowseCallbackProc; bi.lParam = (LPARAM) szCurrent;
pidl = SHBrowseForFolder(&bi);
if (NULL != pidl) {
retval = SHGetPathFromIDList(pidl, szPath);
CoTaskMemFree(pidl); } else {
retval = FALSE; }
if (!retval) {
szPath[0] = TEXT('\0'); }
CoUninitialize(); return retval;
} static int CALLBACK
BrowseCallbackProc(HWND hwnd,UINT
uMsg, LPARAM lParam, LPARAM lpData)
{
// If the BFFM_INITIALIZED message is
received // set the path to the start
path.
switch (uMsg) { case
BFFM_INITIALIZED: { if (NULL !=
lpData) { SendMessage(hwnd,
BFFM_SETSELECTION, TRUE, lpData); }
} }
return 0; // The function
25 characters seems a little short for a full path length, I'd use MAX_PATH.