CMD Variable for registry - batch-file

Alright so I was trying to delete the shell data in the registry. I can get to it and get all of the information right, but I want to automate it for all users. The one I can use right now only targets a specific file.
reg delete "HKEY_USERS\S-1-5-21-3793956547-500355711-2568367668-1002\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags" /f
What I wanted to do was skip the input for S-1-5-21 and have it target all of the keys within HKEY_USERS. This way I can get all of the shell data deleted with the press of a button.
I am not sure if there is a variable for this, or maybe I am going in the wrong direction here. Any input is appreciated and I will attempt to answer any questions I can.

To enumerate the HKEY_USERS you can Reg Query within a For /f
#Echo off
Set "Hive=HKEY_USERS"
For /F "delims=" %%A in (
'Reg Query "%Hive%" ^|findstr "%Hive%\S-1-5-21" '
) Do Echo %%A
Replace Echo with any cmd you like to execute.
Sample scrambled output:
> SO_41773670.cmd
HKEY_USERS\S-1-5-21-2140113576-3579786329-1990256020-1001
HKEY_USERS\S-1-5-21-2140113576-3579786329-1990256020-1001_Classes
HKEY_USERS\S-1-5-21-2140113576-3579786329-1990256020-1005
HKEY_USERS\S-1-5-21-2140113576-3579786329-1990256020-1006

Something like this may very well suit your needs, it is very likely language dependent, and blind automated removal of registry subkeys is not my recommendation.
#Echo Off
For /F "EOL=E Delims=" %%A In ('Reg Query HKU /S /F Bags /K'
) Do Echo=Reg Delete "%%A" /F&&Echo=Reg Add "%%A"
Timeout -1
remove the two instances of Echo= and the last line if you're happy with the output and wish to continue.

Related

Correct syntax for nested for loops in batch file

I am trying to query the registry value of an installed application on many servers. I could hardcode the servers in, and have a lot of repetition and it seems to work. But sometimes a list of servers may change, and I'd like to take a more sensible modular approach.
So I can provide a test file with a list of server names, and then query the registry values of all of these servers, outputting them in a logfile.
I think the issue is definitely with my loops/variable storing. Not sure exactly what is going on, but it seems like once I get one set of Registry values, these are outputted for every single server, regardless of their respective registry values.
Not too experience with this kind of scripting, so I have been sort of mashing this together through trial and error, below is what I have so far. Please point out any woeful syntax errors I've made.
So essentially this is to find a McAfee scan engine version installed to each server. The reporting from the McAfee console itself is not always reliable, and I want to check that the contents are successfully pulled down to each server.
There are two registry values required to create a full engine version, so I am required to pull both of these and then combine them into a single string.
At the moment I do get an output that looks correct, but it does not represent what is actually installed to each server. It is like one value is being picked up and then replicated.
On an additional note, this only seems to work when executed in command line. And the first 1-2 times it is ran, no values are pulled up. Get the feeling I am quite far away from a solution.
SET LOGFILE=C:\LogFile.log
For /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Major ^| find /i "EngineVersion32Major"') do set /a major=%%a
for /f "tokens=3" %%b in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Minor ^| find /i "EngineVersion32Minor"') do set /a minor=%%b
echo %%i: %major%.%minor% >> %LOGFILE%
)
Would expect an output like this:
server1 : 5900.5647
server2 : 6000.4589
server3 : 5900.5647
server4 : 5900.5647
Cheers for any help you can provide.
It has nothing to do with for syntax, but how cmd parses scripts. See How does the Windows Command Interpreter (CMD.EXE) parse scripts?
When cmd parses a block (anything within parens), processes it as a single line. So it expands any %var% to its actual content. Changes made to it, are not taken into account until the block is exited. To retrieve new content within a block, you must enable delayed expansion, which forces the parser to evaluate it for every iteration. Also, syntax must be changed from %var% to !var!
Here, also, removed the /a switch from set command, as you are not doing calculations, and you may get results you won't expect (imagine a minor version equal to 0080 that will be treated as octal (invalid) and would break the script). Also, note both var name and var content enclosed in quotes (set "minor=%%b"), to avoid undesired trailing/leading spaces.
More also, I think you don't need the ^| find /i "EngineVersion32Major part, as possibly the key named EngineVersion32Major will content only what you are looking for. And again, enclose data in quotes (never know when a space may appear). You may also change "tokens=3" by "skip=1 tokens=3" to avoid process the heading reg echoes.
Thus
#echo off
SetLocal EnableDelayedExpansion
SET LOGFILE=C:\LogFile.log
for /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a"
for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b"
echo %%i: !major!.!minor!>>%LOGFILE%
)
EndLocal
Also, this works within a block regardless delayed expansion is enabled or not (note double percent sign)
call echo %%i: %%major%%.%%minor%%>>%LOGFILE%
Another issue, any time a redirection is used within a block, the system opens and closes the file (or stream).
But
#echo off
SetLocal EnableDelayedExpansion
SET LOGFILE=C:\LogFile.log
>>"%LOGFILE%" (
for /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a"
for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b"
echo %%i: !major!.!minor!
)
)
EndLocal
Processes all commands in the block, so the file is opened and closed only once. This may improve performance, specially with large files.
BTW,
>>"%LOGFILE%" (
...
...
)
Is the same as
(
...
...
)>>"%LOGFILE%"
Please use the search facility to locate many SO articles on delayed expansion.
The easy way in your case is to use
call echo %%i: %%major%%.%%minor%% >> %LOGFILE%

