У меня есть приложение C #, которое запускается из C ++ DLL с помощью API CreateProcessAsUserW. Процесс запущен успешно, но завершается немедленно. Он работает должным образом в Windows 10 [как 32-битной и 64-битной] и 32-битной в Windows 7. Я нашел следующую ссылку,
Почему происходит сбой этого процесса при запуске?
тем не менее, монитор процесса из SysInternals не находит отсутствующих DLL. [Я могу прикрепить сохраненные журналы из ProcMon] Я также попытался передать путь к папке приложения, как это было предложено в другом месте, в параметре API lpCurrentDirectory, но это тоже не сработало.
Я следовал указаниям Как получить активного пользователя, когда в Windows зарегистрировано несколько пользователей? написать код, который запускает процесс,
и метод, который запускает процесс, вызывается из службы Windows. Чтобы эмулировать это из командной строки, я использовал следующее
Как вы запускаете CMD.exe под учетной записью локальной системы? [psexec64 -i -s cmd.exe, а затем запустил процесс из cmd.exe]
Метод заключается в следующем
//Как получить активного пользователя, когда в Windows зарегистрировано несколько пользователей?
STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
{
//char *lpszPath = _com_util::ConvertBSTRToString(processName);
wchar_t* path = (wchar_t*)processName;//CharToWideChar(lpszPath);
DWORD session_id = -1;
DWORD session_count = 0;
WTS_SESSION_INFOA *pSession = NULL;if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
{
//log success
}
else
{
//log error
return S_OK;
}
logger->Log(L"Session Count", session_count);
logger->Log(L"Begin Enumerating Sesions");
for (int i = 0; i < session_count; i++)
{
session_id = pSession[i].SessionId;
logger->Log(L"SessionId", session_id);
WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
DWORD bytes_returned = 0;
if (::WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
session_id,
WTSConnectState,
reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
&bytes_returned))
{
wts_connect_state = *ptr_wts_connect_state;
::WTSFreeMemory(ptr_wts_connect_state);
if (wts_connect_state != WTSActive) continue;
}
else
{
//log error
continue;
}
logger->Log(L"End Enumerating Sesions");
logger->Log(L"Selected Session Id", session_id);
HANDLE hImpersonationToken;
if (!WTSQueryUserToken(session_id, &hImpersonationToken))
{
//log error
logger->Log(L"Exception in WTSQueryUserToken", GetLastError());
continue;
}//Get real token from impersonation token
DWORD neededSize1 = 0;
HANDLE *realToken = new HANDLE;
if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
else
{
//log error
logger->Log(L"Exception in GetTokenInformation", GetLastError());
continue;
}HANDLE hUserToken;
if (!DuplicateTokenEx(hImpersonationToken,
//0,
//MAXIMUM_ALLOWED,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hUserToken))
{
//log error
logger->Log(L"Exception in DuplicateTokenEx", GetLastError());
continue;
}
// Get user name of this process
//LPTSTR pUserName = NULL;
WCHAR* pUserName;
DWORD user_name_len = 0;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
{
//log username contained in pUserName WCHAR string
// char * lpszUserName = WideCharToChar(pUserName);
logger->Log(pUserName);
//LocalFree(lpszUserName);
}
else
{
logger->Log(L"Exception in WTSQuerySessionInformation", GetLastError());
}
//Free memory
if (pUserName) WTSFreeMemory(pUserName);
ImpersonateLoggedOnUser(hUserToken);
STARTUPINFOW StartupInfo;
StartupInfo.cb = sizeof(STARTUPINFOW);//GetStartupInfoW(&StartupInfo);
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
//Uncommented by Sagar 20th January 20118 1612
StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
//to Hide Console Process 03-10-2018
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_SHOW;//SW_HIDE;PROCESS_INFORMATION processInfo;SECURITY_ATTRIBUTES Security1;
ZeroMemory(&Security1, sizeof(Security1));
Security1.nLength = sizeof SECURITY_ATTRIBUTES;SECURITY_ATTRIBUTES Security2;
ZeroMemory(&Security2, sizeof(Security2));
Security2.nLength = sizeof SECURITY_ATTRIBUTES;
void* lpEnvironment = NULL;
// Get all necessary environment variables of logged in user
// to pass them to the new process
BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
if (!resultEnv)
{
//log error
DWORD err = GetLastError();
logger->Log(L"Exception in CreateEnvironmentBlock", err);
continue;
}
WCHAR PP[1024]; //path and parameters
ZeroMemory(PP, 1024 * sizeof WCHAR);
wcscpy_s(PP, path);
wcscat_s(PP, L" ");
//wcscat(PP, args);
// Start the process on behalf of the current user
BOOL result = CreateProcessAsUserW(hUserToken,
PP,
NULL,
&Security1,
&Security2,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE/*| CREATE_NO_WINDOW*/,//CREATE_NO_WINDOW to Hide Console Process 03-10-2018
/*lpEnvironment*/NULL,
//"C:\\ProgramData\\some_dir",
NULL,
/*NULL,*/
&StartupInfo,
&processInfo);
if (!result)
{
//log error
//char * lpszPath = WideCharToChar(PP);
logger->Log(L"Failed to create process", PP);
//LocalFree(lpszPath);
DWORD err = GetLastError();
logger->Log(L"GetLastError returned", err);
}
else
{
*dwProcessId = processInfo.dwProcessId;
logger->Log(L"Created Process", *dwProcessId);
//log success
}
DestroyEnvironmentBlock(lpEnvironment);
CloseHandle(hImpersonationToken);
CloseHandle(hUserToken);
CloseHandle(realToken);
RevertToSelf();
}
WTSFreeMemory(pSession);return S_OK;
}
Скриншоты Procmon прилагаются ниже
Пожалуйста помоги.
Спасибо,
Сагар
[![Pg 1](https://i.stack.imgur.com/CJCrG.png)
[![Pg 2](https://i.stack.imgur.com/uo8Uw.png)
[![Pg 3](https://i.stack.imgur.com/G7g12.png)
[![Pg 4](https://i.stack.imgur.com/6e5w4.png)
[![Pg 5](https://i.stack.imgur.com/8k2b0.png)
Я попробовал следующие перестановки
Target Process : ATL DLL : Launcher:Result
64 bit 64 bit 64 bit Crashes
64 bit 32 bit 64 bit Crashes
32 bit 32 bit 64 bit Crashes
32 bit 64 bit 64 bit Crashes
32 bit 32 bit 32 bit OK
64 bit 32 bit 32 bit OK
64 bit 64 bit 32 bit OK
32 bit 64 bit 32 bit OK
Таким образом, кажется, что если процесс запуска является 64-битным, он всегда падает, а если он 32-битный, он всегда завершается успешно. В чем разница между 64-битным и 32-битным процессами запуска?
Я получил ответ на https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb9d15fb-dc9f-488e-92c4-e0bb438442e1/64-bit-dot-net-process-created-with-createprocessasuserw-exits-immediately- с-исключения-кода? форум = vcgeneral [RLWA32 ответил на это] Возникла проблема с запуском процесса. Его код для запуска процесса выглядит следующим образом, и он отлично работает.
UINT __stdcall RunProgram(LPVOID pv)
{
WCHAR szTarg32[MAX_PATH] = TARGET32_PATH, szTarg64[MAX_PATH] = TARGET64_PATH;
LPWSTR pszProcess = nullptr;
PWTS_SESSION_INFOW pwsi = NULL;
DWORD dwSession = -1, dwCount = 0;
HANDLE hToken = NULL;
LPVOID lpEnvironment = nullptr;
LPWSTR pszPath = nullptr;
UINT ret = 1;DWORD dwOpcode = reinterpret_cast<DWORD>(pv);
if (dwOpcode == LAUNCH_X86PROCESS)
pszProcess = szTarg32;
else
pszProcess = szTarg64;
if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER, 0, 1, &pwsi, &dwCount))
{
Report(L"WTSEnumerateSessions failed with %d\n", GetLastError());
return ret;
}
for (DWORD i = 0; i < dwCount; i++)
{
if (pwsi[i].State == WTSActive)
{
dwSession = pwsi[i].SessionId;
break;
}
}
if (dwSession != -1)
{
if (WTSQueryUserToken(dwSession, &hToken))
{
if (CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE))
{
HRESULT hr;
if (SUCCEEDED((hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, hToken, &pszPath))))
{
if (ImpersonateLoggedOnUser(hToken))
{
STARTUPINFOW si = { sizeof si };
PROCESS_INFORMATION pi = {};
if (CreateProcessAsUserW(hToken, pszProcess, nullptr, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, lpEnvironment, pszPath, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
Report(L"CreateProcessAsUser started %s, pid is %d\n", pszProcess, pi.dwProcessId);
ret = 0;
}
else
Report(L"CreateProcessAsUser failed with %d\n", GetLastError());
RevertToSelf();
}
else
Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
}
else
Report(L"SHGetKnownFolderPath failed with 0x%X\n", hr);
}
else
Report(L"CreateEnvironmentBlock failed with %d\n", GetLastError());
}
else
Report(L"WTSQueryUserToken failed with %d\n", GetLastError());
}
else
Report(L"WTSEnumerateSessions reported no active session\n");
if (pwsi)
WTSFreeMemory(pwsi);
if (hToken)
CloseHandle(hToken);
if (lpEnvironment)
DestroyEnvironmentBlock(lpEnvironment);
if (pszPath)
CoTaskMemFree(pszPath);
return ret;
}
Других решений пока нет …