使用 PngBitmapEncoder 的 RenderTargetBitmap 在没有显示时在虚拟机上生成空白图像,Windows 10 版本 1903

RenderTargetBitmap using a PngBitmapEncoder is generating blank images on a virtual machine when there is no display, Windows 10 Version 1903

我们的 .NET 应用程序能够生成 .png 文件,这些文件是 WPF 的屏幕截图 Canvas。

这可以从客户端触发并由我们的另一个应用程序处理(本质上是将作业外包给它排队和处理的东西)可以留在另一台机器上 运行,这是然后负责截图。

这个功能很好用,已经用了很长时间了。这包括在 VM 上,即使没有人连接到该机器,即没有呈现显示。我们没有对代码进行任何更改。

但是,自Windows10 Version 1903(2019年5月更新)以来,如果在无人连接的虚拟机上生成屏幕截图,则生成的屏幕截图始终为空白。如果您当前已连接到 VM,则它工作正常。我们还在更新 1909 和 2004 上重现了这个问题。

我们得到的结果是一个大小正确的完全透明的 .png。

我已经远程调试了创建屏幕截图的虚拟机,没有明显不正确的地方 - 所有属性(如高度、宽度和可见性)都是正确的。没有抛出异常。

我们认为这一定与没有可以访问的显示或类似的东西有关。然而,奇怪的是,这曾经工作得很好,所以尽管我们的代码保持不变,但我们对 Windows 更新之间可能发生的变化感到困惑。

有没有其他人遇到过这个问题或类似问题并设法解决了它?我知道不完全支持在服务中使用 WPF - 这个用例是否交叉到那个用例,因为应用程序在技术上在创建渲染时没有显示?

这里是我们代码的精简示例,供参考:

' A method that ensures all contents of the canvas has been loaded in, then sets the canvases height and width based on its children, 
' ensuring that it is layed out fully in preperation for the screenshot
  theCanvas.UpdateSize()

Try

    Dim renderBitmap As New RenderTargetBitmap(CInt(theCanvas.Width), CInt(theCanvas.Height), 96.0, 96.0, PixelFormats.Pbgra32)
    renderBitmap.Render(theCanvas)

    Dim directoryPath as String = Path.GetDirectoryName(saveLocation)
    Directory.CreateDirectory(directoryPath)

    Using outStream as New FileStream(saveLocation, FileMode.OpenOrCreate)

        Dim encoder As New PngBitmapEncoder()
        encoder.Frames.Add(BitmapFrame.Create(renderBitmap))

        encoder.Save(outStream)
    End Using

Catch ex as IOException
    ...
End Try

我们找出问题所在。

Microsoft fixed a Windows issue 于 2017 年发布了默认行为,其中名为 ShouldRenderEvenWhenNoDisplayDevicesAreAvailable 的设置将设置为 False。显然,这意味着在我们的用例中,WPF 没有呈现任何内容,因为技术上没有可用的显示设备。

将以下内容添加到我们应用程序的 app.config 文件中可以解决问题:

<runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Media.ShouldNotRenderInNonInteractiveWindowStation=false;Switch.System.Windows.Media.ShouldRenderEvenWhenNoDisplayDevicesAreAvailable=true" />
</runtime>