使用Win32 API(C#pInvoke)拍摄不在IIS中工作的屏幕截图

使用Win32 API(C#pInvoke)拍摄不在IIS中工作的屏幕截图,c#,asp.net-mvc,windows,winapi,iis,C#,Asp.net Mvc,Windows,Winapi,Iis,我想拍一张外部网站的截图。 目前,我的工作流程是使用指定的URL启动Firefox实例,并在Win32 API中使用PrintWindow截图 当我在IISExpress中运行此应用程序时,它工作正常,但当我在windows VPS上的IIS中运行相同的应用程序时,它不工作(屏幕截图为空白) 我不知道我做错了什么 我的代码: using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Di

我想拍一张外部网站的截图。 目前,我的工作流程是使用指定的URL启动Firefox实例,并在Win32 API中使用PrintWindow截图

当我在IISExpress中运行此应用程序时,它工作正常,但当我在windows VPS上的IIS中运行相同的应用程序时,它不工作(屏幕截图为空白)

我不知道我做错了什么

我的代码:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using System.Web;

namespace WebTools.Web
{
    public class RemoteScreenshot
    {
        public static Bitmap TakeScreenshot(Process process)
        {
            // may need a process Refresh before
            return TakeScreenshot(process.MainWindowHandle);
        }

        public static Bitmap TakeScreenshot(IntPtr handle)
        {
            RECT rc = new RECT();
            GetWindowRect(handle, ref rc);

            Bitmap bitmap = new Bitmap(rc.right - rc.left, rc.bottom - rc.top);

            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                PrintWindow(handle, graphics.GetHdc(), 0);
            }

            return bitmap;
        }

        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);

        [DllImport("user32.dll")]
        private static extern bool PrintWindow(IntPtr hWnd, IntPtr hDC, int flags);

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        public static void Save(string url, string file, int timeout = 0)
        {
            var proc = Process.Start(new ProcessStartInfo("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe", url)
            {
                CreateNoWindow = false,
                WindowStyle = ProcessWindowStyle.Maximized
            });

            Thread.Sleep(timeout);

            var bitmap = TakeScreenshot(proc);

            bitmap.Save(file, ImageFormat.Png);
            bitmap.Dispose();

            proc.Kill();
        }
    }
}

编辑:运行Firefox工作正常,因为AppPool位于另一个有权执行Firefox的帐户下

使用IIS您无法拍摄屏幕截图,因为它在Windows server的NetworkService帐户下工作

IIS服务无权访问服务器桌面。IIS中的ASP.NET代码正在服务器端运行。它将试图捕获服务器的屏幕,但被拒绝

您将需要使用在客户端计算机上运行代码的silverlight。 以下链接可能会有所帮助:


由于安全原因,在浏览器中使用网页的用户可能需要提供权限。

您正在拍摄哪个屏幕的截图

如果应用程序在笔记本电脑上运行,它将绘制到物理显示适配器上。如果它在RDP会话结束时在一台机器上运行,它将绘制到一个虚拟显示适配器,并且图像将通过线路发送

但如果应用程序在非交互式会话中运行,则不会显示。所以什么都不画


没有要捕获的屏幕位图。

它怎么不工作?它会引发异常吗?很有可能你碰到了一个代码访问边界,它抛出了一个错误UnauthorizedException@SimonWhitehead我使用用户标识运行apppool。我最终在位图构造函数部分遇到ArgumentException,因为无法计算屏幕的宽度和高度,但当我将其设置为1600x900时,它也不起作用。您需要添加一些日志记录。将要传递的值记录到位图构造函数中。我知道传递的值是0和0,因为“GetWindowRect”函数返回该值。但是,当我将1600x900传递给构造函数时,会得到一个空白映像。您确定运行IIs池时使用的用户帐户已正确初始化,并且具有正确的用户配置文件(想想%USERPROFILE%)等等吗?我认为Firefox需要一个用户配置文件才能正常工作。我可以这样做,因为我正在使用IIS中的“用户标识”设置,在NetworkService帐户以外的其他帐户下运行应用池。IIS服务可能是非交互式的,子进程将继承它。我在windows server上遇到类似问题,当我在时间内找不到合适的解决方案时,我最终编写了一个托管在控制台应用程序上的WCF服务,因为它甚至在windows服务中也不工作。我不想使用Silverlight,因为它在本地工作,我相信在一些帮助下,我可以使它在线工作;)无论如何都不会从服务器端捕获客户端屏幕。请查看我编辑过的答案。我100%确信我可以让它工作,我创建的用户有打开Firefox的权限,我可以使用Win32 API捕获屏幕以制作Firefox浏览器的屏幕截图。嗯,该应用程序正在CloudVPS的虚拟专用服务器上运行。但是,有没有办法让会话具有交互性呢?@DillenMeijboom如果你使用XP,你可能会侥幸逃脱,但Vista和以后会尽量避免交互性:@ta.speot.is我会看一看,我目前在我的VPS上运行Windows 8 server。