You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows Forms高DPI缩放适配问题求助:单独运行EXE时缩放方案失效

Troubleshooting WinForms Scaling Issues When Running EXE Alone

Let's break down your problem: you've configured high-DPI scaling for your WinForms app, but it only works in Visual Studio debug mode or when the EXE is placed alongside its manifest and config files. When running the EXE alone (without those files) or dynamically loading Monitor.dll to launch a form, the scaling breaks entirely. Here are targeted troubleshooting steps to fix this:

1. Embed Manifest and Config Files Into Your EXE/DLL

The root issue here is that your scaling settings are tied to external files, not baked into your executable. When you run the EXE alone, it can't find those files, so the scaling rules don't apply.

  • For the Manifest: In Visual Studio, right-click your project → Properties → Application. Under "Manifest", select "Embed manifest with default settings" and edit the manifest to include proper DPI awareness tags. For modern per-monitor scaling, add:
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
      <windowsSettings>
        <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
      </windowsSettings>
    </application>
    
  • For the Config File: If your scaling relies on app.config, go to project properties → Build → Output, and configure the config to be embedded as a resource. Alternatively, you can load the config dynamically in code using ConfigurationManager.OpenExeConfiguration.

If you're dynamically loading Monitor.dll, make sure the DLL itself has the embedded manifest/config, not just the main EXE.

2. Set DPI Awareness Via Code (No External Files Needed)

If embedding the manifest isn't working, you can force DPI awareness directly in your code using Windows APIs. This bypasses the need for external manifest files entirely.

Add these declarations to your VB.NET code, and call the setup method before creating any forms or threads:

Imports System.Runtime.InteropServices
Imports System.Diagnostics

Public Module DpiHelper
    <DllImport("shcore.dll", SetLastError:=True)>
    Private Function SetProcessDpiAwareness(awareness As Integer) As Integer
    End Function

    Public Sub EnablePerMonitorDpi()
        ' 2 = PROCESS_PER_MONITOR_DPI_AWARE (Windows 10 1607+)
        SetProcessDpiAwareness(2)
    End Sub
End Module

Then, in your main program's entry point (or right before starting the Monitor thread), call:

DpiHelper.EnablePerMonitorDpi()

3. Fix Context for Dynamically Loaded DLLs

When you load Monitor.dll using Assembly.Load(File.ReadAllBytes(...)), the DLL runs in the context of your main EXE's working directory—not the DLL's own directory. This means it can't find any manifest/config files in its folder.

Adjust your loading code to switch the working directory temporarily:

Private Sub ShowMonitor()
    Dim dllPath = "path to folder with DLL files\Monitor.dll"
    Dim originalWorkingDir = Environment.CurrentDirectory

    Try
        ' Switch to the DLL's directory
        Environment.CurrentDirectory = Path.GetDirectoryName(dllPath)
        
        Dim frMonitor As Assembly = Assembly.Load(File.ReadAllBytes(dllPath))
        Dim oType As Type = frMonitor.GetType("Monitor.frmMonitor")
        Dim pControl As Object = Activator.CreateInstance(oType)
        Application.Run(pControl)
    Finally
        ' Restore original working directory
        Environment.CurrentDirectory = originalWorkingDir
    End Try
End Sub

4. Verify DPI Awareness Status

To confirm if your DPI settings are actually taking effect, add code to check the current process's DPI awareness level. This helps you rule out whether the issue is with applying the setting or something else.

Add this API declaration and check method:

<DllImport("shcore.dll", SetLastError:=True)>
Private Function GetProcessDpiAwareness(hProcess As IntPtr, ByRef awareness As Integer) As Integer
End Function

Public Sub CheckDpiAwareness()
    Dim awarenessLevel As Integer
    GetProcessDpiAwareness(Process.GetCurrentProcess().Handle, awarenessLevel)
    
    ' Interpret the result:
    ' 0 = DPI unaware
    ' 1 = System DPI aware
    ' 2 = Per-monitor DPI aware
    Debug.WriteLine($"Current DPI Awareness Level: {awarenessLevel}")
End Sub

Call CheckDpiAwareness() right after launching your app. If it returns 0 when running the EXE alone, your DPI settings aren't being applied—go back to steps 1 or 2 to fix that.

5. Ensure Main EXE Has Proper DPI Settings

Remember that DPI awareness is a process-level setting. Even though you're launching the Monitor form from a DLL, the main EXE's DPI configuration will affect all threads and forms in the process. Make sure your main EXE has the correct manifest or code-based DPI setup first.

内容的提问来源于stack exchange,提问作者Sphinx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:04:06