windows实现每天定时静默截图

windows实现每天定时截图

一直想要做一个功能来给自己的电脑每天进行一个截图操作,今天终于做好了,下面分享一下设置的过程。

方式一 借助snipaste和系统任务计划

这个是我初版的方法,后面我使用powershell脚本生成了一个exe文件,这样就就不用依赖第三方工具了,详见 方式二

使用工具

  • 任务计划程序(系统自带)

  • snipaste (手动下载)

设置snipaste

因为我之前的设置是在使用snipaste进行截图的时候将截图自动保存,所以开启了这个设置。本次要设置的定时截图功能也延续了该设置来实现截图的自动保存。

D:\systemfile\Pictures\snipaste\$yyyy$\$MM$\$yyyyMMdd_HHmmss$.png

编写截图的脚本

脚本分为两个,一个是bat脚本,用来启停snipaste、截图操作。另外一个是vbs脚本,用来在后台启动bat脚本。

snipaste.bat

@echo off & chcp 65001 >nul
:: 1. 检查 Snipaste.exe 是否正在运行 
tasklist /FI "IMAGENAME eq Snipaste.exe" 2>NUL | find /I "Snipaste.exe" >NUL
set was_running=%ERRORLEVEL%

:: 2. 如果未运行,则启动 Snipaste.exe
if %was_running% neq 0 (
    echo Snipaste.exe 未运行,正在启动... 
    start "" "Snipaste.exe"
    timeout /t 2 >nul
)

:: 3. 执行截图并保存,这里使用了snipaste的自动保存功能 
:: 如果需要使用自定义的保存,可以参考snipaste文档 
:: https://docs.snipaste.com/zh-cn/command-line-options 
echo 正在执行全屏截图并保存... 
Snipaste.exe snip --full -o success
timeout /t 1 >nul

:: 4. 如果最初未运行,则退出 Snipaste.exe(还原状态) 
if %was_running% neq 0 (
    echo 还原状态,退出 Snipaste.exe...
    start "" "Snipaste.exe" exit
    timeout /t 1 >nul
)

echo 操作完成! 
timeout /t 2 >nul

注意不要使用pause,因为这会导致cmd一直无法退出,需要手动结束进程。

snipaste.vbs

set ws=createobject("wscript.shell")
ws.Run """snipaste.bat""",0

snipaste.vbssnipaste.bat放在同一个目录下,不要使用中文。

设置任务计划程序

Win + R输入taskschd.msc打开任务计划程序设置。

  1. 创建基本任务
  2. 名字写每日截图,根据自己喜好设置
  3. 触发器设置为每天,选一个自己需要运行的时间
  4. 操作选择启动程序
  5. 脚本或脚本,名字填入snipaste.vbs,起始于填入 E:\code\IdeaProjects\notebook\windows\shell\bat\learn-bat\snipaste\,根据自己脚本所在路径进行设置
  6. 设置完成后点选中新添加的任务,点一下右边的运行,测试截图是否成功

至此,通过方式一为windows系统设置每天定时截图的功能就做好了。

方式二 借助powershell和系统任务计划

通过AI支援,我写了一个ps1脚本来进行截图,此方式可以截图到桌面上,并且可以传入参数来设置保存的路径和名字。项目地址:SilentScreenshots

这里省略了一些帮助信息。

screenshot.ps1截图脚本

screenshot.ps1

Param (
        [Parameter(HelpMessage="指定保存截图的目录路径。如果目录不存在,脚本将尝试创建它。")]
        [string]$OutputPath = "$([Environment]::GetFolderPath('Desktop'))\Screenshots",
        [Parameter(HelpMessage="指定截图的文件名,包括扩展名(例如:'my_screenshot.png')。")]
        [string]$FileName = "Screenshot_$(Get-Date -Format 'yyyyMMdd_HHmmss').png"
    )

