Appending string data to an existing REG_MULTI_SZ Windows registry entry - batch-file

REG ADD changes the entire entry. I have not been able to make REG ADD ~ work.
Windows registry contains multiple string zero values. This is what REG_MULTI_SZ means. How can a new string be appended? REG ADD deletes all string previously in the entry and writes only the new one there although REG_MULTI_SZ is specified in the REG ADD command.
Some say ~ before the string means append instead of overwrite. However, I do not what the exact syntax is. How can I use ~?
[Edit]Here is the simplified version of the question :
I have a registry entry KEYROOT\KEY\ENTRY which is type REG_MULTI_SZ. In this entry, there are string zeroes abcd\0 and efgh\0. How can I add ijkl\0 in order to have all three: abcd, efgh and ijkl in the registry entry \ENTRY and not only ijkl?
I want to do this only with Batch Script or Command Prompt commands.
Please, note : I have tried many things with REG and am unable to find a solution and I am not sure whether there is such.
I will be very thankful for any suggestions but I would like to ask you all to concentrate on the ~ possibility. Microsoft says when there is ~ before the string, the string is considered to be appended to the other strings and not to overwrite them.
I have tried many variations but am unable to get the correct syntax of ~. Please, do provide information on how to use ~ before the string to be appended.
I found a solution. However, although the solution works, to add a string to the registry entry is not a good idea because Microsoft allows strings to be appended with hex data. Anyway, here is what I have been able to do :
Read the value of the registry in a batch string variable :
FOR /F "usebackq tokens=2,* skip=2" %%G IN ('REG QUERY "Root\Key" /v Entry') DO SET EntryContents=%%H
Note the reverse apostrophes `.
Now, the entry of the registry key is in the variable EntryContents.
Concatenate the new value to the old value
SET NewEntryContents=%EntryContents%%ContentsToBeAppended%
The variable ContentsToBeAppended has been set elsewhere in the batch file or may be a parameter. The variable NewEntryContents contains the concatenated strings of the old registry key entry contents and the string which is in the variable ContentsToBeApended.
Add NewEntryContents to the entry with REG ADD.
Again, when the entry value is read into a string variable, all hex contents would be ignored in case they are 00's or other values which may be out of the character range. A solution may be to somehow export the entry with REG to a file in hex format and then to somehow add only hex values to the file. The string characters must be converted to their hex values and appended to the file as well as any new hex values.
This answer provides the ability to read a registry entry which would be read in full with all characters such as \0 in a string variable. The string variable will get all characters. Example : In case the registry entry contains PATH\NAME_OF_FILE\0PATH|NAME_OF_FILE, all these will be read into the string variable. \0 too. Just concatenate the new string, which may also contain\0's, and reg add the overall string back to the registry.
The trick here is the for /f statement which skips 2 lines and takes the second string of the third line in G and the third ( the important one ) in H. All blanks and *'s, .'s, dits will be read too.
In order to add all blanks and *'s etcetera back to the entry with reg add, enclose the variable NewEntryContents in quotes :
REG ADD "Root\Key" /v Entry /t REG_MULTI_SZ /d "%NewEntryContents%"
Hope this may help.
Also, the [~] sign works only when REGEDIT is used. REGEDIT is a better approach. Can save a key as is ( with hex ) in a file, then the file can be edited in the batch and then the newly edited key can be imported back to the registry. Pretty nasty, though. Also, I am not sure whether REGEDIT would export the strings and the hex data combined to the file.
Here are the checks for the availability of the entry and for an empty entry :
This checks whether the entry is there or not at all :
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager" /v PendingFileRenameOperations
IF %ERRORLEVEL% EQU 0 GOTO THEREIS
After the for /f :
SET "EntryContents"="%EntryContents: =%" IF DEFINED EntryContents GOTO NOTEMPTY
The SET line is not necessary. Gets rid of blanks around the string. This is supposed to be done by the for /f anyway.
If defined checks the value. Best EntryContents never to have been defined before the for /f.
OK. I have managed to overcome all problems with batch script only.
Echo does echo all ASCII characters and can be made to output Unicode too, however, there are many more problems.
Anyway, I am unable to provide more information because of the amount of problems and solutions BUT, whoever is interested, can read the batch file I have made : http://www.steven-stanley-bayes.com/ForceDelete.zip

Lean and mean batch-file alternative to the ~50KB script linked by OP:
~ Accepting a single parameter, either File or Folder
~ Confirmation prompt ([Cancel] to Clear previous entries)
~ Basic idiot proofing (don't process %Windir% for example)
~ Scripts will add an entry to right-click -- "SendTo" menu on first run
Rename_On_Boot.bat
goto="Batch" /* Rename_On_Boot by AveYo v1
:RenOnBoot
set "input=%*" & call set "input=%%input:?=%%" &rem line below adds entry to right-click -- "SendTo" menu
if /i "_%~dp0"=="_%APPDATA%\Microsoft\Windows\SendTo\" (set .=) else copy /y "%~f0" "%APPDATA%\Microsoft\Windows\SendTo\" >nul 2>nul
if "_%1"=="_" color 4f & echo ERROR! No input provided & ping -n 6 localhost >nul & exit /b
for %%# in ("C:\" "C:\Boot" "C:\Recovery" "%WINDIR%" "%WINDIR%\system32" "%ProgramData%" "%ProgramFiles%" "%USERPROFILE%") do (
if /i "_%input%"=="_%%~#" color 4f & echo ERROR! %%# is not safe to delete & ping -n 6 localhost >nul & exit /b
)
color 0B & echo Please wait, folders might take a while .. & call cscript /nologo /e:JScript "%~f0" RenOnBoot "%input%" & exit /b
:RenOnBoot_Run_As_Admin
color 4f & echo Asking permission to run as Admin.. & call cscript /nologo /e:JScript "%~f0" RunAsAdmin "%~f1???" & exit /b
:"Batch"
#echo off & setlocal disabledelayedexpansion & mode 96,4 & echo. & title %~nx0 by AveYo & if not exist "%~f1" goto :RenOnBoot
reg query HKEY_USERS\S-1-5-20\Environment /v temp 1>nul 2>nul && goto :RenOnBoot || goto :RenOnBoot_Run_As_Admin
:"JScript" */
function RenOnBoot(f){
var HKLM=0x80000002, k='SYSTEM\\CurrentControlSet\\Control\\Session Manager', v='PendingFileRenameOperations';
var reg=GetObject('winmgmts:{impersonationLevel=impersonate}!//./root/default:StdRegProv'), ws=WSH.CreateObject('WScript.Shell');
var confirmation=ws.Popup(" Rename on next boot? [OK]\n Clear previous entries? [Cancel]\n\n "+f,0,'Rename_On_Boot by AveYo',33);
if (confirmation == 2) { reg.DeleteValue(HKLM, k, v); WSH.quit(); } // Clear existing entries on Cancel press and quit script
var mtd=reg.Methods_('GetMultiStringValue').InParameters.SpawnInstance_(); mtd.hDefKey=HKLM; mtd.sSubKeyName=k; mtd.sValueName=v;
var query=reg.ExecMethod_('GetMultiStringValue', mtd), regvalue=(!query.ReturnValue) ? query.SValue.toArray():[,], entries=[];
var fso=new ActiveXObject('Scripting.FileSystemObject'), fn=fso.GetAbsolutePathName(f);
entries.push('\\??\\'+fn,'\\??\\'+fn+'.ren');
reg.CreateKey(HKLM, k); reg.SetMultiStringValue(HKLM, k, v, entries.concat(regvalue));
}
if (WSH.Arguments.length>=2 && WSH.Arguments(0)=='RenOnBoot') RenOnBoot(WSH.Arguments(1));
function RunAsAdmin(self, arguments) { WSH.CreateObject('Shell.Application').ShellExecute(self, arguments, '', 'runas', 1) }
if (WSH.Arguments.length>=1 && WSH.Arguments(0)=='RunAsAdmin') RunAsAdmin(WSH.ScriptFullName, WSH.Arguments(1));
//
Delete_On_Boot.bat
goto="Batch" /* Delete_On_Boot by AveYo v1
:DelOnBoot
set "input=%*" & call set "input=%%input:?=%%" &rem line below adds entry to right-click -- "SendTo" menu
if /i "_%~dp0"=="_%APPDATA%\Microsoft\Windows\SendTo\" (set .=) else copy /y "%~f0" "%APPDATA%\Microsoft\Windows\SendTo\" >nul 2>nul
if "_%1"=="_" color 4f & echo ERROR! No input provided & ping -n 6 localhost >nul & exit /b
for %%# in ("C:\" "C:\Boot" "C:\Recovery" "%WINDIR%" "%WINDIR%\system32" "%ProgramData%" "%ProgramFiles%" "%USERPROFILE%") do (
if /i "_%input%"=="_%%~#" color 4f & echo ERROR! %%# is not safe to delete & ping -n 6 localhost >nul & exit /b
)
color 0B & echo Please wait, folders might take a while .. & call cscript /nologo /e:JScript "%~f0" DelOnBoot "%input%" & exit /b
:DelOnBoot_Run_As_Admin
color 4f & echo Asking permission to run as Admin.. & call cscript /nologo /e:JScript "%~f0" RunAsAdmin "%~f1???" & exit /b
:"Batch"
#echo off & setlocal disabledelayedexpansion & mode 96,4 & echo. & title %~nx0 by AveYo & if not exist "%~f1" goto :DelOnBoot
reg query HKEY_USERS\S-1-5-20\Environment /v temp 1>nul 2>nul && goto :DelOnBoot || goto :DelOnBoot_Run_As_Admin
:"JScript" */
function DelOnBoot(f){
ListDir=function(src, _root,_list) {
_root=_root || src, _list=_list || [];
var root=fso.GetFolder(src), files=new Enumerator(root.Files), dirs=new Enumerator(root.SubFolders);
while (!files.atEnd()) { _list.push(files.item()); files.moveNext(); }
while (!dirs.atEnd()) { _list=ListDir(dirs.item().path, _root,_list); _list.push(dirs.item()); dirs.moveNext(); }
return _list;
};
var HKLM=0x80000002, k='SYSTEM\\CurrentControlSet\\Control\\Session Manager', v='PendingFileRenameOperations';
var reg=GetObject('winmgmts:{impersonationLevel=impersonate}!//./root/default:StdRegProv'), ws=WSH.CreateObject('WScript.Shell');
var confirmation=ws.Popup(" Delete on next boot? [OK]\n Clear previous entries? [Cancel]\n\n "+f,0,'Delete_On_Boot by AveYo',33);
if (confirmation == 2) { reg.DeleteValue(HKLM, k, v); WSH.quit(); } // Clear existing entries on Cancel press and quit script
var mtd=reg.Methods_('GetMultiStringValue').InParameters.SpawnInstance_(); mtd.hDefKey=HKLM; mtd.sSubKeyName=k; mtd.sValueName=v;
var query=reg.ExecMethod_('GetMultiStringValue', mtd), regvalue=(!query.ReturnValue) ? query.SValue.toArray():[,], entries=[];
var fso=new ActiveXObject('Scripting.FileSystemObject'), fn=fso.GetAbsolutePathName(f);
if (fso.FolderExists(fn)) { var list=ListDir(fn); for (var i in list) entries.push('\\??\\'+list[i],''); }
entries.push('\\??\\'+fn,'');
reg.CreateKey(HKLM, k); reg.SetMultiStringValue(HKLM, k, v, entries.concat(regvalue));
}
if (WSH.Arguments.length>=2 && WSH.Arguments(0)=='DelOnBoot') DelOnBoot(WSH.Arguments(1));
function RunAsAdmin(self, arguments) { WSH.CreateObject('Shell.Application').ShellExecute(self, arguments, '', 'runas', 1) }
if (WSH.Arguments.length>=1 && WSH.Arguments(0)=='RunAsAdmin') RunAsAdmin(WSH.ScriptFullName, WSH.Arguments(1));
//

Although not requested, you could probably use something like this in PowerShell:
$key = Get-Item "KEYROOT:\KEY\"
$values = $key.GetValue("ENTRY")
$values += "ijkl"
Set-ItemProperty "KEYROOT:\KEY\" "ENTRY" $values -Type MultiString
Change KEYROOT, KEY & ENTRY to their genuine strings

The following batchfile does the job in four steps:
export the value into a file,
extract the value using the for command
in the subroutine
if the value is valid, concat the string and
finally write the value back.
In this code, HKCU\Software\AITEM is the registry key and AVALUE is the Name of the value. Finally "newstring" is the string you want to add to your list.
The echo command is just for debugging purposes an can be deleted.
The code only works if the key AITEM and the value AVALUE already exist and if AVALUE already has at least one string in its list.
#echo off
reg query HKCU\Software\AITEM /v AVALUE > tmp.txt
FOR /F "tokens=2,3*" %%a in (tmp.txt) do call :sub1 %%b
del tmp.txt
:sub1
if %1x==x goto end
echo %1
REG ADD HKCU\Software\AITEM /f /v AVALUE /t REG_MULTI_SZ /d %1\0newstring
:end
goto :eof
The following code also works if AVALUE does not exist or is empty:
#echo off
reg query HKCU\Software\AITEM /v AVALUE > tmp.txt
find "AVALUE" tmp.txt
if errorlevel 1 goto sub2
FOR /F "tokens=2,3*" %%a in (tmp.txt) do call :sub1 %%b
del tmp.txt
goto :eof
:sub2
REG ADD HKCU\Software\AITEM /f /v AVALUE /t REG_MULTI_SZ /d newstring
goto :eof
:sub1
REG ADD HKCU\Software\AITEM /f /v AVALUE /t REG_MULTI_SZ /d %1\0newstring
if errorlevel 1 REG ADD HKCU\Software\AITEM /f /v AVALUE /t REG_MULTI_SZ /d newstring
goto :eof

Related

How do I create HELP command for custom BAT files?

I have written small script for converting text to uppercase as shown below and saved this file as .BAT extension
`converttoupper.bat`
I want user to try "help" command, so that they get the help on syntax for using the commands as shown below
help converttoupper
something like this
# help converttoupper
For more information on a specific command, type HELP command-name
CONVERTTOUPPER This converts the text to upper case
Update
I am fine even if I get something as shown below. I do not want to overwrite any windows command.
helpme converttoupper
or
helpme connectvpn
I have many BAT files, and wish to display respective helps when each executed.
You can create a "fake" function. Let's call this define.cmd and place it in %systemroot%\system32
We add the code:
#echo off
for /f "tokens=1,*delims=? " %%i in ('type "%~1" ^|findstr ":?"') do echo %%j
Then in all your batch files you want people to read the help for, add the help lines by starting them off with a :? using your convertoupper.cmd file as example:
#echo off & set upper=
if "%~1" == "" echo incorrect usage & call define.cmd "%0"
if "%~1" == "/?" call define.cmd "%0"
for /f "skip=2 delims=" %%I in ('tree "\%~1"') do if not defined upper set "upper=%%~I"
set "upper=%upper:~3%"
echo %upper%
goto :eof
:? # help converttoupper
:? "define %0" or "%0 /?" will display this help content
:? For more information on a specific command, type HELP command-name
:? CONVERTTOUPPER This converts the text to upper case
Now you can run define converttoupper or converttoupper /?. If you run converttoupper without any arguments, it will also display the same help.
Below is an example of safely handling arg capture and help enqueries.
After arguments are safely Captured, Findstr is used to test the content for valid help switches:
Set Args | %SystemRoot%\System32\Findstr.exe /bli "Args=\/? Args=-? Args=Help?" > nul && (Rem commands)
Set Args : allows the argument string to be piped to findstr without any risk of failure due to poison characters.
/bli : findstr sawitches : match literal string at beginning of line ignoring case.
"Args=\/? Args=-? Args=Help?" : Space delimited list of strings to match; treated as match string a or b or c
> nul : Suppress the output of any match
&& : Conditional operator; 'On command success'
Note: Terminating each help switch with ? allows use of substring modification to remove the leading switch and space and directly Call a label prefixed with the query keyword
#Echo off & SETLOCAL
=========================================================================
Rem -- Arg capture method is a modified version of Dave Benhams method:
Rem -- https://www.dostips.com/forum/viewtopic.php?t=4288#p23980
SETLOCAL EnableDelayedExpansion
1>"%~f0:Params.dat" <"%~f0:Params.dat" (
SETLOCAL DisableExtensions
Set prompt=#
Echo on
For %%a in (%%a) do rem . %*.
Echo off
ENDLOCAL
Set /p "Args="
Set /p "Args="
Set "Args=!Args:~7,-2!"
#Rem duplicate Args for the purpose of counting doublequotes [destructive].
Set "DQcount=!Args!"
) || (
Echo(%~nx0 requires an NTFS drive system to function as intended.
CMD /C Exit -1073741510
) || Goto:Eof
If Not defined Args Goto:NoArgs
REM substitute doublequotes in Args clone 'DQcount'; count substring in string;
REM assess if count is even; If false "||": Remove doublequotes from string. If true "&&" and if entire
REM arg line is doublequoted, remove outer quotes.
Set Div="is=#", "1/(is<<9)"
Set "{DQ}=0"
Set ^"DQcount=!DQcount:"={DQ}!"
2> nul Set "null=%DQcount:{DQ}=" & Set /A {DQ}+=1& set "null=%"
Set /A !Div:#={DQ} %% 2! 2> nul && Set ^"Args=!Args:"=!" || If [^%Args:~0,1%^%Args:~-1%] == [""] Set "Args=!Args:~1,-1!")
For /f Delims^= %%G in ("!Args!")Do Endlocal & Set "Args=%%G" 2> nul
:NoArgs
=====================================================================
Rem help query assessment
(
Set Args | %SystemRoot%\System32\Findstr.exe /bli "Args=\/? Args=-? Args=Help?" > nul && (
Rem Args value has leading /? -? or help?
If not "%Args:*?=%"=="" (
Rem Args value contains leading /? -? or help? with additional Parameter
Call:%Args:*? =%_Syntax && Goto:Eof || (
Rem quit after Call to Syntax info if valid Parameter; else notify invalid and show valid syntax queries.
Echo(Invalid query: "%Args:*? =%" : Does not Match a valid Help Query:
)
)
Rem show valid syntax queries.
For /F "Tokens=1 Delims=:_" %%G in ('%SystemRoot%\System32\Findstr.exe /R "^:.*_Syntax" "%~f0"') Do Echo(%~nx0 /? %%G
ENDLOCAL & Exit /b 0
)
) 2> nul
Set Args
Goto:Eof
Rem Demo syntax labels
:Demo_Syntax
Echo %~0 help info
Exit /b 0
:Example_Syntax
Echo %~0 help info
Exit /b 0

Batch file to edit .ini file but do not delete blank space

I am new to StackOverflow. I want to run a batch file to find and replace a single string in an .ini file. I tried several solutions given on stackoverflow and other sites too.
A few of them are working - but delete my other lines having "space" or ";".
Here is the string that I want to find and change in my file RDConfigSettings.ini
CommunicationMode:1
I want it vice-versa:
if it is "CommunicationMode:1" then change it to "CommunicationMode:0"
if it is "CommunicationMode:0" then change it to "CommunicationMode:1"
Here is the whole content of my RDConfigSettings.ini file
;0 for Staging, 1 for Pre-Production, 2 for Production
RDEnviroment:2
;0 for disable, 1 for Enable
RDServiceLogs:0
;0 for disable, 1 for Enable
ClientValidation:0
;Validate Management Server Certificate -- 0 for Yes, 1 for No
ValidateCertificate:0
;Proxy Configuration -- 0 for Direct Internet Access, 1 for Access via Proxy
ProxyConfig:0
ProxyIP:[Proxy IP]
ProxyPort:[Proxy Port]
;0 for Https, 1 for Http
CommunicationMode:1
;Port Range Setting in below field
PortBegin:11100
PortEnd:11120
;ManagementServerURL
Registration:https://rdm.smartbioplus.com/rdm-device-app/registration
Keyrotation:https://rdm.smartbioplus.com/rdm-key-management-app/keyRotation
Telemetry:https://rdm.smartbioplus.com/rdm-telemetry-app/telemetry
Domain:rdm.smartbioplus.com
URL_Port:443
Could anyone help me? THis is my code:
#echo off
set "file=E:\CSC Softwares\MorphoRdServiceL0Soft\RDConfigSettings.ini"
:loop
findstr "^CommunicationMode:0$" "%file%" >nul || (
type "%file%"|repl "^CommunicationMode:1" "CommunicationMode:0" >"%file%.tmp"
move "%file%.tmp" "%file%" >nul
)
timeout 120 >nul
goto :loop
Moreover, it will be a great help if someone can add an Command with administrative rights that will stop a particular service "MORPHO_RD_Service" before replacing the string and then after replace the string, start the same service again.
You have code to switch from 1 to 0, but no code to switch from 0 to 1.
Below code alternates between 1 and 0 with each run of the loop.
I also changed to jrepl (more modern and powerful). It isn't necessary (though possible) to process piped data and redirect the result to another file. The /f switch gives the inputfile to process, the /o switch gives the outputfile. By giving it a single -, it uses the same filename as the input file (and overwrites it with the new(changed) data).
#echo off
set "file=t.txt"
:loop
findstr "^CommunicationMode:" "%file%" & REM this line for troubleshooting only
findstr "^CommunicationMode:0$" "%file%" >nul && (
call jrepl "CommunicationMode:0" "CommunicationMode:1" /f "%file%" /o -
) || (
call jrepl "CommunicationMode:1" "CommunicationMode:0" /f "%file%" /o -
)
timeout 1 >nul
goto :loop
Don't forget to adapt the data file name and the timeout to your needs.
Without the need for an external utility such as jrepl, which is great for some things, but not needed for such a task:
#echo off
setlocal enabledelayedexpansion
set "file=E:\CSC Softwares\MorphoRdServiceL0Soft\RDConfigSettings.ini"
for /f "tokens=1,*delims=]" %%i in ('type "%file%" ^| find /v /n "" ^& break^>"%file%"') do (
set "line=%%j"
if "!line!" == "CommunicationMode:1" (
set "line=!line:1=0!"
set "hold=!line!"
) else if "!line!" == "CommunicationMode:0" (
set "line=!line:0=1!"
set "hold=!line!"
)
echo(!line!>>"!file!"
)
echo Changed to !hold!
pause

Changing a flag in the ini file from batch script

I have a script which will check if the file names and the content of the files are same or not, below is the code and it is working fine
ECHO OFF
CLS
for %%i in (C:\Users\f1ym41a\Documents\deep\*.DAT) do (
fc C:\Users\f1ym41a\Documents\deep\MOVE.DAT %%i > NUL
if errorlevel 1 (
CALL :error
echo C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are different >>output.log
) ELSE (
CALL :next
echo C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are same >>output.log
)
timeout 5
)
PAUSE
What i need to do is if the file names are same then it will change the flag in the ini file to 1. Below is the ini file (deep.ini)
[INI]
flag = 0
Since i am new to batch scripting. Can somebody help me out with this?
You can try with replacer.bat:
call replacer.bat move.dat "flag = 0" "flag = 1"
This is an easy to achieve task with using JREPL.BAT written by Dave Benham which is a batch file / JScript hybrid to run a regular expression replace on a file using JScript.
#echo off
if not exist "%USERPROFILE%\Documents\deep\MOVE.DAT" goto :EOF
if not exist "%~dp0jrepl.bat" goto :EOF
call "%~dp0jrepl.bat" "^(flag *= *)0" "$11" /F "%USERPROFILE%\Documents\deep\MOVE.DAT" /O -
The batch file first checks if the file to modify exists at all and immediately exits if this condition is not true, see Where does GOTO :EOF return to?
The batch file JREPL.BAT must be stored in same directory as the batch file with the code above. For that reason the batch file checks next if JREPL.BAT really exists in directory of the batch file and exits if this condition is not true.
The meaning of the regular expression search string is:
^ ... find at beginning of a line
(...) ... a string referenced in replace string with $1 to keep this part of found string unmodified
flag ... case-sensitive the string flag
 * ... with 0 or more spaces
= ... and an equal sign
 * ... and once more 0 or more spaces
0 ... and the character 0.
The replace string back-references the found string between beginning of line and character 0 with $1 and replaces 0 by 1.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains also %~dp0 ... drive and path of argument 0 which is the batch file path always ending with a backslash.
echo /?
goto /?
if /?
jrepl.bat /?
:: 1st need remove some possible space in the string to got more precision
when compare them: "flag = 0" will became "flag=0", no
space and no tab.
:: 2nd for to do this, use this "' (2 characters) to set a variable that
use "=" to string instead a special character,
by set "'=flag=0" (very old technical!)
:: 3rd treat equal, treat tab character, and to remove it, because some time
this is a invisible and possible character that can eventually occur
in file dat, see in this question 10878138
:: 4th Compare the strings by string from file by file, line by line...
:: finely You need replace line in the file (.dat or .ini) this part I´m really confuse, but the code are above, sorry if my error!
Obs: use the conversion of this "flag = 0" this this one "flag=0", only for processing comparatives operation, wend the %%i match flag = 0 then only changed to replace to files by flag = 1, bat, a specific thing here is the command fc are comparing %%i, by the same file in looping for with no other file.
#echo off && setlocal EnableExtensions EnableDelayedExpansion
set "'=flag=0"
set _file_new_flag1="%temp%\Flag1.dat"
set _path_to_dats=C:\Users\f1ym41a\Documents\deep\
for /f "delims= " %%T in ('forFiles /p "." /m "%~nx0" /c "cmd /c echo(0x09"') do set "_tab=%%T"
type nul >output.log && set "_tab=%_tab:~0,1%"
cd /d "!_path_to_dats!"
for /f "tokens=* delims= " %%x in ('dir /o-d /on /b "*.dat"') do (
if defined _file_new_flag (
move /y "!_file_new_flag1!" "!_file_now!"
set _file_now=<nul
set "_file_now=%%~x"
) else (
set "_file_now=%%~x"
)
call :_file_compare_:
)
endlocal & goto :_end_of_file_:
:_file_compare_:
for /f "tokens=* delims= " %%X in ('type "!_file_now!"') do (
for /f "tokens=* delims= " %%i in ('echo/"%%~X"') do (
set "_to_compare=%%~i"
call set "_to_compare=!_to_compare: =!"
for /f "tokens=* delims=" %%I in ('echo/%_tab%') do call set "_to_compare=!_to_compare:%%I=!"
if ["!_to_compare!"] equ ["%'%"] (
echo/C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are same >>output.log
echo/%%~i>>!_file_new_flag1!
) else (
echo/C:\Users\f1ym41a\Documents\deep\MOVE.DAT and %%i are different >>output.log
echo/flag = 1>>!_file_new_flag1!
)
timeout /t 5
set _to_compare=<nul
)
)
exit /b
:_end_of_file_:
So sorry about my English.

Login script with output of systeminfo

I am trying to create a Windows batch login script that collects each user's system info and username/computername and outputs it to one log file (rather than a separate file created for each user). So I need something like echo %username%-%computername% >> file.txt and systeminfo|find /i "original" >> file.txt, which I managed to do with something like this:
systeminfo|find /i "original" >> \\share\sysinfo.log
echo %username%-%computername% >>\\share\user.log
type \\share\user.log > \\share\Results\systeminfo.log
type \\share\sysinfo.log >> \\share\Results\systeminfo.log
Every time someone logs on, it output to one file, but the username and systeminfo are separated. I need them to output into separate columns, for example:
Username-ComputerName Original Install Date
Jo-PC1 17/16/2016, 09:14:34
Dan-PC2 17/03/2015, 11:00:05
Please mind that Stack Overflow is not a write-code-for-me-services. Anyways, I shamefully stole the script(and edited) by MC ND in my question
#echo off
setlocal enableextensions disabledelayedexpansion
rem Prepare padding for two column
set "Width=30"
setlocal enabledelayedexpansion
set "padding= "
for /l %%a in (1 1 %Width%) do set "padding=!padding! "
endlocal & set "padding=%padding%"
rem return "Username-ComputerName Original Install Date"
echo Username-ComputerName Original Install Date>File.ext
rem Prepate two files to store username-computerName and install date lists
for %%d in ("%temp%\username-computerName.%random%%random%%random%.tmp") do (
for %%f in ("%temp%\installName.%random%%random%%random%.tmp") do (
rem Retrieve the list of username-computerName and install date into the temp files
type user.log > "%%~fd" 2>nul
type date.log > "%%~ff" 2>nul
rem Assign each temporary file to a separate stream
rem and call the code to process them
9<"%%~fd" 8<"%%~ff" call :dumpPairs
rem Clean up temporary files
) & del /q "%%~ff"
) & del /q "%%~fd"
rem All done, leave
cls
type File.ext
pause
goto :eof
rem Read stream 9 to retrieve username-computerName - Clean var on failure
rem Read stream 8 to retrieve install date - Clean var on failure
rem If both variables are uninitialized, there is nothing more to do
rem Concatenate both information and padding
rem Echo the padded results
rem Repeat the process
:dumpPairs
<&9 set /p "username-computerName=" || set "username-computerName="
<&8 set /p "installName=" || set "installName="
if not defined username-computerName if not defined installName goto :eof
set "line=%username-computerName%%padding%"
setlocal enabledelayedexpansion
echo(!line:~0,%Width%! !installName!>>File.ext
endlocal
goto :dumpPairs
The explanation is already is inside the script, so I won't explain much.
Simply get the result into 2 files
Echo them together
The output part is
rem All done, leave
cls
type File.ext
pause
goto :eof
so you may need some adjustments.

Modifying a batch file from another batch file

I am trying to create a batch file that updates another batch file. This is what I got.
Waiter.bat
#echo off
set /p Waiter="What would you like to eat? "
Call Menu.bat %Waiter%
Pause
Menu.bat
#echo off
if /i "%1=="Pizza echo "Cheesy goodness"
if not "%1=="Pizza "goto Add <----------------------------------
goto EOF |
|
:Add |
set /p Add="%1 is not in our menu. Would you like to add it? " |
if /i %Add%==yes goto next |
if /i %Add%==no goto EOF |
|
:next |
set /p Add1="What is %1? " |
echo >> "if /i "%1=%1" "echo %Add1" -----------------------------------------
pause
goto EOF
How do I make it add the new menu item under the
if /i "%1=="Pizza echo "Cheesy goodness"
Here's a version that migt work - it doesn't change the batch file...
menu.bat
#ECHO OFF
SETLOCAL
#echo off
set /p Waiter="What would you like to eat? "
Call q28612146_Menu.bat "%Waiter%"
Pause
GOTO :EOF
Note: The batchfile called is simply q28612146_Menu.bat for my convenience. You call it what you like - Ikeep all data relating to SO question 28612146 together on my machine.
Note that I've enclosed the parameter supplied to the menu batch in quotes, which will allow you to use spaces if you like (like "Filet mignon")
q28612146_Menu.bat
#ECHO OFF
SETLOCAL
:begin
FOR /f "tokens=1*delims=|" %%a IN (q28612146.txt) DO IF /i "%%a"=="%~1" ECHO %%b&GOTO :EOF
:again
set /p Add="%~1 is not in our menu. Would you like to add it? "
if /i "%Add%"=="yes" goto next
if /i "%Add%"=="no" goto :EOF
GOTO again
:next
set /p Add1="What is %1? "
>>q28612146.txt echo %~1^|%Add1%
pause
GOTO begin
I used a file named q28612146.txt containing this data for my testing.
Pizza|Cheesy goodness
The batch reads the file, putting the first "token" (before the delimiter "|") into %%a and the description into %%b. If there's a match against the supplied parameter (case-insensitive) then the description part in %%b is echoed and we exit (note the colon - :eof means 'end of this batch file')
Then you ask the question, then if you want to add, ask for the description. I've also added a loop back to again for the case that the response is neither yes nor no.
Note the use of quotes in the if statements - we have no control over what is typed, so quoting the response affords some protection in case the user responds with something including a space (the protection is incomplete). The other side must also be quoted because the two strings must exactly match.
Then echo the new item and description to the data file - the caret (^) tells batch that the pipe is part of the data, not the instruction echo - and pauses. I chose to return to the label begin to read and the response from the file.

Resources