关于java:计算机锁定时是否可以通过编程方式截取屏幕截图?

Is it possible to programmatically take a screenshot while the computer is locked?

我正在隔夜运行Selenium测试(使用Java和WebDriver),并且想在其中一个测试用例失败时拍摄屏幕截图。如果我使用Robot的createScreenCapture()方法,则只有在显示器打开的情况下它才起作用;如果我使用Selenium的getScreenshotAs()方法,它不会捕获任何弹出窗口或窗口顶部的任何内容(通常包含原因)问题)。 getScreenshotAs()方法在PC锁定时确实有效,这就是我当前正在使用的方法。如果这很重要,我的机器将运行Windows 7。

我修改了此代码(可在本网站找到),目前正在使用它:

1
2
3
4
5
WebDriver driver = new FirefoxDriver();
driver.get("http://www.google.com/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));

这是我以前使用过的,但是如果PC被锁定,它只会捕获灰色屏幕,并且任务栏位于底部,但是如果我登录,它会很好地工作并捕获所有内容。问题是我需要整夜锁定计算机,也就是在这段代码需要运行时:

1
2
3
4
5
6
7
Robot robot = new Robot();
// Get size of screen
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
// Capture the screen
BufferedImage screenFullImage = robot.createScreenCapture(screenRect);
// Save the screen to to disk
ImageIO.write(screenFullImage,"jpg", new File(fileName));

我在这里发现了其他一些帖子,它们在问类似的问题,但是它们都已经很老了,与我的问题不太吻合,所以我想知道在这些情况下是否有解决方案?

编辑:
当我使用机器人代码时,这些就是结果。我尝试使用Chrome作为浏览器(ChromeDriver)和Firefox(FirefoxDriver)。

铬:
Screenshot Using Google Chrome

Firefox:
enter image description here

如果我仅自己在一个类中运行屏幕截图的机器人版本,那么就只是一个每5秒捕获一次屏幕的循环("运行方式"> Java应用程序),即使锁定了计算机,它也可以正常工作,但是当我拥有Selenium时如果测试失败,则运行相同的代码(其运行方式> JUnit测试),如果电脑被锁定,则会给出上面的屏幕截图。我什至尝试过让Selenium代码生成一个新线程来拍摄屏幕快照,而它却执行了Thread.sleep()动作,但是一旦电脑被锁定,结果还是一样。


On a personal desktop, locking screen should not be an issue in capturing screen using AWT Robot.

您可以使用脚本ScreenCapture.java对其进行测试

  • 将Java文件下载到文件夹中。
  • 在下载文件的文件夹中打开cmd
  • javac ScreenCapture.java
  • java ScreenCapture

您应该看到屏幕快照在文件夹中循环捕获。锁定屏幕,等待5秒钟,然后解锁屏幕并检查屏幕截图

In case of a virtual machine or a remote computer which is accessed via RDP, locking can result in black screenshots.

当用户正常访问桌面时(如笔记本电脑或个人计算机,没有RDP),则将用户会话设置为控制台。您可以使用以下命令查看它。

1
2
3
c:\Users\*******\Desktop>query user
USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
>*********              console             1  Active      none   12/18/2018 5:50 PM

您可以看到用户已连接到会话console。在此模式下,捕获屏幕截图可以完美运行。

但是,如果您使用RDP访问桌面,则会看到以下结果。

1
2
3
4
5
6
7
8
9
c:\Users\*******\Desktop>FOR /L %N IN () DO (query user
timeout 2)

 // When the screen is locked (RDP closed)
 USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
>*********                                  1  Disc            .  8/21/2018 12:25 PM
 // When RDP session is active
 USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
>*********              rdp-tcp#0           1  Active       none  8/21/2018 12:25 PM

您可以看到,当RDP会话断开连接时,没有活动的会话。结果是空白的屏幕截图

Solution

当RDP关闭时,您必须使用以下命令激活console会话。这可以通过设置计划任务来完成。

  • 创建具有以下内容的批处理文件。

    1
    Tscon 1 /dest:console /v
  • 通过打开Run并键入taskschd.msc来打开任务计划程序。
  • Action menu中,单击Create Task
  • 给任务起个名字
  • 选择Run whether user is logged in or not复选框
  • Triggers选项卡中,单击New按钮
  • 选择On disconnect from user session,然后单击OK
  • Actions选项卡中,单击New按钮
  • 操作Start a program并指向批处理文件的位置,然后单击OK
  • 单击OK创建任务

  • 当然,您可以在使用浏览器锁定PC时截取屏幕截图-

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static String captureScreen(WebDriver driver, String screenName) throws IOException {
        String dest = null;
        try {
            Screenshot screenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000)).takeScreenshot(driver);
            dest = ScreenshotsPath() +"\" + screenName +".png";
            ImageIO.write(screenshot.getImage(),"
    PNG", new File(dest));
        } catch (Exception e) {
            e.printStackTrace(writeException.toFile());
        }
        return dest;
    }

    我的方法以字符串形式返回destination(图像的路径),因为我在报表中使用了它们。我还使用AShot(),因为我想拍摄整页的屏幕截图。

    谢谢,