如何在 Win 7 中为 C 中的 Windows 服务检索系统代理设置
Posted
技术标签:
【中文标题】如何在 Win 7 中为 C 中的 Windows 服务检索系统代理设置【英文标题】:How to retrieve system proxy settings in Win 7 for windows service in C 【发布时间】:2017-02-15 08:27:36 【问题描述】:我正在编写一个将作为服务运行并选择系统代理设置以与外界通信的应用程序。我尝试了WinHttpGetIEProxyConfigForCurrentUser
,但它无法检索当前用户的代理设置,这很明显,因为服务正在运行本地系统的域。为了实现这一点,我必须让用户登录我不希望应用程序用户执行的服务。我读到了可以传递给 CreateService() 的 SERVICE_USER_OWN_PROCESS
参数,但我既没有在 WinNT.h 中找到它的声明,也不确定它是否会起作用。由于这个问题,应用程序的开发被卡住了。有人可以帮忙吗?
【问题讨论】:
【参考方案1】:在当前用户的上下文中运行程序时,我遇到了类似的情况。
首先 - 在全局范围内的某个地方 - 定义以下变量:
HANDLE hUsrToken;
HANDLE hDupToken;
int sessionId;
需要获取当前用户的会话ID:
int getInteractiveSessinoId()
PWTS_SESSION_INFO pSessInfo;
ulong count; // Number of current user sessions
int result = -1;
if (!WTSEnumerateSessions(WTS_CURRENT_SERVER, 0, 1, &pSessInfo, &count))
printf("Getting session information failed with error %d\n", << GetLastError());
WTSFreeMemory(pSessInfo);
return -2;
for (ulong loop = 0; loop < count; loop++)
if (pSessInfo[loop].State == WTSActive)
printf("Session %d is currently active\n", pSessInfo[loop].SessionId);
result = pSessInfo[loop].SessionId;
break;
WTSFreeMemory(pSessInfo);
return result;
接下来你需要模拟当前用户(我称之为“附加到会话”):
bool attachToSession(int sessionId)
// We need to duplicate the token of the session's user
if (!WTSQueryUserToken(sessionId, &hUsrToken))
pritnf("Query the user token failed with error %d\n", GetLastError());
return false;
if (!DuplicateTokenEx(hUsrToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation , &hDupToken))
printf("Duplicating a token failed with error %d\n", GetLastError());
return false;
if (!ImpersonateLoggedOnUser(hDupToken))
printf("Impersonating the user failed with error %d\n", GetLastError();
return false;
return true;
现在在当前用户的上下文中做任何你想做的事情,完成后,从用户的上下文中恢复(或“分离”):
bool detachFromSession()
if (!RevertToSelf())
printf("Reverting the token failed with error %d\n", GetLastError());
return false;
(void)CloseHandle(hDupToken);
(void)CloseHandle(hUsrToken);
return true;
我不确定将令牌应用于当前(服务)线程是否是个好主意。我认为创建一个新线程来执行您想要在用户上下文中执行的任何操作并将模拟令牌应用于它是一个更好的主意。所以你的代码部分可能如下所示:
HANDLE hUsrToken;
HANDLE hDupToken;
HANDLE hThread;
int sessionId;
DWORD threadId;
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
// WinHttpGetIEProxyConfigForCurrentUser(...
sessionId = getInterActiveSessionId();
if (attachToSession(int sessionId) == false)
// Error handling
return;
hThread = CreateThread(NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
NULL, // argument to thread function
CREATE_SUSPENDED, // Delay execution
&threadId);
if (SetThreadToken(hThread, hDupToken) == false)
// Error handling
return;
ResumeThread(hThread);
我不能保证这会解决您的问题,但我希望它会。祝你好运!
【讨论】:
在没有用户登录系统的情况下调用模拟 API 时服务的行为是什么? 上面代码中的 getInteractiveSessinoId() 将返回一个无效的 id(返回 -2),应该正确处理。否则,attachToSession() 将在 WTSQueryUserToken() 中失败,将返回在函数中处理的错误。简而言之:确保您有一个交互式会话。附加到会话 0(服务正在运行的地方)没有意义,因为您已经在该会话中运行。以上是关于如何在 Win 7 中为 C 中的 Windows 服务检索系统代理设置的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 7 中为 composer 创建一个工作别名
让 libspotify 中的示例在 Windows 7 下工作