#include "mainwindow.h" #include <QApplication> #include <windows.h> //#include <wtsapi32.h> int main(int argc, char *argv[]) { HANDLE mutex = ::CreateMutex(Q_NULLPTR,true,(LPCWSTR)qApp->applicationName().toStdWString().c_str()); if(GetLastError() == ERROR_ALREADY_EXISTS) { QMessageBox waringBox(QMessageBox::Warning,QStringLiteral("警告"),QStringLiteral("程序[文本数据同步服务端]只能运行一个!")); waringBox.setButtonText(QMessageBox::Ok,QStringLiteral("确定")); waringBox.setStandardButtons(QMessageBox::Ok); waringBox.exec(); ::CloseHandle(mutex); return 0; } else { ::ReleaseMutex(mutex); } QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 上面的QT代码可有效限制在windows10系统只能打开一个程序, 但是在windows Server2016系统中,由于有多个用户界面,不同用户界面依然可以打开多个程序, 请问如何限制在windows Server2016系统中,不管有多少个用户界面,也只能打开一个程序,请给我完整代码。
时间: 2024-01-22 09:02:01 浏览: 72
在 Windows Server 2016 系统中,可以使用 WTSQueryUserToken 函数获取当前用户的令牌,然后使用 CreateProcessAsUser 函数创建进程,从而实现在所有用户界面下只能打开一个程序的效果。
以下是完整代码:
```
#include "mainwindow.h"
#include <QApplication>
#include <windows.h>
#include <wtsapi32.h>
#pragma comment(lib, "Wtsapi32.lib")
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
HANDLE hToken = NULL;
DWORD dwSessionId = WTSGetActiveConsoleSessionId();
if (!WTSQueryUserToken(dwSessionId, &hToken)) {
QMessageBox::warning(nullptr, QStringLiteral("错误"), QStringLiteral("获取用户令牌失败!"));
return -1;
}
HANDLE mutex = ::CreateMutex(Q_NULLPTR, true, (LPCWSTR)qApp->applicationName().toStdWString().c_str());
if (GetLastError() == ERROR_ALREADY_EXISTS) {
QMessageBox warningBox(QMessageBox::Warning, QStringLiteral("警告"), QStringLiteral("程序[文本数据同步服务端]只能运行一个!"));
warningBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
warningBox.setStandardButtons(QMessageBox::Ok);
warningBox.exec();
::CloseHandle(mutex);
return 0;
}
else {
::ReleaseMutex(mutex);
}
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.lpDesktop = (LPWSTR)L"winsta0\\default";
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessAsUser(hToken, NULL, qApp->applicationFilePath().toStdWString().data(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
QMessageBox::warning(nullptr, QStringLiteral("错误"), QStringLiteral("创建进程失败!"));
CloseHandle(hToken);
return -1;
}
CloseHandle(hToken);
return 0;
}
```
代码中,我们首先调用 WTSGetActiveConsoleSessionId 函数获取当前活动的控制台会话的标识符,然后使用 WTSQueryUserToken 函数获取该控制台会话的用户令牌。
接着,我们使用 CreateProcessAsUser 函数创建新的进程,其中将用户令牌作为参数传递给该函数,以便在当前用户会话下创建新进程。
最后,我们需要记得关闭用户令牌的句柄,释放资源。
阅读全文