如何在 C# 中捕获 Windows 应用商店应用程序的窗口内容

Posted

技术标签:

【中文标题】如何在 C# 中捕获 Windows 应用商店应用程序的窗口内容【英文标题】:How to capture window contents of a Windows Store App in C# 【发布时间】:2016-10-22 06:17:27 【问题描述】:

我有一些代码可以捕获 Windows 桌面应用程序内容并保存到 .NET 中的位图对象。它使用 User32.dll 和 Gdi32.dll (BitBlt) 并且工作得很好。但是,当我为代码提供一个包含 Windows 应用商店应用程序的窗口的句柄时,该代码会生成全黑位图。我不确定这是安全功能还是什么。我不能使用 ScreenCapture api,因为窗口的内容在调整大小后几乎总是比屏幕高/大。对于 Windows 应用商店应用程序,有没有人幸运地捕获窗口内容,即使它们比屏幕还大?

编辑:作为一个注释,我正在尝试捕获不同程序的窗口,而不是我自己的程序。我的程序可以假定为 .NET 4.6.1 / C# 中的 Windows 控制台应用程序

另外,我知道这必须在 Windows API 中以某种方式实现,因为 Aero Peek 功能,如果您将鼠标悬停在正在运行的程序图标上的任务栏上,则会显示窗口的整个高度,包括屏幕外组件。 (见右侧高窗,设置为比我的显示高出 6000 像素)

【问题讨论】:

由于赏金,我不能作为重复关闭,但你看到了吗:Capture screen of Windows store App 您拥有该应用程序吗?因为在一般情况下,如果应用程序有部分屏幕外,没有什么可以保证屏幕外的内容可以物理呈现。在一般情况下,您只能捕获屏幕上显示的内容(例如 graphics.CopyFromScreen)。 不,我不拥有该应用程序。我正在尝试从用 .NET 4.6.1 编写的控制台应用程序中捕获 Windows 商店应用程序。 看看下面提供的解决方案。 @Richtofen:运气好吗?我正在尝试从另一个应用程序获取运行 Windows 商店应用程序的屏幕截图。 【参考方案1】:

从 Windows 8.1 开始,您可以使用 Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap 将元素呈现为位图。有几点需要注意:

    您可以捕获屏幕外的元素,只要它们位于 XAML 可视化树中并且将 Visibility 设置为 Visible 而不是 Collapsed。 不会捕获某些元素,例如视频。

查看 API 了解更多详情:

https://msdn.microsoft.com/library/windows/apps/xaml/windows.ui.xaml.media.imaging.rendertargetbitmap.aspx

【讨论】:

很遗憾,我无法使用 RenderTargetBitmap,因为我无权访问应用程序的 XAML 树。我正在从一个单独的应用程序而不是我尝试捕获的应用程序运行捕获。 啊..据我所知,没有办法做到这一点。我会澄清您的问题,以明确您正在尝试从单独的应用程序中捕获窗口内容。不过祝你好运——如果可能的话,这对我来说也会很有趣。【参考方案2】:

这可能会奏效。基本上是获取应用程序的窗口句柄,调用其上的原生函数来确定应用程序窗口的位置,提供那些执行图形类并从屏幕复制的函数。

class Program

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);

    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

    public struct Rect
    
        public int Left  get; set; 
        public int Top  get; set; 
        public int Right  get; set; 
        public int Bottom  get; set; 
    


    static void Main(string[] args)
    
        /// Give this your app's process name.
        Process[] processes = Process.GetProcessesByName("yourapp");
        Process lol = processes[0];
        IntPtr ptr = lol.MainWindowHandle;
        Rect AppRect = new Rect();
        GetWindowRect(ptr, ref AppRect);
        Rectangle rect = new Rectangle(AppRect.Left, AppRect.Top, (AppRect.Right - AppRect.Left), (AppRect.Bottom - AppRect.Top));
        Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(bmp);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);

        // make sure temp directory is there or it will throw.
        bmp.Save(@"c:\temp\test.jpg", ImageFormat.Jpeg);
    

【讨论】:

因此,这可能适用于您只需要屏幕内容的情况。但是在我的情况下,我的窗口大于屏幕(屏幕高度为 2000 像素,但窗口高度/内容约为 6000 像素)。 类似于 selenium 的打印屏幕(虽然我要捕获的窗口不是 Web 浏览器)我想一次性捕获窗口内容的整个缓冲区。 啊,明白了。因此,您实际上需要需要正常滚动的应用程序的内部内容,您希望将其提取到图像中。

以上是关于如何在 C# 中捕获 Windows 应用商店应用程序的窗口内容的主要内容,如果未能解决你的问题,请参考以下文章

如何制作一个 C# Windows 窗体应用程序,为 Windows 应用商店转换,从 Windows 开始

使用 fiddler 捕获 Windows 商店应用程序流量引发异常

Windows 商店应用程序 WInRT XAML C# - 如何获取导航页面文本框值

在 Windows 10 商店应用程序 c# 中获取设备的唯一 ID

如何调试 Windows 商店应用程序崩溃?

有没有办法通过本机 C# 调用检测系统上安装了哪些 Windows 应用商店应用程序?