SwitchDesktop 可以暂时工作,但片刻后会切换回来
SwitchDesktop works momentarily but switches back after a moment
我有一些代码来创建一个新桌面并在该桌面中启动一个进程。
几台选择Windows XP机器,当此代码运行时,我可以看到它切换到新桌面并开始该过程,但几乎立即,桌面切换回普通桌面。
这段代码在大约 98% 的机器上运行良好,我似乎无法找出任何原因,这在其他机器上不起作用。
SwitchDesktop
应该可靠吗? 是否可以将调用挂接到可能从其他应用程序调用的SwitchDesktop
?
我的代码:
int DLL_EXP_IMP WINAPI Process_Desktop(char *szDesktopName, char *szPath)
{
HDESK hOriginalThread;
HDESK hOriginalInput;
HDESK hNewDesktop;
int procSuccess;
// Save original ...
hOriginalThread = GetThreadDesktop(GetCurrentThreadId());
hOriginalInput = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
// Create a new Desktop and switch to it
hNewDesktop = CreateDesktop(szDesktopName, NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
SetThreadDesktop(hNewDesktop);
SwitchDesktop(hNewDesktop);
// This call blocks until the process exits, and is confirmed to work on the affected machines
procSuccess = StartProcess(szDesktopName, szPath);
// Restore original ...
SwitchDesktop(hOriginalInput);
SetThreadDesktop(hOriginalThread);
// Close the Desktop
CloseDesktop(hNewDesktop);
if (procSuccess != 0)
{
return procSuccess;
}
else
{
return 0;
}
}
我的猜测是 SetThreadDesktop() 失败了。
从 MSDN:"如果调用线程在其当前桌面上有任何窗口或挂钩,则 SetThreadDesktop 函数将失败(除非 hDesktop 参数是当前桌面的句柄)。
你提到 StartProcess() 会阻塞,直到进程终止。因此,没有人引用新桌面,因此桌面将消失。
您可能需要考虑将易出错的系统调用包装在C++-- 在它们失败时抛出异常。当然,CreateDesktop/CloseDesktop一对属于C++资源包装器。这是2013年!
SwitchDesktop 失败(大多数情况下是访问被拒绝,或者由于另一个桌面中的现有句柄而出现错误 170),或者有另一个程序切换回默认桌面。
我知道雅虎工具栏这样做了(版本 5-6-7,也许他们现在修复了);KABE4.exe(我不知道这是什么),一个Acronis程序(备份调度程序,AFAIK)等等。所有这些都是在没有任何用户干预的情况下调用SwitchDesktop(一个很大的禁忌)。
我为雅虎工具栏证明了这一点;通过将另一个dll注入yt.dll(由IE加载)并从挂机调用返回FALSE来挂钩SwitchDesktop解决了我的问题。
近 2 年前发送给雅虎的概念验证至今仍未得到答复。
在您发布的代码中,有那部分:
// Create a new Desktop and switch to it
hNewDesktop = CreateDesktop(szDesktopName, NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
SetThreadDesktop(hNewDesktop);
SwitchDesktop(hNewDesktop);
// This call blocks until the process exits, and is confirmed to work on the affected machines
procSuccess = StartProcess(szDesktopName, szPath);
// Restore original ...
SwitchDesktop(hOriginalInput);
SetThreadDesktop(hOriginalThread);
您对 StartProcess 函数的调用是在对 SwitchDesktop 的两次调用之间进行的。此代码中的任何函数都不会停止(暂停)或延迟正在运行的代码、线程或进程,因此当您切换到 hNewDesktop 时,您会立即切换回 hOriginalInput。您应该在调用 StartProcess 之后和第二次调用 SwitchDesktop 之前添加一个带有结束条件的 while 循环。我不知道while循环的结束条件是什么,但你知道,你会选择,毕竟这是你的程序。
例如,您可以使用 GetKeyState或 GetAsyncKeyState 函数来检查键盘上按下了哪个键,并将其作为 while 循环的结束条件,因此当您按下该键时,您将立即返回到原始桌面!
- 等待被迷住了,没有回来
- 将对象的字节复制到数组并再次复制回来是否安全
- 如何将文本文件加载到 QListwidget 并将其保存回来
- 我需要做一个空函数循环回来,而不会让它崩溃或跳过
- 将整数转换为字符数组,然后将其转换回来
- 将转换范围缩小到更大的类型(然后再回来)
- 将 QStringList 打包到 QString 并解压缩回来
- SwitchDesktop 可以暂时工作,但片刻后会切换回来
- 将人类可读日期转换为毫秒,然后再转换回来,而不会丢失信息
- 更改了bool值,但在while语句的下一个循环中它又变了回来
- 打印回来和第四
- SDL C++ TTF 会在一段时间后随机消失(并且不会回来)
- 我可以克隆C++对象的字节,覆盖原始字节,然后将这些字节复制回来吗?
- c_str回来了,但缺少第一个字符
- Kinect 从框架数据转换为深度数据,然后再转换回来
- 如何将无符号的 int 放入 char 数组并将其解压缩回来
- 将派生的对象投射到基础,然后再投射回来
- 正在将字节转换为char数组,然后再转换回来
- 让NaN回来了,不知道为什么
- OpenCV转换图像到字节和回来