使用 wmic 和修改输出文件生成计算机列表中的 RAM 概览
Generating an overview of RAM in a list of computers by using wmic and modifying output file
我已经负责了几十台 PC,我需要检查内部硬件和软件。我们的 CMDB 系统不是最新的,因此我需要找出我们实际拥有的东西。我花了几个小时试图想出一种方法来制作易于使用并生成易于阅读的输出的批处理脚本。我想开始物理 memory/RAM.
我找到了 wmic 命令,并且能够指定它只获取我需要的信息,并使用文本文件和 FOR 循环循环遍历 SN 列表并将每台计算机的 RAM 输出到文本文件中:
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 将文本文件变形为 table,我添加了一个 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
But all the wmic output lines got weird spaces between each character and cramped into one line, whereas before they were nicely split into as many lines as there were different "words"为什么会这样?
如果我从输出文件中手动删除所有“”字符,它会转换回我所期望的: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, but it still doesn't work, I only get the lines of the first ECHO。
我找到了另一个论坛的thread about WMIC posting unicode outcomes, which can't be interpreted correctly, and some attempts to solve this. I tried integrating this into my code, but it doesn't work 100%, it now adds extra "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 结果写入单独的变量,可能有一种方法可以集成这行代码以删除 spaces:
set str=%str: =%
最后一步是将 RAM space(以字节为单位)减少到更易读的 GB 数。我已经看到了一些可能实现这一点的东西,我只需要将字符串放入变量中即可操作它们。
但正如我所说,我是一个彻头彻尾的菜鸟,对一些 visual basic 和 C++ 以及一些 HTML/JAVA/CSS 编程只有十年的知识。这个问题可能有一个简单的解决方案...
如有任何帮助,我们将不胜感激!此外,如果有人可以推荐一个网站或一本书,让您逐步完成 cmd/batch 脚本编写,并提供语法结构的一般解释、变量如何工作的信息等,那也会非常有帮助:)
很难从你的故事中准确地说出你想要什么,所以这是我最好的猜测:
@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
此脚本从不同的 WMIC 调用中收集多个值,其中每个数据源都在子例程中处理。为了说明,收集了总内存大小和 BIOS 序列号。 nodelist 文件包含主机名,在 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 调用 returns 一个成功标志 (OK)。如果一个调用失败,则不会在此主机上尝试其他调用。最后,现在节点名称可以包含尾随 space 而不会干扰进程。
But all the wmic output lines got weird spaces between each character
[...] Why does this happen?
wmic
输出 Unicode(两个字节字符编码)。
您可以 "convert" 到 ASCII type
或 more
:
wmic memorychip get capacity|more >>output.txt
各自:
FOR /F "tokens=* USEBACKQ" %%F IN (`wmic /node:%%i memorychip get capacity ^|more`) DO ( ...
我已经负责了几十台 PC,我需要检查内部硬件和软件。我们的 CMDB 系统不是最新的,因此我需要找出我们实际拥有的东西。我花了几个小时试图想出一种方法来制作易于使用并生成易于阅读的输出的批处理脚本。我想开始物理 memory/RAM.
我找到了 wmic 命令,并且能够指定它只获取我需要的信息,并使用文本文件和 FOR 循环循环遍历 SN 列表并将每台计算机的 RAM 输出到文本文件中:
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 将文本文件变形为 table,我添加了一个 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
But all the wmic output lines got weird spaces between each character and cramped into one line, whereas before they were nicely split into as many lines as there were different "words"为什么会这样?
如果我从输出文件中手动删除所有“”字符,它会转换回我所期望的: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, but it still doesn't work, I only get the lines of the first ECHO。
我找到了另一个论坛的thread about WMIC posting unicode outcomes, which can't be interpreted correctly, and some attempts to solve this. I tried integrating this into my code, but it doesn't work 100%, it now adds extra "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 结果写入单独的变量,可能有一种方法可以集成这行代码以删除 spaces:
set str=%str: =%
最后一步是将 RAM space(以字节为单位)减少到更易读的 GB 数。我已经看到了一些可能实现这一点的东西,我只需要将字符串放入变量中即可操作它们。
但正如我所说,我是一个彻头彻尾的菜鸟,对一些 visual basic 和 C++ 以及一些 HTML/JAVA/CSS 编程只有十年的知识。这个问题可能有一个简单的解决方案...
如有任何帮助,我们将不胜感激!此外,如果有人可以推荐一个网站或一本书,让您逐步完成 cmd/batch 脚本编写,并提供语法结构的一般解释、变量如何工作的信息等,那也会非常有帮助:)
很难从你的故事中准确地说出你想要什么,所以这是我最好的猜测:
@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
此脚本从不同的 WMIC 调用中收集多个值,其中每个数据源都在子例程中处理。为了说明,收集了总内存大小和 BIOS 序列号。 nodelist 文件包含主机名,在 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 调用 returns 一个成功标志 (OK)。如果一个调用失败,则不会在此主机上尝试其他调用。最后,现在节点名称可以包含尾随 space 而不会干扰进程。
But all the wmic output lines got weird spaces between each character [...] Why does this happen?
wmic
输出 Unicode(两个字节字符编码)。
您可以 "convert" 到 ASCII type
或 more
:
wmic memorychip get capacity|more >>output.txt
各自:
FOR /F "tokens=* USEBACKQ" %%F IN (`wmic /node:%%i memorychip get capacity ^|more`) DO ( ...