
我們公司的員工甚至在周末都讓他們的電腦 24/7 運行,這是一個問題。我們的公司政策是在不使用時關閉,但情況並非總是如此。因此,我們一直在做的是使用 PsInfo 運行一個簡單的腳本來縮短電腦的正常運行時間。我們將 AD 中的計算機列表匯出到文字檔案中,然後使用批次檔遍歷該列表,提取正常運行時間信息,並將其保存到另一個文字檔案中:
For /F "tokens=*" %%i in (ComputerList.txt) do psinfo uptime -nobanner \\%%i 1>>UptimeResults.txt
效果很好,但如果電腦不在線,預設超時似乎是 60 秒,這可能會導致腳本在數百台電腦上花費很長時間。 PsExec 本身有一個可以使用的超時開關,但 PsInfo 似乎沒有考慮到這一點。是否有另一種方法可以強制它在 10 秒後超時,或者使用不同的程序來執行相同的操作?可能直接將 PsExec 與超時開關和其他命令一起使用?附帶說明一下,我們已經停用了 fastboot,因此正常運行時間結果是準確的。
我們已經爭論過,但希望有一個更簡單的解決方案:使用 PsExec 並運行,systeminfo | find "Boot Time"
然後分析啟動時間並進行一些數學運算以獲得運行時間。取得 uptime.exe 的舊副本,將其部署到電腦上,並透過 PsExec 使用其輸出。然後切換到 powershell 命令,該命令將輪詢 WMI 的上次啟動時間並再次進行數學計算。一切似乎都太複雜,寧願擁有簡單但緩慢的解決方案,除非其他人有更好的建議。
答案1
我喜歡格雷格的建議取得最後一次啟動時間。
但我相信以下內容會滿足您的要求。我使用 WMIC 在新的 cmd.exe 會話中啟動 PSINFO。 FOR /F 用於擷取新 CMD 會話的 PID。然後我呼叫一個例程來監視該過程長達 10 秒。如果不再運行,則立即返回。但 10 秒後我在返回之前終止了該進程。
我使用虛擬超時進程測試了啟動和監視進程。但我無法使用 PSINFO 進行測試,因為我沒有 PSINFO,也沒有你的環境。
@echo off
setlocal
set "timeout=10"
set "log=UptimeResults.txt"
:: Start with an empty result file
copy /y nul %log% >nul
:: Loop through the list of computers
for /f "tokens=*" %%i in (ComputerList.txt) do (
%= For each computer, launch PSINFO via wmic and use FOR /F to capture the parent cmd.exe session PID =%
%= The cd argument is the location where the process should run (current directory) =%
for /f "tokens=2 delims=;= " %%P in (
'wmic process call create 'cmd /c "psinfo uptime -nobanner \\%%i 1>>%log%"'^, "%cd%" ^| find "ProcessId"'
) do call :monitor %%P 2>nul 1>nul
)
exit /b
:monitor PID
:: Monitor up to %timeout% seconds and return immediately if process no longer running
for /l %%N in (1 1 %timeout%) do (
timeout 1
tasklist /fi "pid eq %1" | find "cmd.exe" || exit /b
)
:: It has been longer than %timeout% seconds, so kill the process
taskkill /pid %1 /f /t
exit /b