I'm running an exe as a service that launches another exe (im gonna call it foo.exe) as soon the current user logged in.
However when there's more than one user and I switch between them, how I could verify if any currently running foo.exe belongs to the new switched user, and if don't, then launch a new foo.exe?
The problem I'm facing: process_session_id is being returned 'wrong'.
If i run foo.exe on the user at session 1, and switch to another user in a new session'2', and call the API:
ProcessIdToSessionId(pid, &process_session_id);
with the pid of foo.exe that's running on session1, process_session_id returns 2 instead of 1.
It should return 1, as it's running on session1 and there's no foo.exe running on session2.
When I go to the task manager > Details and check under the tab Session it does display the value correctly, session 1.
The code below represents the exe running as service, and it's running at the session 0.
#include <wtsapi32.h> // For GetCurrentUserSessionId_RemoteDesktop
#pragma comment(lib, "wtsapi32.lib") //
auto _GetAllProcessId(LPCTSTR ProcessName)
{
std::vector<int> processes_id {};
PROCESSENTRY32 pt;
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pt.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hsnap, &pt)) { // must call this first
do
{
if (!lstrcmpi(pt.szExeFile, ProcessName))
processes_id.push_back(pt.th32ProcessID);
} while (Process32Next(hsnap, &pt));
}
CloseHandle(hsnap); // close handle on failure
return processes_id;
}
DWORD GetCurrentUserSessionId_RemoteDesktop()
{
int dwSessionId = 0;
PWTS_SESSION_INFO pSessionInfo = 0;
DWORD dwCount = 0;
// Get the list of all terminal sessions
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&pSessionInfo, &dwCount);
// look over obtained list in search of the active session
for (DWORD i = 0; i < dwCount; ++i)
{
WTS_SESSION_INFO si = pSessionInfo[i];
if (WTSActive == si.State)
{
// If the current session is active – store its ID
dwSessionId = si.SessionId;
break;
}
}
WTSFreeMemory(pSessionInfo);
return dwSessionId;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD pid = 0;
DWORD current_user_session_id = 0;
bool process_running = false;
std::vector<int> processes_id{};
while (true)
{
processes_id = _GetAllProcessId(L"foo.exe");
if (processes_id.empty())
{
// Launch the process as the current user.
continue;
}
for (size_t i = 0; i < processes_id.size(); i++)
{
pid = processes_id[i];
DWORD process_session_id = 0;
// Get the sessionId from where the given pid is running.
ProcessIdToSessionId(pid, &process_session_id);
// If its running on sessionId 0 we must close it.
// As inside of this session it will not work properly.
if (process_session_id == 0)
{
const auto explorer = OpenProcess(PROCESS_TERMINATE, false, pid);
TerminateProcess(explorer, 1);
CloseHandle(explorer);
continue;
}
else
// Check if the exe belong to the actual user logged-in.
{
current_user_session_id = GetCurrentUserSessionId_RemoteDesktop();
if (process_session_id = current_user_session_id)
process_running = true;
}
}
// As we could not find the process running for the current user, launch it.
if (!process_running)
// Launch the process as the current user.
Sleep(10);
}
return 0;
}
To launch foo.exe as the current user, im using this lib: https://github.com/noelmartinon/ExecAs
Why im doing this all? foo.exe dont work properly when executed inside of session 0, and im trying to start him at login time.