Skip to content

Instantly share code, notes, and snippets.

@valinet

valinet/README.md

Last active Oct 13, 2020
Embed
What would you like to do?
Fix Task Manager blurriness on different DPI monitors in Windows 10

Fix Task Manager blurriness on different DPI monitors in Windows 10

Task Manager on Windows 10 is blurry on secondary monitors if they have a different DPI from the primary monitor. This is because Task Manager is only PROCESS_SYSTEM_DPI_AWARE, despite being a relatively new application (a new Task Manager was introduced in Windows 8). This can be confirmed by using a tool such as Resource Hacker and checking the manifest file for this:

<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true</dpiAware>
    <autoElevate>true</autoElevate>
</asmv3:windowsSettings>

Task Manager draws its contents using good old GDI. Fortunately, recent Windows 10 versions provide tremendous improvements regarding scaling for GDI apps. This scaling method, which produces really good results (blur is significantly reduced to the artificial zooming that is done to regular DPI unaware applications), can be applied automatically by the system and is transparent to the application that receives the treatment. One of the techniques that is applied with this method consists in using different font sizes for text displayed by GDI apps, the size being scaled proportional to the difference in DPI between the screen and a 100% scaled display. Because there can't always be a 1:1 mapping between scaling levels and font sizes, some artifacts, like kerning around fonts, may appear. You can read more about how GDI scaling works here.

GDI scaling can be set for applications using the Compatibility tab of the executable's Properties. Unfortunately, for system apps, neither the Compatibility settings are available in the UI, nor are the settings respected if specified via the Registry. Another solution that we could try is editing the embedded manifest within the executable manually, using Resource Hacker, specifying the following tag in asmv3:windowsSettings:

<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>

Unfortunately, if we replace the original Task Manager in system32 with the modified run, the new executable does not launch, and Windows prompts us like this:

I haven't found a way to disable that. It does not happen for all system apps though, plus I try to avoid patching system binaries, because modifications may be reverted on system updates, and I do not want to repatch all the time. When I have to patch, I try to maintain the patch at a minimum, and also don't want to disable security protections.

Fortunately, there is another way to enforce the manifest: there is a registry setting that allows telling Windows to prefer external manifests first, and then resort to embedded manifests. The default behavior is the opposite. So, go to this key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide

Create a new DWORD (32-bit) value called PreferExternalManifest and set its value to 1. Now, copy the text bellow to a file named Taskmgr.exe.manifest, and copy that to C:\Windows\System32. The file is generated by extracting the manifest from Taskmgr.exe, and then appling the GDi scaling tag as well in the asmv3:windowsSettings section. Now, launch Task Manager and voila, it scales with GDI scaling properly on all high DPI and regular DPI displays. The setting in the manifest file is equivalent to the "System (Enhanced)" setting in the Compatibility tab. Enjoy!

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
<assemblyIdentity
    processorArchitecture="amd64"
    version="5.1.0.0"
    name="Microsoft.Windows.Diagnosis.AdvancedTaskManager"
    type="win32"
/>
<description>Task Manager</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="amd64"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
        <requestedPrivileges>
            <requestedExecutionLevel
                level="highestAvailable"
            />
        </requestedPrivileges>
    </security>
</trustInfo>
<asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
	    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
        <gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>
        <autoElevate>true</autoElevate>
    </asmv3:windowsSettings>
</asmv3:application>
</assembly>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment