Reputation: 4454
For my app to function properly and display running processes, it requires elevated permissions. I embed the manifest file for this purpose using the mt.exe
tool.
If I make changes to the code and rebuild, I would have to reuse the manifest tool to embed the manifest into the new executable. How can I embed the manifest into the executable during the build process in 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 (command prompt; path: c:\Program Files (x86)\Windows Kits\10\bin<VER>\x64\mt.exe):
mt.exe -manifest display_running_processes.manifest -outputresource:display_running_processess.exe;1
Resource.h
#pragma once
#define IDD_DIALOG1 101
#define ID_LISTBOX 1001
#define IDOK 1
#define IDCANCEL 2
Resource.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;
}
Upvotes: 0
Views: 152
Reputation: 33754
manifest this is only resouce in your PE. so correct solution - include direct it in .rc file. not need any external tools, like mt.exe
we can add next line to Resource.rc:
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "display_running_processes.manifest"
(this is in case exe, if you have dll - use ISOLATIONAWARE_MANIFEST_RESOURCE_ID
instead CREATEPROCESS_MANIFEST_RESOURCE_ID
)
also possible not direct include this line to Resource.rc, because it autogenerated by VS, but add it to *.rc2
file
using the Resource Includes dialog box
add in Compile-time directives: box .rc2
file and in this file put line
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "display_running_processes.manifest"
this file never auto edited my VS
also in this case you need set /MANIFEST:NO
for linker (Linker > Manifest File
tab) and Embed Manifest: No
for Manifest Tool > Input and Output
Upvotes: 0