output net view (batch) into text then perform action against each computer

I have been trying to find away to search for the existence of my company's software on PC's by searching hostnames on the network \\computername\c$\Program Files\Foo, and if it finds it, copy over an updated config etc.
I've seen that net view will out put all the PC's on the network, something like this:
\\DISKSTATION
\\JWLAPTOP
\\TEST
\\XP
The command completed successfully.
I was wondering if there was a way to just get the computer names in a clean list (without "command completed" etc.):
\\DISKSTATION
\\JWLAPTOP
\\TEST
\\XP
Then run some commands against it, for everything in hostnames.txt, if exist:
\\JWLAPTOP\c$\Program Files\Foo --> do copy xyz to wherever
I can take care of the part \c$\Program Files\Foo as a variable to add after the computer names in the text file.
Hope that makes sense, thanks for any tips.
edit
Been re thinking this perhaps there is a more direct way to do this....
I need to see the list of PC's on customers network.....net view is a good way of getting this info so far, but I further need to see which ones are online. Any online, query for folder and update a *.CFG file, any offline, output to text for reference.
So at the minute....
FOR /F "tokens=1 delims= " %%G IN ('net view ^|findstr /L /B /C:"\\"')
this is working great, I then made it output to a text file..
FOR /F "tokens=1 delims= " %%G IN ('net view ^|findstr /L /B /C:"\\"') DO (echo %%G>>%~dp0netview.txt)
However, the %%G echo's back \somecomputer which means I am struggling to get a new line..
for /f %%G in (%~dp0netview.txt) DO (ping etc......
to ping because of the \ before the computer name. So was wonder if we can make the list 'just" have the PC name without the \ before it.
Also this is the content of the .cfg file I need to edit...
<?xml version="1.0" encoding="utf-8"?>
<ClientConfigurationFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ServerPath>**\\server\shared\data**</ServerPath>
<ApplicationMode>Workstation</ApplicationMode>
<VRPath />
<ServicePollingInterval>0</ServicePollingInterval>
</ClientConfigurationFile>
perhaps there is a way of editing a certain section of this directly once its existence is found. \server\shared\data...in bold is what I need to update often when clients have new servers and things and involves having to go round lots of rooms to update manually. This batch could save hours upon hours of unnecessary work.
over writing the existing .cfg file is still a good way of doing it if it's too tricky or not possible directly.
Hope it makes sense, thanks for the replies!!!
Assuming none of your computer names have spaces in them.
#echo off
FOR /F "tokens=1 delims= " %%G IN ('net view ^|findstr /L /B /C:"\\"') DO (
IF EXIST "%%~G\c$\Program Files\Foo" copy "C:\folder\xyz.txt" "C:\other folder\"
)
If you want the leading back slashes stripped then use it as a delimiter just like I am using the space as a delimiter to get rid of all the extraneous NET VIEW output.
#echo off
FOR /F "tokens=1 delims=\ " %%G IN ('net view ^|findstr /L /B /C:"\\"') DO (
PING %%G
IF EXIST "\\%%~G\c$\Program Files\Foo" copy "C:\folder\xyz.txt" "C:\other folder\"
)
You could do the following:
#echo off
setlocal EnableExtensions
set "TARGET=C$\Program Files\Foo"
for /F "eol=| delims=" %%C in ('
net view ^| find "\\"
') do (
pushd "%%C\%TARGET%"
if not ErrorLevel 1 (
rem do your operations here...
copy "\your\source\path\xyz" "."
popd
)
)
endlocal
The for /F loop walks through all host names returned by net view (supposing each one starts with \\ and there are only the host names).
Since the resulting path (for instance \\TEST\C$\Program Files\Foo) is a UNC path which is not supported by several commands, pushd is used, which is capable of connecting to the given resource by establishing a temporary drive letter like Z:, and changing the working directory to its root immediately (if the command extensions are on, which is the Windows default).
The query if not ErrorLevel 1 is used to skip over the remaining commands in case pushd could not connect to the resource for some reason.
After all your operations, popd ensures that the temporary drive created by pushd is unmounted and that the former working directory is restored.

.bat - insert text before a period

I have a .bat that I use to quickly query basic information from servers. After it gets the FQDN from DNS, I need to insert a "-r" (minus quotes) after the servername, but before the ".domain.com". The area that it will be added to the script is below -
for /f "delims=[] tokens=2" %%b in ('ping %servername% -n 1 ^| findstr "["') do (set thisip=%%b)
for /f "tokens=2" %%a in ('nslookup %thisip% ^| find /i "Name: "') do (set fqdnstat=%%a)
so how can I take the FQDN, which is set to fqdnstat, and modify it from -
server.domain.com
to server-r.domain.com ?
Edit - I guess I didn't really explain very well. I just need to insert text into a line of text, before a period. I need to take the following name: server.domain.com and edit it to read server-r.domain.com, using a command. The rest of the script above is context for the issue. The fqdnstat is the variable that I use to for the Fully Qualified Domain Name.
I am afraid I don't really understand your concern, but this Batch file may help you:
#echo off
set fqdnstat=server.domain.com
echo Before: "%fqdnstat%"
for /F "tokens=1* delims=." %%a in ("%fqdnstat%") do set "fqdnstat=%%a-r.%%b"
echo After: "%fqdnstat%"
set servername=%servername:.domain.com=-r.domain.com%
Presumably above the two lines you've put, but I'm not sure what the goal is, so maybe not.

batch script delete file when file name matches pattern

Quite nervous today, I am a long time StackOverflow voyeur about to ask my first ever question so I hope I dont suck at it. I can perform the following task easily using something like a console app but i was hoping that it would be possible to do it in a batch script, and I dont know batch scripting well at all.
I want to delete all files in a directory except those whose name matches a certain pattern. A typical example of the kind of files in this directory is as follows:
dep_invoice_101.pdf -- to delete
dep_invoice_102.pdf -- to delete
invoice_103.pdf -- to delete
invoice_106.pdf -- to delete
invoice_106_E56.pdf -- keep
deposit_invoice_101_068.pdf -- keep
i want to delete all files except those whose name matches
any string (or nothing) followed by "invoice_"
followed by any number
then an underscore
then another alphanumeric string
The final underscore is the key. if i was doing this using C# or something, i would extract the name into a string, remove all text before "invoice_" and then see if there is a remaining underscore - this would be a match, e.g.
"deposit_invoice_101_068.pdf"
search for "invoice_" and remove all text before and including this
left with "101_068.pdf"
if there are any underscores in this string then it is a match
Hope this makes sense. If this is not an appropriate question let me know.
Many thanks
for /f "tokens=*" %%a in (
'dir /a-d /b *.pdf ^| findstr /v /r /c:"invoice_[0-9][0-9]*_.*\.pdf$"'
) do echo del "%%a"
If output to console is correct, remove the echo command
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
SET "filename=%%a"
SET "filename=!filename:*invoice_=!"
IF "!filename!"=="!filename:_=!" ECHO DEL "%sourcedir%\%%a"
)
GOTO :EOF
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO DEL to DEL to actually delete the files.
You'd need to change your sourcedir to suit, naturally.
This follows your how I'd do it in C rather than your narrative spec.

