0
體系結構是一個服務可以與系統特權,代碼段1無法關閉從服務中的用戶會話的過程
用戶會話的處理組內啓動一個進程當服務需要停止本身,我想發送一個信號給子進程,使它有機會優雅地關閉代碼片段2.
問題是它似乎沒有發送信號,沒有任何明顯的錯誤代碼。我測試了從命令提示符運行的子進程,ctrl + break工作得很好。
代碼片段
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\Default";
si.dwFlags |= STARTF_USESTDHANDLES;
LPVOID environment;
BOOL createRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
if (!createRet) {
throw std::runtime_error("Failed to create environment block");
}
DWORD creationFlags =
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW |
CREATE_UNICODE_ENVIRONMENT |
CREATE_NEW_PROCESS_GROUP; // this create a process in a group
// launch a process in the user session
// the toke is a system privilege toke within the user session
createRet = CreateProcessAsUser(
userToken, NULL, LPSTR(command.c_str()),
sa, NULL, TRUE, creationFlags,
environment, NULL, &si, &processInfo);
if (!createRet) {
throw std::runtime_error("Failed to create the service in user session");
}
m_serviceGroupId = processInfo.dwProcessId;
DestroyEnvironmentBlock(environment);
CloseHandle(userToken);
代碼片段2
if (m_serviceGroupId == 0) {
return;
}
HANDLE process;
const UINT kExitCode = 0;
const UINT kShutdownTimeout = 3000;
if (findProcessInSession(kServiceProcess, &process, getActiveSession())) {
BOOL r = GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, m_serviceGroupId);
// this won't success if I don't specifically call AllocConsole() in the constructor
if (!r) {
writeEventErrorLog(GetLastErrorAsString().c_str());
}
DWORD exitCode = WaitForSingleObject(process, kShutdownTimeout);
if (exitCode != WAIT_OBJECT_0) {
// always fall into forceful shutdown
writeEventErrorLog("Forcefully shutdown synergy service");
// GetLastErrorAsString returns empty string
writeEventErrorLog(GetLastErrorAsString().c_str());
if (!TerminateProcess(process, kExitCode)) {
writeEventErrorLog("Failed to shutdown synergy service");
}
}
}
m_serviceGroupId = 0;
'GenerateConsoleCtrlEvent'遠程調用'csrss'。但您的服務附加到另一個「csrss」進程 - 每個會話都有自己的「csrss」。所以'GenerateConsoleCtrlEvent'不能用於另一個會話中的發送控制事件 – RbMm
@RbMm謝謝。我有辦法管理子進程嗎? RPC調用? – Jerry
您需要做的只是從服務向孩子發送一次性消息,因此命名事件對象可能是最合適的選擇。在更復雜的情況下,您可以使用命名管道。還有其他的選擇。 –