为了让我的应用程序正常运行并显示正在运行的进程,它需要提升的权限。为此,我使用
mt.exe
工具嵌入清单文件。
如果我对代码进行更改并重建,我将不得不重用清单工具将清单嵌入到新的可执行文件中。如何在 Visual Studio 2022 的构建过程中将清单嵌入到可执行文件中?
display_running_processes.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
mt.exe(命令提示符;路径:c:\Program Files (x86)\Windows Kits in
mt.exe -manifest display_running_processes.manifest -outputresource:display_running_processess.exe;1
资源.h
#pragma once
#define IDD_DIALOG1 101
#define ID_LISTBOX 1001
#define IDOK 1
#define IDCANCEL 2
资源.rc
#include <Windows.h>
#include "resource.h"
IDD_DIALOG1 DIALOGEX 0, 0, 600, 200
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Process List"
FONT 8, "MS Shell Dlg"
BEGIN
LISTBOX ID_LISTBOX, 10, 10, 580, 150, LBS_NOTIFY | WS_VSCROLL | WS_BORDER | WS_TABSTOP
DEFPUSHBUTTON "OK", IDOK, 50, 170, 50, 14
PUSHBUTTON "Cancel", IDCANCEL, 110, 170, 50, 14
END
WinMain.cpp
#include <windows.h>
#include <psapi.h>
#include <tchar.h>
#define ID_LISTBOX 1001
#define IDD_DIALOG1 101
#define IDOK 1
#define IDCANCEL 2
void PopulateProcessList(HWND hwndListBox) {
DWORD processes[1024], cbNeeded;
if (EnumProcesses(processes, sizeof(processes), &cbNeeded)) {
int numProcesses = cbNeeded / sizeof(DWORD);
for (int i = 0; i < numProcesses; ++i) {
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
if (hProcess) {
if (GetModuleFileNameEx(hProcess, NULL, szProcessName, MAX_PATH)) {
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szProcessName);
}
else {
DWORD error = GetLastError();
TCHAR szError[MAX_PATH];
_stprintf_s(szError, TEXT("GetModuleFileNameEx error %lu"), error);
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szError);
}
CloseHandle(hProcess);
}
else {
DWORD error = GetLastError();
if (error == ERROR_ACCESS_DENIED) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processes[i]);
if (hProcess) {
if (GetProcessImageFileName(hProcess, szProcessName, MAX_PATH) > 0) {
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szProcessName);
}
else {
_stprintf_s(szProcessName, TEXT("PID %u: Access Denied, Unable to get name"), processes[i]);
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szProcessName);
}
CloseHandle(hProcess);
}
else {
_stprintf_s(szProcessName, TEXT("PID %u: Access Denied"), processes[i]);
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szProcessName);
}
}
else {
TCHAR szError[MAX_PATH];
_stprintf_s(szError, TEXT("OpenProcess error %lu"), error);
SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)szError);
}
}
}
}
else {
MessageBox(hwndListBox, TEXT("Failed to enumerate processes"), TEXT("Error"), MB_OK | MB_ICONERROR);
}
}
INT_PTR CALLBACK DialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
{
HWND hwndListBox = GetDlgItem(hwndDlg, ID_LISTBOX);
PopulateProcessList(hwndListBox);
}
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
return 0;
}
表明这只是您的 PE 中的资源。所以正确的解决方案 - 将其直接包含在 .rc 文件中。不需要任何外部工具,例如 mt.exe
我们可以将下一行添加到 Resource.rc:
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "display_running_processes.manifest"
(这是在 exe 的情况下,如果你有 dll - 使用
ISOLATIONAWARE_MANIFEST_RESOURCE_ID
代替 CREATEPROCESS_MANIFEST_RESOURCE_ID
)
也可能不直接将此行包含到Resource.rc,因为它是由VS自动生成的,而是将其添加到
*.rc2
文件
添加编译时指令:框
.rc2
文件,并在此文件中放置行
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "display_running_processes.manifest"
这个文件从未自动编辑过我的 VS