CMD I need to run a FOR /f on one line of a text file (5th line normally, however this could change depending on return results)

I have managed to output a query from:
REG Query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall " /F "LanSchool Teacher" /s > %temp%\lanschool.txt
%temp%\lanschool.txt
FOR /F "delims=\" %%a in ('find "%temp%\lanschool.txt) DO (
echo token8=%%h
)
pause
However now I have the text file, and it has numerous lines of output in it.
Is it possible to do a:
FOR /F "delims=\" %%a in ('find "%temp%\lanschool.txt) DO (
echo token8=%%h
)
But I only want this to run on one line, and that line may change but the only line of that code that I want it to run on, only has one difference compared to another line of code (and that difference is the part of the code that I am trying to get into the %%h variable).
The output is this:
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Teacher
DisplayName REG_SZ LanSchool Teacher
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{89F475EE-2075-4F35-A37D-30C69916EE64}
DisplayName REG_SZ LanSchool Teacher
End of search: 2 match(es) found.
I would like to get the {89F475EE-2075-4F35-A37D-30C69916EE64} part to be token %%h however at the moment as you can see there is 2 REG Keys being output, and the only difference is the part that I want to use, and I can't always guarantee that there will only be 2 REG Keys output.
Sorry if I was all over the place explaining this, let me know if you would like anything clarified.
This line should fix it. It uses find.exe to search for the character { and if it is not found then the file will not be created, so you can branch on that.
REG Query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall " /F "LanSchool Teacher" /s |find "{" > %temp%\lanschool.txt
if not exist %temp%\lanschool.txt goto :EOF
would
for /f "tokens=2delims=}{" %%a in (
'REG Query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall " /F LanSchool Teacher" /s'
) do set mystring={%%a}
echo %mystring%
work for you?

Resources