Java 是否可以在计算机锁定时以编程方式拍摄屏幕截图?

Java 是否可以在计算机锁定时以编程方式拍摄屏幕截图?,java,selenium,selenium-webdriver,automated-tests,Java,Selenium,Selenium Webdriver,Automated Tests,我通宵运行Selenium测试(使用Java和WebDriver),并希望在其中一个测试用例失败时截图。如果我使用Robot的createScreenscapture()方法,它只在监视器打开时工作,如果我使用Selenium的getScreenshotAs()方法,它不会捕获任何弹出窗口或窗口顶部的任何内容(通常包含问题的原因)。当电脑被锁定时,getScreenshotAs()方法会起作用,因此我目前正在使用该方法。如果有必要的话,我的机器运行Windows7 我修改了此代码(在本网站上找到

我通宵运行Selenium测试(使用Java和WebDriver),并希望在其中一个测试用例失败时截图。如果我使用Robot的
createScreenscapture()
方法,它只在监视器打开时工作,如果我使用Selenium的
getScreenshotAs()
方法,它不会捕获任何弹出窗口或窗口顶部的任何内容(通常包含问题的原因)。当电脑被锁定时,
getScreenshotAs()
方法会起作用,因此我目前正在使用该方法。如果有必要的话,我的机器运行Windows7

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

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)

铬:

Firefox:

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

在个人桌面上,使用AWT Robot捕获屏幕时,锁定屏幕不应成为问题

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

  • 将java文件下载到一个文件夹中
  • 在下载文件的文件夹中打开cmd
  • javac屏幕截图.java
  • java截屏
你应该看到截图在文件夹中的一个循环中被捕获。锁定屏幕,等待5秒钟,然后解锁屏幕并检查屏幕截图

对于通过RDP访问的虚拟机或远程计算机,锁定可能会导致黑色屏幕截图

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

c:\Users\*******\Desktop>query user
USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
>*********              console             1  Active      none   12/18/2018 5:50 PM 
您可以看到用户已连接到会话
控制台
。在这种模式下,捕获屏幕截图可以完美地工作

但是如果您使用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关闭时,您必须使用以下命令激活
控制台
会话。这可以通过设置计划任务来完成

  • 创建包含以下内容的批处理文件

    Tscon 1 /dest:console /v
    
  • 通过打开
    Run
    并键入
    taskschd.msc
  • 操作菜单中
    ,单击
    创建任务
  • 给任务命名
  • 选择
    无论用户是否登录都运行
    复选框
  • 触发器
    选项卡中,单击
    新建
    按钮
  • 在断开与用户会话的连接时选择
    ,然后单击
    OK
  • 操作
    选项卡中,单击
    新建
    按钮
  • 操作
    启动程序
    并指向批处理文件的位置,然后单击
    确定
  • 单击
    OK
    创建任务

  • 当然,您可以在使用浏览器锁定电脑时拍摄屏幕截图-

    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(),因为我想拍摄一整页的屏幕截图


    谢谢,

    这很奇怪,无论屏幕是锁定还是解锁,它都捕捉到了正确的快照卡洛斯:这是在计算机锁定时发生的,但这对于电脑未锁定是个好主意,谢谢我使用的是个人桌面,但RDP信息仍然很好,谢谢。不幸的是,您发布的链接所指向的代码正是我试图使用的无法正常工作的代码,但我认为这可能是与Selenium的某种兼容性问题,我在问题中添加了更多内容,更好地解释了我所尝试的内容和结果,因此我不会在这里重写它,但再次感谢您。同样仅供参考,ScreenCapture.java脚本每2秒拍摄一个屏幕截图,并使用新文件名制作同一屏幕截图的新副本,但我理解你的意思。我已经更新了java文件。谢谢你。我将发布另一个答案,详细说明调试策略,其中涉及命令行,以调试屏幕锁定时会话是否处于活动状态。这似乎与我当前使用的非常类似(TakesScreenshot.getScreenshotAs()),似乎如果它使用浏览器,它不会捕获任何弹出窗口或警报或类似的内容。基本上,我想捕捉监视器打开时看到的内容。你的方式能捕捉到那种东西吗?我通常只是试试看,但你的方法是安装一个新的.jar,这在工作中有点棘手(获得许可等等)。这个方法只会截取浏览器活动窗口的屏幕截图。