wmic os get localdatetime突然出错
介绍
我有一个BAT文件,是通过cronical(一个类似Windows定时任务的服务)在执行。
已经工作正常了10天……然后今天突然时间戳计算失败,而且还把脚本给弄坏了。
有趣的地方:
日志文件今天似乎是这样的:
dailyOne_~0,8dt
不像这样:
dailyOne_20260412_2000.log
我的直觉是问题出在这里……只是我不知道为什么它今天就爆炸/出现了……
REM ===== 3. Timestamp =====
for /f %%a in ('wmic os get localdatetime ^| find "."') do set dt=%%a
set "TIMESTAMP=!dt:~0,8!_!dt:~8,6!"
问题
- 它本来运行良好……我测试过这个……也没有做出任何改动。
- 今天的日期会不会有关系?14/04/2026?
- 会不会是杀毒软件的问题?有没有什么在拦截时间戳的查询?
全部代码
下面是BAT文件的内容:
@echo off
setlocal enabledelayedexpansion
REM ===== 1. Read parameters =====
set "HOST=%~1"
set "REPORT_NAME=%~2"
REM ===== 2. Validate =====
if "%HOST%"=="" (
echo ERROR: Missing HOST
exit /b 1
)
if "%REPORT_NAME%"=="" (
echo ERROR: Missing REPORT_NAME
exit /b 1
)
REM ===== 3. Timestamp =====
for /f %%a in ('wmic os get localdatetime ^| find "."') do set dt=%%a
set "TIMESTAMP=!dt:~0,8!_!dt:~8,6!"
REM ===== 4. Log file =====
set "LOGFILE=%REPORT_NAME%_!TIMESTAMP!.txt"
type nul > "%LOGFILE%"
REM ===== 5. Live viewer =====
start "Log Viewer - %REPORT_NAME%" cmd /k powershell -NoExit -Command "Get-Content -Path '%LOGFILE%' -Wait"
REM ===== 6. Start log =====
echo ================================================== >> "%LOGFILE%"
echo [%DATE% %TIME%] START >> "%LOGFILE%"
echo HOST=%HOST% >> "%LOGFILE%"
echo REPORT=%REPORT_NAME% >> "%LOGFILE%"
echo ================================================== >> "%LOGFILE%"
REM ===== 7. Call API (NO TIMEOUT, NO RETRY) =====
echo [%DATE% %TIME%] Calling API... >> "%LOGFILE%"
curl -N -sS ^
"http://%HOST%/process/reports/p?reportName=%REPORT_NAME%" ^
>> "%LOGFILE%" 2>&1
REM ===== 8. End log =====
echo. >> "%LOGFILE%"
echo ================================================== >> "%LOGFILE%"
echo [%DATE% %TIME%] END >> "%LOGFILE%"
echo ================================================== >> "%LOGFILE%"
echo Done. Log file: %LOGFILE%
exit /b 0
cronical.dat中的其中一条记录如下
28 21 * * * cmd /c ""D:\Menelaos\sched_scripts\processReport.bat" server1:5000 dailyOne"
一切都正常工作(命令在执行、日志也在产生等)
日志
今天我在计划发送的邮件里看到这个:
Cronical: Results from cmd /c ""D:\Menelaos\sched_scripts\processReport.bat" server1:5000 dailyOne""
Invalid XSL format (or) file name. Done. Log file: logs\dailyOne_~0,8dt:~8,4.log
The filename, directory name, or volume label syntax is incorrect。
下面是一个日志样本(来自凌晨4点的另一条记录):
`2026-04-14 04:00:01.334 [154] Starting job: cmd /c ""D:\Menelaos\sched_scripts\processReport.bat" server:5000"
2026-04-14 04:06:41.293 WARN [162] Job failed to end, terminating program
2026-04-14 04:06:44.401 ERR [162] Win32Exception: The operation was canceled by the user
Source: System
TargetSite: Boolean StartWithShellExecuteEx(System.Diagnostics.ProcessStartInfo)
Stack trace:
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at Cronical.InjectCtrlC.Break(Int32 processId)
at Cronical.Misc.ProcessWrapper.Stop()
at DotNetCommons.Logging.Logger.Catch(Action action)`
更新 - 替代方法
我发现使用替代方法获取日期时间有效,错误消失了:
REM ===== 3. Timestamp (NO seconds) =====
for /f %%a in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmm"') do set "TIMESTAMP=%%a"
if "%TIMESTAMP%"=="" (
echo ERROR: Failed to generate timestamp
exit /b 1
)
不过,我仍然不确定WMIC是否不可用。我在命令提示符下运行它时它工作了。因此,我只能得出结论,可能是以下三种情况之一?
- WMIC在 cronable运行的上下文(路径)中不可用
- 杀毒软件、Windows Smart这类安全功能,或其它什么阻止它?
- 某种策略?
另外,我看到WMIC现在已被弃用……尽管在不少答案中它仍然是获取日期时间的方式……参考:https://techcommunity.microsoft.com/blog/windows-itpro-blog/wmi-command-line-wmic-utility-deprecation-next-steps/4039242
解决方案
似乎 dt 因为某种原因是空的。你仍然可以通过VBS请求WMI。
注: VBS未来也可能被废弃:https://techcommunity.microsoft.com/blog/windows-itpro-blog/vbscript-deprecation-timelines-and-next-steps/4148301
注: WMIC不是WMI。
Source code
print_wmi_local_datetime.vbs:
Dim objWMI : Set objWMI = GetObject("winmgmts:")
Dim objSet: Set objSet = objWMI.InstancesOf("Win32_OperatingSystem")
Dim obj
For Each obj in objSet
WScript.Echo obj.LocalDateTime
Exit For
Next
get_wmi_local_datetime.vbs.bat:
@echo off
rem drop return value
set "RETURN_VALUE="
rem CAUTION:
rem `for /F` does not return a command error code
for /F "usebackq tokens=* delims="eol^= %%i in (`@"%%SystemRoot%%\System32\cscript.exe" //nologo "%~dp0print_wmi_local_datetime.vbs" 2^>nul`) do set "RETURN_VALUE=%%i"
if defined RETURN_VALUE endlocal & set "RETURN_VALUE=%RETURN_VALUE:~0,18%" & exit /b 0
exit /b 1
rem Description:
rem Independent to Windows locale date/time request.