Background
In Windows, applications can use the app.manifest
asset file to configure the role permissions used when the program is launched.
The effect is as follows:
Under normal circumstances, adding the following configuration to app.manifest
is sufficient:
If the project does not have this file, you can create a new item - Manifest File in the project.
<trustInfo xmlns='urn:schemas-microsoft-com:asm.v2'>
<security>
<requestedPrivileges xmlns='urn:schemas-microsoft-com:asm.v3'>
<requestedExecutionLevel level='requireAdministrator' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
However, in MAUI applications, it cannot be added. If attempted, an error occurs.
Platforms\Windows\app.manifest : manifest authoring error c1010001: Values of attribute "level" not equal in different manifest snippets.
This is because the .NET compiler already generates a default app.manifest
file that includes the trustInfo
configuration.
If the project has <WindowsAppSDKSelfConatined>true</WindowsAppSDKSelfConatined>
enabled, you should check the Microsoft.WindowsAppSDK.SelfContained.targets
file:
Therefore, if you want to customize app.manifest
, you either need to modify Microsoft.WindowsAppSDK.SelfContained.targets
, which is not ideal.
Customizing the Build Process
If you observe the build process, you will find that the manifest
file is generated in the obj
directory.
Here, mergeapp.manifest
is the app.manifest
from the project, renamed by the .NET compiler during the build process.
During the build, the default app.manifest
is generated first from Microsoft.WindowsAppSDK.SelfContained.targets
. Then, the developer's app.manifest
is copied to mergeapp.manifest
, which is subsequently merged into app.manifest
.
If the configuration already exists in app.manifest
, then the duplicate records in mergeapp.manifest
will lead to compilation errors.
Since we understand the build process, we can manipulate it.
We can replace the configuration in app.manifest
after it has been generated but before the main program is compiled, using the following command:
powershell -Command "(gc app.manifest) -replace 'level=''asInvoker''', 'level=''requireAdministrator''' | Out-File -encoding ASCII app.manifest";
The steps used by MSBuild during compilation can refer to the official documentation:
https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-targets?view=vs-2022
During compilation, there are two important environment variables:
_DeploymentManifestFiles
: Directory where the manifest files are located;
ApplicationManifest
: Path of the app.manifest
file.
You can add the following script in the .csproj
file, which will automatically modify the manifest file during the program compilation.
<Target Name="RequireAdministrator" BeforeTargets="GenerateManifests" Condition="'$(PublishDir)' != ''">
<Exec WorkingDirectory="./" Command="echo $(ApplicationManifest)" />
<Exec WorkingDirectory="./" Command="echo $(_DeploymentManifestFiles)" />
<Exec WorkingDirectory="$(_DeploymentManifestFiles)" Command="dir" />
<Exec WorkingDirectory="$(_DeploymentManifestFiles)" Command="powershell -Command "(gc app.manifest) -replace 'level=''asInvoker''', 'level=''requireAdministrator''' | Out-File -encoding ASCII app.manifest"" />
</Target>
BeforeTargets="GenerateManifests"
indicates that the custom command is executed before GenerateManifests
.
Condition="'$(PublishDir)' != ''"
indicates the trigger condition. In MAUI, this variable only exists when publishing, but it could be modified to Condition="'$(Release)' != ''"
.
Note that in some cases, the _DeploymentManifestFiles
directory may not exist, so multiple tests might be needed.
Of course, the safest method:
<Target Name="RequireAdministrator" BeforeTargets="GenerateManifests" Condition="'$(PublishDir)' != ''">
<Exec WorkingDirectory="./" Command=" powershell -Command "(gc $(ApplicationManifest)) -replace 'level=''asInvoker''', 'level=''requireAdministrator''' | Out-File -encoding UTF8 $(ApplicationManifest)"" />
</Target>
The build process mainly consists of the following three steps, where only GenerateManifests
can be used in .csproj
.
<Target Name="GenerateManifests"
Condition="'$(GenerateClickOnceManifests)'=='true' or '@(NativeReference)'!='' or '@(ResolvedIsolatedComModules)'!='' or '$(GenerateAppxManifest)' == 'true'"
DependsOnTargets="$(GenerateManifestsDependsOn)"/>
===================================================
GenerateApplicationManifest
Generates a ClickOnce or native application manifest.
An application manifest specifies declarative application identity, dependency and security information.
===================================================
<Target Name="GenerateApplicationManifest"
DependsOnTargets="
_DeploymentComputeNativeManifestInfo;
_DeploymentComputeClickOnceManifestInfo;
ResolveComReferences;
ResolveNativeReferences;
_GenerateResolvedDeploymentManifestEntryPoint"
Inputs="
$(MSBuildAllProjects);
@(AppConfigWithTargetPath);
$(_DeploymentBaseManifest);
@(ResolvedIsolatedComModules);
@(_DeploymentManifestDependencies);
@(_DeploymentResolvedManifestEntryPoint);
@(_DeploymentManifestFiles)"
Outputs="@(ApplicationManifest)">
The following parameters can be retrieved:
$(_DeploymentBaseManifest);
@(ResolvedIsolatedComModules);
@(_DeploymentManifestDependencies);
@(_DeploymentResolvedManifestEntryPoint);
@(_DeploymentManifestFiles)
@(ApplicationManifest)
文章评论