【问题标题】:Is it possible to programmatically take a screenshot while the computer is locked?是否可以在计算机锁定时以编程方式截取屏幕截图?
【发布时间】:2019-05-19 10:46:35
【问题描述】:

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

我修改了这段代码(在这个网站上找到)并且目前正在使用它:

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"));

这是我以前使用过的,但如果电脑被锁定,它只会捕获一个灰色屏幕,底部的任务栏,但如果我登录它,它工作得很好并且可以捕获所有内容。问题是我需要将我的计算机锁定一夜,而这正是这段代码需要运行的时候:

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)。

铬:

火狐:

如果我在一个类中单独运行机器人版本的屏幕截图,只是一个每 5 秒捕获一次屏幕的循环(运行方式 > Java 应用程序),即使计算机锁定它也能正常工作,但是当当测试失败时,我让 Selenium 运行相同的代码(其运行方式 > JUnit 测试),如果 pc 被锁定,它会给出上面的屏幕截图。我什至尝试让 Selenium 代码在执行Thread.sleep() 时生成一个新线程来截取屏幕截图,但在电脑锁定后得到相同的结果。

【问题讨论】:

  • 这很奇怪,它捕捉到正确的快照,无论屏幕是锁定还是解锁
  • Carlos:这是在计算机被锁定时发生的,但是当电脑没有被锁定时这是一个好主意,谢谢

标签: java selenium selenium-webdriver automated-tests


【解决方案1】:

在个人桌面上,锁定屏幕不应该是使用 AWT Robot 捕获屏幕的问题。

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

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

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

如果是通过 RDP 访问的虚拟机或远程计算机,锁定可能会导致黑屏。

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

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 访问桌面,您会看到以下结果。

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 会话断开连接时,没有处于活动状态的会话。这导致空白屏幕截图

解决方案

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

  1. 创建一个包含以下内容的批处理文件。

    Tscon 1 /dest:console /v
    
  2. 通过打开Run 并输入taskschd.msc 打开任务计划程序
  3. Action menu 中,单击Create Task
  4. 为任务命名
  5. 选中Run whether user is logged in or not复选框
  6. Triggers 选项卡中,单击New 按钮
  7. 选择On disconnect from user session并点击OK
  8. Actions 选项卡中,单击New 按钮
  9. 操作Start a program并指向批处理文件的位置并单击OK
  10. 点击OK创建任务

【讨论】:

  • 我使用的是个人桌面,但仍然很高兴知道 RDP 信息,所以谢谢你。不幸的是,您发布链接的代码是我尝试使用的确切代码,但我认为这可能是与 Selenium 或其他东西的某种兼容性问题,我在我的问题中添加了更多内容,更好地解释了我有什么尝试了结果,所以我不会在这里重写它,但再次感谢你。同样仅供参考,ScreenCapture.java 脚本会截取 1 个屏幕截图,并每 2 秒使用新文件名制作同一屏幕截图的新副本,但我明白你在说什么。
  • 我已经更新了java文件。感谢那。我将发布另一个答案,详细说明涉及命令行的调试策略,以调试屏幕锁定时会话是否处于活动状态
【解决方案2】:

当然,你可以在电脑被浏览器锁定时截屏 -

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;
}

我的方法将目的地(图像的路径)作为字符串返回,因为我在报告中使用它们。我也在使用 AShot(),因为我想截取整页截图。

谢谢,

【讨论】:

  • 这似乎与我目前使用的(TakesScreenshot.getScreenshotAs())非常相似,似乎如果它使用浏览器它不会捕获任何弹出窗口或警报或类似的东西。本质上,我想捕捉如果显示器打开,我会看到什么。你的方式能捕捉到那种东西吗?我通常会尝试看看,但你的方式涉及安装一个新的 .jar,这在工作中有点棘手(获得许可等等)。
  • 该方法只会截取浏览器的活动窗口。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2012-01-31
  • 1970-01-01
相关资源
最近更新 更多