function Take-FullScreenScreenshot {
    
    # 确保输出目录存在
    if (-not (Test-Path $OutputPath)) {
        New-Item -ItemType Directory -Path $OutputPath | Out-Null
    }

    # 添加必要的 .NET 程序集
    Add-Type -AssemblyName System.Drawing
    Add-Type -AssemblyName System.Windows.Forms

    # 设置进程为 DPI 感知 ---
    # 导入 User32.dll 中的 SetProcessDPIAware 函数
    Add-Type -TypeDefinition @"
        using System;
        using System.Runtime.InteropServices;

        public class User32 {
            [DllImport("user32.dll")]
            public static extern bool SetProcessDPIAware();
        }
"@
    # 调用 SetProcessDPIAware 函数
    # 这将告诉 Windows 我们的进程是 DPI 感知的,从而正确处理屏幕缩放
    [User32]::SetProcessDPIAware() | Out-Null

    # 获取虚拟屏幕的尺寸(包括所有显示器),现在应该能正确获取物理像素尺寸
    $Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen
    $Width = $Screen.Width
    $Height = $Screen.Height
    $Left = $Screen.Left
    $Top = $Screen.Top

    # 创建一个位图对象
    $Bitmap = New-Object System.Drawing.Bitmap $Width, $Height

    # 创建一个图形对象
    $Graphics = [System.Drawing.Graphics]::FromImage($Bitmap)

    # 从屏幕复制像素到图形对象
    # 源坐标 (Left, Top) 和目标坐标 (0, 0)
    $Graphics.CopyFromScreen($Left, $Top, 0, 0, $Bitmap.Size)

    # 构建完整的文件路径
    $FullFilePath = Join-Path -Path $OutputPath -ChildPath $FileName

    # 保存位图为PNG格式
    $Bitmap.Save($FullFilePath, [System.Drawing.Imaging.ImageFormat]::Png)

    # 清理对象
    $Graphics.Dispose()
    $Bitmap.Dispose()
}

# 调用函数进行截图
Take-FullScreenScreenshot

如果直接运行这个ps1文件是可以截图的,但是还不够优雅,因为他会弹出一个powershell的运行窗口。下面来解决这个问题。

screenshot.vbs隐藏窗口截图

上面的screenshot.ps1已经可以截图了,screenshot.vbs要做的是把窗口给隐藏了。

screenshot.vbs

Set sh = CreateObject("WScript.Shell")
psPath = Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName, "\")) & "screenshot.ps1"
args = ""
For Each a In WScript.Arguments: args = args & " " & a: Next
sh.Run "powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File """ & psPath & """ " & args, 0, False

现在把screenshot.vbsscreenshot.ps1放在同一个目录下,点击screenshot.vbs运行,会发现没有任何反应,这正常的,可以去桌面看看有没有截图的文件夹screenshot,如果有的话,里面就是刚才的截图了。

这样看起来,我们的需求已经达到了,但是现在我们有ps1vbs两个脚本,使用起来不太优雅,那能不能仅仅使用一个文件达到效果呢?研究了一下(问了下AI),还真可以。

根据ps1脚本创建exe可执行文件。

我们要使用的是powershell的PS2EXE模块。

先安装PS2EXE模块。

Install-Module ps2exe

生成exe文件,因为命令太长,我又写成了一个release.ps1脚本,这样每次修改了。先建立一个icon文件夹存放图标,里面我使用C:\WINDOWS\system32\moricons.dll ID为50的图标,使用的是IconsExtract提取出来的。

release.ps1

# 假设 screenshot.ps1 文件在当前目录

# 导入 PS2EXE 模块 (如果尚未导入)
Import-Module PS2EXE

# 命令详解参考 https://github.com/MScholtes/PS2EXE

# 打包exe

ps2exe -InputFile "screenshot.ps1" -OutputFile "screenshot.exe" -IconFile "./icon/moricons_50.ico" -Title "静默截图" -NoConsole -STA -X86 -Version "1.0.0.0" -noError  -Copyright "@ 2025 zjw"

运行打包脚本后,效果还不错。运行screenshot.exe也是没有提示截图了。

image

传入参数更改文件名和保存的位置

如果需要更改文件名和保存的位置,可以按照下面的方式调用

# 运行脚本(默认保存到桌面/Screenshots目录)
.\screenshot.exe
# 保存到指定目录
.\screenshot.exe -OutputPath "C:\MyCaptures"
# 指定保存的文件名
.\screenshot.exe -FileName "daily_report.png"

设置任务计划程序

这个操作和方式一里面的类似,就是把可执行文件换成screenshot.exe,同时添加自己需要的参数(我这里更改了保存了位置)

Win + R输入taskschd.msc打开任务计划程序设置。

  1. 创建基本任务
  2. 名字写每日截图,根据自己喜好设置
  3. 触发器设置为每天,选一个自己需要运行的时间
  4. 操作选择启动程序
  5. 脚本或脚本,名字填入screenshot.exe,参数填入-OutputPath "D:\systemfile\Pictures\定时截图",起始于填入 E:\code\IdeaProjects\SilentScreenshots\,根据自己脚本所在路径进行设置
  6. 设置完成后点选中新添加的任务,点一下右边的运行,测试截图是否成功

image

至此,通过方式二为windows系统设置每天定时截图的功能就做好了。

posted @ 2025-04-29 00:15  雨中遐想  阅读(694)  评论(1)    收藏  举报