如何使用 VS2022 将清单嵌入到 C++/WinAPI 应用程序中?

问题描述 投票:0回答:1

为了让我的应用程序正常运行并显示正在运行的进程,它需要提升的权限。为此,我使用

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\x64\mt.exe):

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;
}
c++ winapi visual-studio-2022 manifest elevated-privileges
1个回答
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

© www.soinside.com 2019 - 2024. All rights reserved.