我已经负责几十台PC,我需要检查内部硬件和软件。我们的CMDB系统不是最新的,因此我需要找出我们实际拥有的内容。我花了几个小时试图找到一种方法来制作易于使用的批处理脚本,并生成易于阅读的输出。我想开始使用物理内存/ RAM。
我找到了wmic命令,并且能够指定它以仅获取我需要的信息并使用文本文件和FOR循环来遍历SN列表并将每台计算机的RAM输出到文本文件中: / p>
IF EXIST output.txt DEL /Q output.txt >NUL
FOR /F "tokens=*" %%i IN (input.txt) DO (
wmic /node:%%i memorychip get capacity >> output.txt
)
EXIT /B
仅在PC上线时才有效。
到目前为止,这么好。
要查看计算机的序列号,例如 - 使用Excel将文本文件转换为表格,我添加了一个ECHO行:
IF EXIST output.txt DEL /Q output.txt >NUL
FOR /F "tokens=*" %%i IN (input.txt) DO (
@Echo Serialnumber %%i >> output.txt
wmic /node:%%i memorychip get capacity >> output.txt
)
EXIT /B
如果我从输出文件中手动删除所有“”字符,它会转换回我期望的内容:Everything back to neat lines
我希望我能直接从wmic函数的输出中删除“space”字符,但我不能。例如,我发现这个技巧可以将wmic的输出转换为变量,然后我可以操作它:
SETLOCAL ENABLEDELAYEDEXPANSION
@echo off
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`wmic /node:2CMFFY1 memorychip get capacity`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ECHO %var4%
ECHO %var5%
ENDLOCAL
This piece of code neatly creates separate lines if I add a serial number manually
但我不能让它填充input.txt文件中的序列号。如果我尝试这个代码,它仍会打印序列号行,但显然会跳过第二个FOR循环:
SETLOCAL ENABLEDELAYEDEXPANSION
IF EXIST output.txt DEL /Q output.txt >NUL
FOR /F "tokens=*" %%i IN (input.txt) DO (
@Echo Serialnumber %%i >> output.txt
SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`wmic /node:%%i memorychip get capacity`) DO (
SET var!count!=%%F
SET /a count=!count!+1
)
ECHO %var1%
ECHO %var2%
ECHO %var3%
ECHO %var4%
ECHO %var5%
)
ENDLOCAL
EXIT /B
如果我查看实际发生的情况,似乎在某些情况下,第二个FOR确实获得了正确的序列号passed into the wmic command,但它仍然不起作用I only get the lines of the first ECHO。
我发现另一个论坛的thread关于WMIC发布unicode结果,这些结果无法正确解释,有些尝试解决这个问题。我尝试将其集成到我的代码中,但它不能100%工作,现在增加了额外的"Echo is ON" lines to the results。
IF EXIST output.txt DEL /Q output.txt >NUL
FOR /F "tokens=*" %%i IN (input.txt) DO (
ECHO Serialnumber %%i>>output.txt
FOR /F "tokens=*" %%j IN ('wmic /node:%%i memorychip get capacity') DO @echo %%j>>output.txt 2>&1
)
如果我可以将WMIC结果写成单独的变量,可能有一种方法可以整合这行代码来删除空格:
set str=%str: =%
最后一步是将RAM空间(以字节为单位)减少到更可读的GB数。我已经看到了一些可能实现的东西,我只需要将字符串变成变量来操纵它们。
但正如我所说,我是一个完全的菜鸟,只有十年的知识,一些视觉基础和C ++以及一些HTML / JAVA / CSS编程。对这个问题可能有一个简单的解决方案......
任何帮助都会非常感激!此外,如果任何人都可以推荐一个网站或一本书,一步一步地通过cmd /批处理脚本,语法结构的一般解释,变量如何工作的信息等,这也将是非常有帮助:)
答案 0 :(得分:0)
很难从你的故事中准确地说出你想要的东西,所以这是我最好的猜测:
@Echo Off
(For /F "Delims=" %%A In (input.txt) Do (Echo Serialnumber %%A
For /F "Skip=1" %%B In ('WMIC /Node:%%A MemoryChip Get Capacity'
) Do For /F %%C In ("%%B") Do Echo %%C))>output.txt
Exit/B
答案 1 :(得分:0)
此脚本从不同的WMIC调用中收集多个值,其中每个数据源都在子例程中处理。为了说明,收集了总内存大小和BIOS序列号。节点列表文件包含主机名,在OP的情况下恰好与主机的序列号相同(如果我已理解这一点)。
WMIC输出通常具有尾随控制字符。要摆脱它,使用临时文件:
@echo off
REM 8:12:49 PM Saturday 18/11/2017
REM get serial number and memory size for all hosts in a hostname list file
REM output is in CSV format
REM 1:43:58 PM Tuesday 21/11/2017
REM added: check if host is online, using ping
setlocal EnableDelayedExpansion
set nodelist=nodelist.txt
REM needs write permissions for next 2 paths
set out=output.txt
set temppath=%TEMP%
echo node,serial,memsize> %out%
for /F "delims=" %%N in (%nodelist%) do (
set "node=%%N"
set "node=!node: =!"
set "memsize=" & set "getserial="
CALL :checkonline !node!
if defined OK CALL :getmem !node!
if defined OK CALL :getserial !node!
REM ... and so on
) & echo !node!,!serial!,!memsize!>> %out%
type %out%
goto :EOF
:checkonline
set "OK="
if "%~1"=="" goto :EOF
ping -4 -w 200 -n 2 %~1 | find "TTL" 2>&1 >nul && set "OK=1"
goto :EOF
:getmem
set "OK="
set "out1=%temppath%\%RANDOM%.tmp"
WMIC /Node:%~1 /output:%out1% ComputerSystem get TotalPhysicalMemory /value 2>&1 >nul|| goto :EOF
for /F "tokens=1,2 delims==" %%A in ('find "=" ^< %out1%') do @set memsize=%%B
rem memsize is in bytes now
rem calc size in MB, need to truncate by 1000, cannot use SET /A
set "memsize=!memsize:~0,-3!"
rem div by 1048 (1024 * 1,024) in 2 steps
set /A memsize *= 42
set /A memsize /= 44016
rem assume Windows itself is using 132 MB
set /A memsize += 132
set "OK=1"
del %out1%
goto :EOF
:getserial
set "OK="
set "out1=%temppath%\%RANDOM%.tmp"
WMIC /Node:%1 /output:%out1% Bios get SerialNumber /value 2>&1 >nul || goto :EOF
for /F "tokens=1,2 delims==" %%A in ('find "=" ^< %out1%') do @set serial=%%B
set "OK=1"
del %out1%
goto :EOF
编辑:
我已经使用ping添加了一个快速检查节点是否在线的信息。主机需要具有IPv4 IP地址(而不是IPv6)才能保持简单。此外,每个WMIC调用都返回一个成功标志(OK)。如果一个呼叫失败,则不会在此主机上尝试其他呼叫。最后,现在节点名称可以包含尾随空格而不会干扰进程。
答案 2 :(得分:0)
但是所有wmic输出行在每个字符之间都有奇怪的空格 [...]为什么会这样?
wmic
输出Unicode(两个字节字符编码)。
您可以使用type
或more
wmic memorychip get capacity|more >>output.txt
各自:
FOR /F "tokens=* USEBACKQ" %%F IN (`wmic /node:%%i memorychip get capacity ^|more`) DO ( ...