Question:
What is a method that can parse out just the hotfix KB entries in a Windows systeminfo command report.
Background:
I have many windows systems that I need to get the list of installed KBs from. I can't install any software on the systems, so I've resolved to use a batch file.
I would like to have a list of KBs as the output, saved to a file " .txt"
My Current Method:
So far, I can get the full list from systeminfo and put the entire output into a text file named with the device's host name and date and stick it in a directory called Systeminfo Saves. That works well enough for me, but I'm really only interested in the KBs and I am hoping to use that output to compare it to a list of validated KBs so I can get a list of KBs that need installed.
I've been messing around with for statements and tokens and delimiters to narrow down the list to just the KB files, but without success.
Here's my current code:
#echo off
REM Get date and host and set it to sFileName
REM -----------------------------------------
setlocal enabledelayedexpansion
set ssDate=%date%
set sHost=%computername%
set sDate=!ssDate:/=-!
REM Remove the day of the week
set sDate=%sDate:~-10%
set sFileName=%sHost% %sDate%.txt
REM -----------------------------------------
REM - Save system info to hostname and date -
REM -----------------------------------------
systeminfo > "Systeminfo Saves/%sFileName%"
REM
REM PUT FOR STATEMENT HERE FOR OUTPUT OF JUST KBs
REM -----------------------------------------
My next step that I haven't been able to pull off is to parse out the installed KBs into a file.
For statements have thrown me for a loop (pun mildly intended). I've tried this:
REM OUTPUT a list of KBs
SET count=1
set lookieloo = "]: KB"
FOR /F "tokens=* USEBACKQ" %%F IN (`systeminfo`) DO (
SET var!count!=%%F
SET /a count=!count!+1
REM See if "]: KB" is in the resultant string
if not x%%F:"]: KB"=%==x%%F echo %%F >> "Systeminfo Saves/%sFileName%"
)
I'm splicing together answers that I don't fully understand from other Stack Overflow answers that partially answer my question.
The last save to file I'm fairly sure won't work
.
The "]: KB" doesn't work at all. I tried using the variable lookieloo to get that statement to work. I didn't get an error, but I didn't get a list of KBs either.
So, the question is: What would a batch program look like to export a text file of installed KBs on a system using the systeminfo command?
From LotPings comment, I was able to put together a full program that extracts the installed KBs using just batch.
#setlocal enableextensions enabledelayedexpansion
#echo off
REM Get date and host and set it to sFileName
REM -----------------------------------------
set ssDate=%date%
set sHost=%computername%
REM Get the directory and make it if it doesn't exist
set sDir=Systeminfo Saves
if not exist "%sDir%\" mkdir "%sDir%\"
set sDate=!ssDate:/=-!
REM Remove the day of the week
set sDate=%sDate:~-10%
REM Compile the full file name with directory
set sFileName=%sDir%^\%sHost% %sDate%.txt
REM -----------------------------------------
echo %sFileName%
REM -- Extract KB information and save to file --
(For /f "tokens=2delims=: " %%A in ('systeminfo^|findstr "\[[0-9][0-9]*\]:.KB[0-
9]*"') Do #Echo:%%A)>"%sFileName%"
REM ---------------------------------------------
Loading and parsing SystemInfo is a time consuming operation and whilst determining the updates can take a while on its own, using WMI is probably a quicker method.
Here's an alternative which uses WMIC:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "sDir=WMIC Saves"
Set "sDate=%DATE:/=-%"
Set "sDate=%sDate:~-10%"
Set "sFileName=%sDir%\%COMPUTERNAME% %sDate%.txt"
If Not Exist "%sDir%\" MD "%sDir%" 2>Nul || Exit /B
(For /F "EOL=H Tokens=*" %%A In ('"WMIC QFE Get HotFixID|Sort"'
) Do For /F "Tokens=*" %%B In ("%%A") Do Echo=%%B)>"%sFileName%"
Related
With my little knowledge of writing code, I am trying to make a batch file where I can disable or enable a line in audio device with an IF statement.
For example, if the device is currently enabled, when I run the .bat file it will disable. If it's disabled, then it enables it.
I have the the device ID ("SWD\MMDEVAPI{0.0.1.00000000}.{55e90a30-8001-4bc8-af56-52998c03ed88}"). I am currently using pnputil /disable-device which works. But I don't know how to go about the IF statement. Would appreciate some help with that.
Edit: Okay so I found a tool called SoundVolumeView.exe that can lower the sound so the white noise can't be heard on startup. It can also mute as well all through command line.
I wasn't sure if you had solved this yourself already and I know I'm not supposed to spoon feed code on here but I had a script that did something similar and thought I should contribute. If you have any issues with this script, please comment with your issue.
Explaination: it runs pnputil /enum-devices /ids and looks at the output until it gets to a line with the device id. It sets a variable called ahead to 4. If ahead is above 0, then it will check if it is 0, if it isn't then it will go to the next line in the output of the command. If it is 0, then it will go to the toggle label and then it will check the line if it doesn't say Started. If it doesn't have Started in the line, then it will enable your device, if it does say started, then it will disable it. Then it just pauses and exits.
#echo off
setlocal enableDelayedExpansion
REM Needs to be run as administrator to work
set device=SWD\MMDEVAPI{0.0.1.00000000}.{55e90a30-8001-4bc8-af56-52998c03ed88}
set ahead=-1
for /f "delims=" %%a in ('pnputil /enum-devices /ids') do (
set "line=%%a"
if !ahead! GEQ 0 (
if !ahead!==0 goto :toggle
set /a ahead-=1
) else (
if not "x!line:%device%=!"=="x!line!" (
set ahead=4
)
)
)
:toggle
if "x!line:Started=!"=="x!line!" (
REM Device is not running
pnputil /enable-device "%device%" >nul
echo Enabling device...
) else (
REM Device is running
pnputil /disable-device "%device%" >nul
echo Disabling device...
)
pause
exit /b 0
For documentation on PnPUtil: https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/pnputil-command-syntax
For information on on for loops: https://ss64.com/nt/for.html, https://stackoverflow.com/a/50704943/19341457
For information on finding if a substring is in a string: https://stackoverflow.com/a/7006016/19341457
For information on delayed expansion: https://ss64.com/nt/delayedexpansion.html
I am creating a should-be-simple batch file that will allow me to input a class name and it will take me to the correct google classroom. However, my if statement doesn't work, even when I input the word "Social Studies". It does not take me to my classroom, and on top of that, the CMD is just closed. When I remove the If Statement line, the code works fine and the cmd just stays open after inputting a class.
set /p class="Enter Class: "
IF "%class%" /I EQU "Social Studies" (START https://classroom.google.com)
cmd /k
IF /I "%class%" EQU "Social Studies"...
The parsing logic for an if statement is very specific; if [/i][NOT] arg1 op arg2 where /i and not are optional, but must if used, be used in that order.
Your code sees /i where it expects a comparison-operator and generates a syntax-error.
When you use the point-click-and-giggle method of executing a batch, the batch window will often close if a syntax-error is found. You should instead open a 'command prompt' and run your batch from there so that the window remains open and any error message will be displayed.
You can write #echo off whice prevents the prompt and contents of the batch file from being displayed.
I replaced the your EQ with == and now it works:
#echo off
set /p class="Enter Class: "
IF "%class%"=="Social Studies" (START https://classroom.google.com)
PAUSE
The PAUSE at the end will make the CMD remain open after it's done
I've read a lot of things and I can't find away of doing this that I understand. This might be because I'm a wee newbie though.
What I'm trying to do is:
I have a file called start.txt with the contents
..\dll | toapp.exe "..\posdata\filename.xml" "..\OUT" "..\TEMP"
I want to read the contents of that in a batchfile and take only filename.xml as a variable. From device to device inside the network it changes.
I'm then going to use that variable to copy a file from 1 machine to another but I only want that one file and I can't be sure what it's called without looking in the start.txt. I can do all the copy and checks to make sure it's looking in the correct places but just not the findstr section.
Any idea of what to do to understand would be fantastic
#echo off
set "start_file=start.txt"
for /f tokens^=5^ delims^=\^" %%# in ('type "%start_file%"^|find /i "..\posdata"') do set "xml_file=%%#"
echo %xml_file%
Your question is a little bit unclear.Is this the only line in the file? Is this the exact content? How can I recognize the line with the file?
The script above will work in case there's only one line wwith "..\postdata" string and the content is exact as described in question.
Edit Covering the both cases:
#echo off
setlocal
set "start_file=start.txt"
set "xml_file="
for /f tokens^=5^ delims^=\^" %%# in ('type "%start_file%"^|find /i "..\posdata"^|find /i /v "-storedbpath"') do set "xml_file=%%#"
if not defined xml_file (
for /f "usebackq tokens=9" %%# in ("%start_file%") do (
set "xml_file=%%~#"
)
)
echo %xml_file%
Text this:
for /f "usebackq tokens=4" %%a in ("start.txt") do echo %%~nxa
I have a list (list.txt) like this with the content:
C:\Users\Computers\39323227
C:\Users\Computers\39323227.zip
C:\Users\Computers\39328635
C:\Users\Computers\39328635.zip
C:\Users\Computers\39329113.zip
C:\Users\Computers\39329288.zip
C:\Users\Computers\39331075
C:\Users\Computers\39331075.zip
C:\Users\Computers\39331386.zip
C:\Users\Computers\39904282
C:\Users\Computers\39904282.zip
C:\Users\Computers\39905798
C:\Users\Computers\39905798.zip
C:\Users\Computers\39906307.zip
And all files and created folders in parent folder clutter like this:
C:\Users\Computers\39323227
C:\Users\Computers\39328635
C:\Users\Computers\39331075
C:\Users\Computers\39904282
C:\Users\Computers\39905798
C:\Users\Computers\39323227.zip
C:\Users\Computers\39328635.zip
C:\Users\Computers\39329113.zip
C:\Users\Computers\39329288.zip
C:\Users\Computers\39331075.zip
C:\Users\Computers\39331386.zip
C:\Users\Computers\39904282.zip
C:\Users\Computers\39905798.zip
C:\Users\Computers\39906307.zip
Is it possible to write a CMD to move files to folders as the below? :
C:\Users\Computers\39323227\39323227.zip
C:\Users\Computers\39328635\39328635.zip
C:\Users\Computers\39328635\39329113.zip
C:\Users\Computers\39328635\39329288.zip
C:\Users\Computers\39331075\39331075.zip
C:\Users\Computers\39331075\39331386.zip
C:\Users\Computers\39904282\39904282.zip
C:\Users\Computers\39905798\39905798.zip
C:\Users\Computers\39905798\39906307.zip
If not, could you suggest that there are any soft which could help me to solve this problem?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "delims=" %%a IN (q22540287.txt) DO (
IF "%%~xa"==".zip" (
rem ECHO MD "!destdir!\"
ECHO MOVE "%%a" "!destdir!\"
) ELSE (SET "destdir=%%~dpna")
)
GOTO :EOF
I used a file named q22540287.txt containing your data for my testing.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
I've added in a line to ensure that the selected destination directory exists. To activate that feature, remove the REM from the MD... line. The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
Results for me (noting that I changed C: to U: for my testing)
MOVE "u:\Users\Computers\39323227.zip" "u:\users\computers\39323227\"
MOVE "u:\Users\Computers\39328635.zip" "u:\users\computers\39328635\"
MOVE "u:\Users\Computers\39329113.zip" "u:\users\computers\39328635\"
MOVE "u:\Users\Computers\39329288.zip" "u:\users\computers\39328635\"
MOVE "u:\Users\Computers\39331075.zip" "u:\users\computers\39331075\"
MOVE "u:\Users\Computers\39331386.zip" "u:\users\computers\39331075\"
MOVE "u:\Users\Computers\39904282.zip" "u:\users\computers\39904282\"
MOVE "u:\Users\Computers\39905798.zip" "u:\users\computers\39905798\"
MOVE "u:\Users\Computers\39906307.zip" "u:\users\computers\39905798\"
This does not relate directly to my development project but I am curious none the less. Recently, after a lot of head-banging, I traced a build problem to an invalid entry in the System PATH variable. On my machine, it contains about 20 entries. I am guessing there has to be an easier way to verify the validity of each entry. Can anyone suggest a way to check this? Thanks for your time.
This code in a batch file (based on this answer) works for me:
#echo off
setlocal DisableDelayedExpansion
set "var=%PATH%"
set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
rem ** This is the key line, the missing quote is intention
set var=%var:""="%
set "var=%var:"=""%"
set "var=%var:;;="";""%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
set "var=%var:"=""%"
set "var=%var:"";""=";"%"
set "var=%var:"""="%"
setlocal EnableDelayedExpansion
for %%a in ("!var!") do (
endlocal
call :testdir "%%~a"
setlocal EnableDelayedExpansion
)
goto :eof
:testdir
if exist %1 echo OK: %1
if not exist %1 echo NOK: %1
Put the code into a text file, e.g. validatepath.bat.
When run, it should output something like:
OK: C:\Users\abcde
NOK: C:\this\is\no\dir