使用 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>
我们的 .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>