I work for a school district and we need to remotely remove profiles. We are using RemProf. I need the script to fail if it encounters two specific domains or a device with a specific identifier in the name. I want it to exit with an error code. This will let our field staff know that they have tried to run RemProf against a device that is restricted because of domain or name. Here is what I have. The line with -SAD- identifies part of a device name. This script is not exiting if it encounters an error level of 1. It continues with RemProf and deletes profiles. I would appreciate any guidance.
Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Hostname /f -SAD-
if %ERRORLEVEL%==1 exit /b 9
Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Domain /f teach.inst.schools
if %ERRORLEVEL%==1 exit /b 0
Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Domain /f admin.schools
if %ERRORLEVEL%==1 exit /b 9
Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Domain /f elem.inst.schools
if %ERRORLEVEL%==0 goto Run_RemProf
Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Domain /f sec.inst.schools
if %ERRORLEVEL%==0 goto Run_RemProf
:Run_RemProf
Rem Deleteing profiles and abandoned files
RemProf.exe /D: /EXCLUDE:Public,Default,Administrator,SOL
RemProf.exe /AD: /EXCLUDE:Public,Default,Administrator,SOL
Your Reg Query HKLM\System\CurrentControlSet\services\Tcpip\Parameters /v Hostname /f -SAD- always returns Hostname value, along with appropriate errorlevel return value of 0 - success (or 1 - failure) regardless of data or pattern supplied in /f switch.
reg query /? is a bit short about using /V and /F switches together:
/v Queries for a specific registry key values.
If omitted, all values for the key are queried.
Argument to this switch can be optional only when specified
along with /f switch. This specifies to search in valuenames only.
/f Specifies the data or pattern to search for.
Use double quotes if a string contains spaces. Default is "*".
Another official source says about /V switch:
/v <ValueName> Specifies the registry value name that is to be
queried. If omitted, all value names for KeyName are returned.
ValueName for this parameter is optional if the /f option is
also used.
Optional? Read dictionary.com definitions for adjective optional:
common: left to one's choice; not required or mandatory;
British: possible but not compulsory; left to personal choice.
In fact, ValueName for /V parameter should be omitted if the /f option is also used (nonofficial):
To search part of the registry, use the following syntax:
REG Query HKxx\subkey [/D|/K|/V] /F "search_pattern" [/S] [/E] [/C]
Use /D to search the data (i.e. the registry values' values), /K
to search for matching key names, /V to search for matching value
names, or none of these switches to search keys, values and data.
You can:
check ERRORLEVEL from findstr command rather, or
set desired registry data to suitable environment variable and then check whether this variable contains specified substring.
Sample script (partially commented):
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_pattern=%~1" for demonstration purposes: first line parameter
if not defined _pattern set "_pattern=-SAD-"
rem next `_KeyName` variable keeps `reg query` line length <80 chars
set "_KeyName=HKLM\System\CurrentControlSet\services\Tcpip\Parameters"
echo(
echo `findstr` approach:
Reg Query "%_KeyName%" /v Hostname | findstr /I /C:"%_pattern%" >NUL
if errorlevel 1 (
echo `Hostname` data DOES NOT CONTAIN specified string "%_pattern%"
) else (
echo `Hostname` data CONTAINS specified string "%_pattern%"
)
echo(
echo `substring` approach:
rem set `_Hostname` and `_Domain`
for /F "tokens=1,2,*" %%G in ('
Reg Query "%_KeyName%" ^| findstr /I /R "\<Domain\> \<Hostname\>"
') do set "_%%G=%%I"
call set "_auxiliary=%%_Hostname:%_pattern%=%%"
if "%_auxiliary%"=="%_Hostname%" (
echo `Hostname` data DOES NOT CONTAIN specified string "%_pattern%"
) else (
echo `Hostname` data CONTAINS specified string "%_pattern%"
)
Output:
==> D:\bat\SO\39359057.bat -SAD-
`findstr` approach:
`Hostname` data DOES NOT CONTAIN specified string "-SAD-"
`substring` approach:
`Hostname` data DOES NOT CONTAIN specified string "-SAD-"
==> D:\bat\SO\39359057.bat %computername%
`findstr` approach:
`Hostname` data CONTAINS specified string "myNewPC"
`substring` approach:
`Hostname` data CONTAINS specified string "myNewPC"
==>
Related
i want to export HKEY_LOCAL_MACHINE\SOFTWARE\ABC\EFGH string XYZ value 12. i looked into regedit /e and Reg export. it gives options to export till HKEY_LOCAL_MACHINE\SOFTWARE\ABC\EFGH, but not my string value XYZ.
I can think of no native method of exporting just a particular value with its data directly as a .reg file.
The best advice would be that you parse the output from reg query for your particular value data, and save it as a reg add command to another batch file. Then when, or if, you need to replace that value data with the previously saved data, you can just run that saved batch file.
Below is a basic example, (designed only for use with value type REG_SZ). I've used a common registry subkey and value for demonstration purposes, (because yours was not clear to me); please replace those on lines 4 and 5 as per your specific requirements:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "RegistryKey=HKEY_CURRENT_USER\Control Panel\Desktop"
Set "ValueName=Wallpaper"
Set "ValueData="
For /F "Tokens=*" %%G In ('%SystemRoot%\System32\reg.exe Query "%RegistryKey%"
/V "%ValueName%" 2^>NUL ^| %SystemRoot%\System32\findstr.exe /R "\<REG_SZ\>"'
) Do (Set "ValLine=%%G" & SetLocal EnableDelayedExpansion
For /F "UseBackQ Tokens=1,*" %%H In ('!ValLine:*%ValueName%^=!'
) Do EndLocal & Set "ValueData=%%I")
If Defined ValueData Echo #%%SystemRoot%%\System32\reg.exe Add "%RegistryKey%"^
/V "%ValueName%" /T REG_SZ /D "%ValueData:"=\"%" /F 1^>NUL 1>"%ValueName%.cmd"
If the string value is successfully found, its data will be saved to a local variable %ValueData%, for further use within the script if required. In addition, a batch file with the name of the registry value, should be output to the current directory. If you wish to change that name or location, please replace %ValueName%.cmd on the last line as needed. To restore the data at a later time just run the saved batch file.
I have a batch script to add new entries based on the given IP address:
#echo off
SET NEWLINE=^& echo.
set /p ipAddress=What is the IPv4 address of the instance?
FIND /C /I "storage.app.lab" %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 ECHO %NEWLINE%^%ipAddress% storage.app.lab>>%WINDIR%\System32\drivers\etc\hosts
FIND /C /I "home.app.lab" %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 ECHO %NEWLINE%^%ipAddress% home.app.lab>>%WINDIR%\System32\drivers\etc\hosts
FIND /C /I "api.app.lab" %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 ECHO %NEWLINE%^%ipAddress% api.app.lab>>%WINDIR%\System32\drivers\etc\hosts
pause
However, I want to be able to overwrite existing entries with the domain name if a new ip address is entered. For example, if an entry with the domain name of "storage.app.lab" already exists, replace it with the new IP address.
How can I achieve that without using a backup hosts file?
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q64587777.txt"
:: I'll just use a fixed string for the IPaddress
set "IPaddress=User-input IP address"
:: remove variables starting #
FOR /F "delims==" %%a In ('set # 2^>Nul') DO SET "%%a="
FOR /f "tokens=1*delims=:" %%a IN (
'findstr /v /N /L /C:"storage.app.lab" /C:"home.app.lab" /C:"api.app.lab" "%filename1%"'
) DO set "#%%a=%%b"
(
FOR /F "tokens=1*delims==" %%a In ('set # 2^>Nul') DO echo %%b
for %%a in ("storage.app.lab" "home.app.lab" "api.app.lab") do echo %IPaddress% %%~a
)>"%filename1%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q64587777.txt containing some dummy data for my testing.
The first few lines simply establish filename variables for testing, and a recognisable string to save re-entering data in testing.
The procedure will use variables named #* for temporary storage of the "other" lines in the file in question, so first clear out any variables that may exist that start #.
Then execute findstr and "print" lines that do NOT contain (/V) any of the /L literal strings provided as /c:"string-to-EXclude" and /N number thos lines with a leading serial number followed by a colon.
The for /f tokenises the line using the : separator as a delimiter and assigning the line number to %%a (token 1) and the remainder of the line (the data in question) to %%b. Set the environment variable #%%a to the lines found.
Then use the same principle on a set # list, which will list all variables starting # in the format #1=line one, delimiting on = and selecting the 2nd token, which is the line data originally read from the file.
And add the three new lines by construction.
Parenthesising the two for statements together gathers the echoed output which is then redirected to the original file, overwriting it.
Note that OP's code appended the (up to) three new lines. The requirement is (apparently) that the 3 lines will appear in the file, replacing any existing data for those three entries.
Trying to record a user client IP for a remote session. Currently have a little batch file recording logon times, and hostname. Need to also include the client IP address;
Currently using this;
reg query "HKEY_CURRENT_USER\Volatile Environment" /s > %temp%\IPINFO.txt
findstr /L ViewClient_IP_Address %temp%\IPINFO.txt > %temp%\IPRESULTS.txt
FOR /F “tokens=* delims= ” %%a in (%temp%\IPRESULTS.txt) do set IP=%%a
del %temp%\IPRESULTS.txt
set IP=%IP%
echo Login ,%Date%,%Time%,%computername%,%clientname%,%IP% >> Y:\%username%.csv
The registry key viewclient_ip_Address has the information I need, but the registry folder it sits within changes name each time so I'm having to export the whole directory and then filter for the key itself.
I just need to add the information from that IPRESULTS.txt into my end .csv file but struggling with writing it up.
Any help appreciated.
Is this what you're looking for? (The for-loop runs the command and parses it's output in memory)
For /F "EOL=HTokens=2*" %%H In ('^""%__AppDir__%reg.exe" Query "HKCU\Volatile Environment" /V ViewClient_IP_Address 2^>NUL^"')Do Set "IP=%%~I"
To find out more about how to use reg.exe with query, open up a Command Prompt window and enter reg query /?
If, as you've stated in your question, the required value and data is located under HKEY_CURRENT_USER\Volatile Environment but within a variable/unknown, subkey name, the help information should show you that you can use the /F option to locate your known value name, ViewClient_IP_Address, if you specify that the search is to locate a value using /V, it should retrieve the line you need.
For example, at the Command Prompt:
Reg Query "HKCU\Volatile Environment" /S /F "ViewClient_IP_Address" /V
Returns:
C:\Users\smith_ll>Reg Query "HKCU\Volatile Environment" /S /F "ViewClient_IP_Add
ress" /V
HKEY_CURRENT_USER\Volatile Environment\UnknownSubKey
ViewClient_IP_Address REG_SZ 192.168.1.15
End of search: 1 match(es) found.
You can then put that command into your for-loop, and pass its output through find.exe to isolate the line you need to parse. The underscore, for instance, looks unique to just the line you need. As we're already excluding any line beginning with H ,(with EOL=H), it will not match the End of search: 1 match(es) found. line:
Example:
For /F "EOL=HTokens=2*" %%H In ('^""%__AppDir__%reg.exe" Query "HKCU\Volatile Environment" /S /F "ViewClient_IP_Address" /V 2^>NUL^|"%__AppDir__%find.exe" "_"^"')Do #Set "IP=%%~I"
If you don't like the super long line, you can split into more using the caret:
For /F "EOL=HTokens=2*" %%H In ('^""%__AppDir__%reg.exe" Query^
"HKCU\Volatile Environment" /S /F "ViewClient_IP_Address" /V 2^>NUL^
^|"%__AppDir__%find.exe" "_"^"')Do #Set "IP=%%~I"
I have a situation here that is as followed:
I've extracted a registry value under HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders with folder locations.
The problem is that the code works for a path that has a space in it, but if i use the very same code for a path that has no spaces in it, the output is wrong.
I know it is related to tokens but i'm hoping there is a way to make the code work for both cases .
The code i currently have looks as followed:
FOR /F "tokens=2*" %I in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Startup ') DO echo "%J"
and the output:
"%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
On a side note: expanding %USERPROFILE% is no problem for me, i simply use the CALL function for that
Now, when changing the path of registry value Startup to something that doesn't have any spaces in it, the before mentioned code fails.
Hopefully someone has a way to make it work in both cases.
With best regards,
copyitright
One of the requirements of the for /f command usage is the correct use (when needed) of delims and tokens clauses. They have to be properly adapted to the format of the line(s) being processed.
Your problem here is that the output of the reg.exe command does not include a clear, unmistakable delimiter. We usually use the default space/tab delimiters to process the reg.exe output but as you have found, sometimes the general format has to been adapted to process different lines as
Cache REG_EXPAND_SZ %USERPROFILE%\AppData\Local\Microsoft\Windows\INetCache
My Pictures REG_EXPAND_SZ %USERPROFILE%\Pictures
In the second line the additional space present in the value name requires a different tokens clause when using space as delimiter.
And no, there is not any universal way of dealing with the output of the reg.exe command. You need to know what you request and adapt to it.
An alternative, if you know your value names will not include a underscore is to use it as a delimiter. This will split the line in the REG_* value type, leaving a token that can be splitted using the space as a delimiter
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "skip=2 tokens=1,* delims=_" %%a in ('
reg query
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
/v "My Pictures"
') do for /f "tokens=1,*" %%c in ("%%b") do echo "%%d"
Another alternative is to use another way to retrieve the value. You can use wmic to query the registry. Something like (sorry, spanish locale)
W:\>wmic /NameSpace:\\root\default Class StdRegProv Call GetStringValue hDefKey="&H80000001" sSubKeyName="Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" sValueName="My Pictures"
Ejecutando (StdRegProv)->GetStringValue()
Ejecución correcta del método.
Parámetros de salida:
instance of __PARAMETERS
{
ReturnValue = 0;
sValue = "C:\\Users\\UserName\\Pictures";
};
This output can be processed by retrieving the sValue line and using the quotes as delimiters (not the only way, just an example)
#echo off
setlocal enableextensions disabledelayedexpansion
for /f tokens^=2^ delims^=^" %%a in ('
WMIC /NameSpace:\\root\default Class StdRegProv
Call GetExpandedStringValue
hDefKey^="&H80000001"
sSubKeyName^="Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
sValueName^="My Pictures"
^| find "sValue"
') do echo "%%~fa"
note: The wmic sample code uses the Shell Folders subkey instead of the User Shell Folders because the wmic was expanding %userprofile% to the system user profile folder and I'm not sure if this is a default/logic behaviour or it is a problem in my machine. When I have another machine at hand I will test it.
This solution does not "make FOR /F tokens more universal", but get the value placed after "REG_EXPAND_SZ " string instead that, IMHO, is what you want...
#echo off
setlocal
for /F "delims=" %%a in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Startup') do set "value=%%a"
set "value=%value:*REG_EXPAND_SZ =%"
echo "%value%"
reg.exe uses four consecutive SPACEs to separate value names, data types and values from each other in the output (after an empty line and the line holding the key):
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
Startup REG_EXPAND_SZ %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
So, given that the value does never contain such four SPACEs on its own, you could replace them by a character that does never occur in the value either, then use this one as the delimiter, e. g., the |:
#echo off
rem // The `skip=2` option skips the empty line and the key from being iterated:
for /F "skip=2 delims=" %%R in ('
reg query ^
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" ^
/v "Startup"
') do (
rem // Store line of interest in environment variable:
set "LINE=%%R"
rem // Toggle delayed expansion to not lose exclamation marks:
setlocal EnableDelayedExpansion
rem /* Replace ` ` by `|` and use the latter as the delimiter character;
rem token 1 is dismissed but is included for the loop to iterate even in case
rem the 3rd token, namely the value, was empty: */
for /F "tokens=2,* delims=|" %%V in ("!LINE: =|!") do (
endlocal
echo(%%W
)
)
This approach fails in case the value name contains four consecutive SPACEs or the used delimiter character |.
Alternatively, you could search for the string 4 × SPACE + REG_, because all registry data types begin with REG_; then from the string behind that, remove everything up to the next four consecutive SPACEs to extract the value:
#echo off
rem /* The `eol=H` option skips the line with the key (`HKEY_*`) from being iterated;
rem the empty line is skipped anyway by `for /F`: */
for /F "delims= eol=H" %%R in ('
reg query ^
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" ^
/v "Startup"
') do (
rem // Store line of interest in environment variable:
set "LINE=%%R"
rem // Toggle delayed expansion to not lose exclamation marks:
setlocal EnableDelayedExpansion
rem /* Remove everything up to ` REG_`, so the value name is split off;
rem this works only because every value type begins with `REG_`: */
set "LINE=!LINE:* REG_=!"
rem // Then remove everything up to ` `, so the actual value remains:
echo(!LINE:* =!
endlocal
)
This approach fails in case the value name (not the value) contains four consecutive SPACEs followed by the string REG_.
Due to the fact that there are a very limited number of known registry data types, we could even search the line for these strings, preceded and followed by four SPACEs:
#echo off
rem /* The `eol=H` option skips the line with the key (`HKEY_*`) from being iterated;
rem the empty line is skipped anyway by `for /F`: */
for /F "delims= eol=H" %%R in ('
reg query ^
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" ^
/v "Startup"
') do (
rem // Store line of interest in environment variable:
set "LINE=%%R"
rem // Toggle delayed expansion to not lose exclamation marks:
setlocal EnableDelayedExpansion
rem /* Loop through the possible registry value data types, search the line for
rem ` ` + a data type name + ` ` and remove everything up to that: */
for %%T in (
REG_SZ,REG_MULTI_SZ,REG_EXPAND_SZ,REG_DWORD,REG_QWORD,REG_BINARY,REG_NONE
) do (
set "LINE=!LINE:* %%T =!"
)
echo(!LINE!
endlocal
)
Since it is very unlikely that the search strings occur in the value name and the value itself, I consider this as the most reliable method when using the reg command.
Problem: The below batch program exits when trying to run the 1st for loop, and %file3% txt file only has:
Displayname
-------------
Need advice on why the for loop is not working please.
Partial output of REG query in 1st for loop in a text file:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Adobe AIR
DisplayName REG_SZ Adobe AIR
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cisco AnyConnect Secure Mobility Client
DisplayName REG_SZ Cisco AnyConnect Secure Mobility Client
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb
DisplayName REG_SZ Citrix Receiver
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\KLiteCodecPack_is1
DisplayName REG_SZ K-Lite Codec Pack 10.7.5 Basic
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Mobile Broadband HL Service
DisplayName REG_SZ Mobile Broadband HL Service
Desired output in %file3%:
Displayname
-------------
Adobe AIR
Cisco AnyConnect Secure Mobility Client
Citrix Receiver
K-Lite Codec Pack 10.7.5 Basic
Mobile Broadband HL Service
Batch code:
#echo OFF
setlocal enableextensions enabledelayedexpansion
set "Version_tool=v2"
Echo Version: %Version_tool%
Echo Modified 19/01/15 by xxx
SET "ComputerName=%computername%"
echo ComputerName is: %ComputerName%
SET "file3=%~dp0%computername%-programs_unsorted.txt"
echo File3 is: %file3%
If Exist %file3% Del %file3%
echo Displayname >> %file3%
echo ------------- >> %file3%
set "keyname=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
echo keyname is: !keyname!
Rem === Problem is below - program exits when running for loop ===
For /f "usebackq tokens=* delims=" %%A in (`REG Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" /V /F DisplayName /S /E`) do (
pause
set "DisplayName=%%A"
echo DisplayName is: !Displayname!
pause
set "Display_Substring=!DisplayName:~0,71!"
echo Display_Substring is: !Display_Substring!
pause
if not "!DisplayName:HKEY_LOCAL_MACHINE=!"=="!DisplayName!" echo !DisplayName! >> %file3%
::if !DisplayName:~0,71!==HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ (
:: echo skipping !DisplayName!
::) else (
:: echo !DisplayName! >> %file3%
::)
)
Problems:
1) You specify usebackq, but you used single quotes, so FOR /F processes the string instead of the command. Drop the usebackq and the loop will process the command properly. The only time I ever use usebackq is when I am reading from a file whose path must be quoted, typically because of spaces.
2) Your IF statement is a mess:
Your command uses normal expansion instead of delayed expansion, so it cannot see the value set within the loop.
You used = but the comparison operator is ==.
Values should be quoted on both sides of the comparison when using delayed expansion substring operation within an IF statement, or you must escape the comma. I recommend the quotes (actually you don't even need the IF at all)
if "!DisplayName:~1,71!"=="yourValue..."
3) You want to exclude the summary line of output. The simplest solution is to pipe the output to FIND or FINDSTR and let it filter out lines you don't want. The pipe operator must be escaped within the IN() clause.
4) You can let FOR /F parse out the columns (tokens). You want the 3rd column, which contains spaces. None of the prior columns contain spaces, so you can use tokens=2*, which means capture the 2nd token in the first variable, and preserve everything after that in the second variable.
for /f "tokens=2*" %%A in (
'REG Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" /V /F DisplayName /S /E^|find "DisplayName"'
) do echo %%B>>"%file3%"