EDIT: I have updated this post to include the entire script.
EDIT: While not ideal, this is meant to be an automation of a fix provided by the company that makes the software.
I have a batch file that I am running as Administrator.
I am running a batch file based on the file system input by the user.
One of the first commands renames a file.
If I execute this command on its own, from an elevated command prompt, it renames the file.
When I nest the command inside the IF statement, it doesn't rename the file.
I have commented out all of the other lines to simply rename the file if the user enters "1".
I have tried encapsulating the file path and file each individually within quotes, which I shouldn't need, and still do not get it to rename the file.
I am running the batch script as Admin.
#echo off
setlocal EnableDelayedExpansion
if "%$ecbId%" == "" (
echo Welcome to the ADaPT
echo Choose '1' for 32 bit
echo Choose '2' for 64 bit
echo Type anything else to abort.
echo.
set "UserChoice=abort"
set /P "UserChoice=Type your choice: "
if "!UserChoice!"=="1" (
echo Executing 32 bit sequence...
echo Regsvr32.exe /u C:\Windows\System32\MSCOMCTL.OCX
echo REN C:\Windows\System32\MSCOMCTL.OCX MSCOMCTL.bak
xcopy C:\install\MSCOMCTL.OCX C:\Windows\System32 folder
Regsvr32.exe C:\Windows\System32\MSCOMCTL.OCX
Regsvr32.exe /u C:\Windows\System32\MSCOMCTL.OCX
del "C:\Windows\System32\ MSCOMCTL.OCX"
echo REN "C:\Windows\System32\MSCOMCTL.bak" "MSCOMCTL.OCX"
Recho Regsvr32.exe C:\Windows\System32\MSCOMCTL.OCX
shutdown.exe /r /t 00
)
if "!UserChoice!"=="2" (
echo Regsvr32.exe /u C:\Windows\SYSWOW64\MSCOMCTL.OCX
echo REN "C:\Windows\SYSWOW64\MSCOMCTL.OCX" "MSCOMCTL.bak"
xcopy C:\install\MSCOMCTL.OCX C:\Windows\SYSWOW64 folder
Regsvr32.exe C:\Windows\SYSWOW64\MSCOMCTL.OCX
Regsvr32.exe /u C:\Windows\SYSWOW64\MSCOMCTL.OCX
del "C:\Windows\SYSWOW64\ MSCOMCTL.OCX"
echo REN "C:\Windows\SYSWOW64\MSCOMCTL.bak" "MSCOMCTL.OCX"
echo Regsvr32.exe C:\Windows\SYSWOW64\MSCOMCTL.OCX
REM... shutdown.exe /r /t 00
)
if not "!UserChoice!"=="1" (
echo toto3
if not "!UserChoice!"=="2" (
echo toto4
echo Unknown input ... Aborting script
endlocal
exit /B 400
)
)
)
endlocal
I have simplified your entire script structure so as not to require parenthesised blocks, or the need to delay expansion:
#Echo Off
If Defined $ecbId GoTo :EOF
Echo Welcome to the ADaPT
Choice /C CQ /M "Continue or Quit"
If ErrorLevel 2 GoTo :EOF
Set "Dest=TEM32"
Set PROCESSOR_ARCHITE|Find "64">Nul&&(Set Dest=WOW64)
Set "Dest=%SYSTEMROOT%\SYS%Dest%"
Echo Executing sequence . . .
RegSvr32 /U "%Dest%\MSCOMCTL.OCX"
Rem To backup and replace MSCOMCTL.OCX:
Rem Uncomment the next three unRemarked lines
Rem and comment the next three unRemarked lines below them.
::Del /A /F "MSCOMCTL.bak" 2>Nul
::Ren "%Dest%\MSCOMCTL.OCX" "MSCOMCTL.bak"
::XCopy "C:\install\MSCOMCTL.OCX" "%Dest%"
Rem To recover MSCOMCTL.OCX from the backup:
Rem Comment the next three unRemarked lines
Rem and uncomment the previous three unRemarked lines above them.
If Not Exist "MSCOMCTL.bak" RegSvr32 "%Dest%\MSCOMCTL.OCX" & GoTo :EOF
Del /A /F "%Dest%\MSCOMCTL.OCX"
Ren "%Dest%\MSCOMCTL.bak" "MSCOMCTL.OCX"
RegSvr32 "%Dest%\MSCOMCTL.OCX"
ShutDown /R /T 0 /D P:2:4
Notes:It is probably safe to delete lines 3 and empty line 4, I left them in only because no explanation was provided as to the purpose of the %$ecbId% variable value comparison.I have added Remarks for toggling the script for the backup or recovery methods, but not knowingly altered any of your command sequence, (I have however added the /A and /F options with Del, just in case, and included the /D option with ShutDown to ensure that the logs show it as a planned shutdown event).
Related
Hello and firstly I would like to apologize for this post if it was already answered before. I spent the last 4 hours searching Stackoverflow and Google.
I have a gamesettings.ini file I would like to edit via batch file. I need to perform this over many PCs, so I would like to keep the other settings besides 2 lines in the file.
The two lines im trying to change are:
CustomVoiceChatInputDevice=Default Input
CustomVoiceChatOutputDevice=Default Output
I tried a few batch scripts I found on Stackoverflow, but they only work if I define the full line. Since every user has different options set, i need the script to just take the start of the line. Just "CustomVoiceChatInputDevice" for example.
Here's an example code I used, thanks to #jsanchez. This script doesn't work unless I type out the whole line:
Thank you for your time!!
#echo off
::Use the path from whence the script was executed as
::the Current Working Directory
set CWD=C:\
::***BEGIN MODIFY BLOCK***
::The variables below should be modified to the
::files to be changed and the strings to find/replace
::Include trailing backslash in _FilePath
set _FilePath=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient\
set _FileName=GameUserSettings.ini
::_WrkFile is the file on which the script will make
::modifications.
set _WrkFile=GameUserSettings.bak
set OldStr="CustomVoiceChatInputDevice"
set NewStr="CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"
::***END MODIFY BLOCK***
::Set a variable which is used by the
::search and replace section to let us
::know if the string to be modified was
::found or not.
set _Found=Not found
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
if not exist "%_FilePath%%_FileName%" goto :NotFound
::If a backup file exists, delete it
if exist "%_FilePath%%_WrkFile%" (
echo Deleting "%_FilePath%%_WrkFile%"
del "%_FilePath%%_WrkFile%" >nul 2>&1
)
echo.
echo Backing up "%_FilePath%%_FileName%"...
copy "%_FilePath%%_FileName%" "%_FilePath%%_WrkFile%" /v
::Delete the original file. No worries, we got a backup.
if exist "%_FilePath%%_FileName%" del "%_FilePath%%_FileName%"
echo.
echo Searching for %OldStr% string...
echo.
for /f "usebackq tokens=*" %%a in ("%_FilePath%%_WrkFile%") do (
set _LineChk=%%a
if "!_LineChk!"==%OldStr% (
SET _Found=Found
SET NewStr=!NewStr:^"=!
echo !NewStr!
) else (echo %%a)
)>>"%_FilePath%%_FileName%" 2>&1
::If we didn't find the string, rename the backup file to the original file name
::Otherwise, delete the _WorkFile as we re-created the original file when the
::string was found and replaced.
if /i "!_Found!"=="Not found" (echo !_Found! && del "%_FilePath%%_FileName%" && ren "%_FilePath%%_WrkFile%" %_FileName%) else (echo !_Found! && del "%_FilePath%%_WrkFile%")
goto :exit
:NotFound
echo.
echo File "%_FilePath%%_FileName%" missing.
echo Cannot continue...
echo.
:: Pause script for approx. 10 seconds...
PING 127.0.0.1 -n 11 > NUL 2>&1
goto :Exit
:Exit
exit /b
Each setting within your .ini file identifies the name of the setting. So the order of the lines should not may not matter.
If the line order is meaningless, then all you need do is use FINDSTR /V to remove the old values, and then simply append the new values. In the script below I modify both values at the same time.
#echo off
setlocal enableDelayedExpansion
set "iniLoc=C:\Users\NEOSTORM\AppData\Local\RedDeadGame\Saved\Config\WindowsClient"
set "iniFile=%iniLoc%\GameUserSettings.ini"
set "iniBackup=%iniLoc%\GameUserSettings.bak"
set "CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game)"
set "CustomVoiceChatOutputDevice=Some new value"
>"%iniFile%.new" (
findstr /vb "CustomVoiceChatInputDevice= CustomVoiceChatOutputDevice=" "%iniFile%"
echo CustomVoiceChatInputDevice=!CustomVoiceChatInputDevice!
echo CustomVoiceChatOutputDevice=!CustomVoiceChatOutputDevice!
)
copy "%iniFile%" "%iniBackup%"
ren "%iniFile%.new" *.
It would be slightly faster to create the backup file via rename instead of copy, but then there would be a brief moment where the ini file does not exist.
Windows command processor is not designed for editing text files, it is designed for running commands and applications.
But this text file editing/replacing task can be nevertheless done with cmd.exe (very slow):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FileName=%LOCALAPPDATA%\RedDeadGame\Saved\Config\WindowsClient\GameUserSettings.ini"
set "TempFile=%TEMP%\%~n0.tmp"
if not exist "%FileName%" goto EndBatch
del "%TempFile%" 2>nul
for /F delims^=^ eol^= %%A in ('%SystemRoot%\System32\findstr.exe /N "^" "%FileName%"') do (
set "Line=%%A"
setlocal EnableDelayedExpansion
if not "!Line:CustomVoiceChatInputDevice=!" == "!Line!" (
echo CustomVoiceChatInputDevice=Line (Astro MixAmp Pro Game^)
) else if not "!Line:CustomVoiceChatOutputDevice=!" == "!Line!" (
echo CustomVoiceChatOutputDevice=Line (Astro MixAmp Pro Game^)
) else echo(!Line:*:=!
endlocal
) >>"%TempFile%"
rem Is the temporary file not binary equal the existing INI file, then move
rem the temporary file over existing INI file and delete the temporary file
rem if that fails like on INI file currently opened by an application with
rem no shared write access. Delete the temporary file if it is binary equal
rem the existing INI file because of nothing really changed.
%SystemRoot%\System32\fc.exe /B "%TempFile%" "%FileName%" >nul
if errorlevel 1 (
move /Y "%TempFile%" "%FileName%"
if errorlevel 1 del "%TempFile%"
) else del "%TempFile%"
:EndBatch
endlocal
See the answer on How to read and print contents of text file line by line? for an explanation of the FOR loop.
Please note the caret character ^ left to ) in the two lines to output. A closing parenthesis outside a double quoted argument string must be escaped here with ^ as otherwise ) would be interpreted by Windows command processor as end of command block and not as literal character to output by command ECHO. Other characters with special meaning for cmd.exe on parsing a command line or an entire command block like &|<> must be also escaped with ^ on ECHO command lines.
Please take also a look on Wikipedia article about Windows Environment Variables. It is highly recommended to use the right predefined environment variables for folder paths like local application data folder.
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 %~n0 ... batch file name without path and file extension.
del /?
echo /?
endlocal /?
fc /?
findstr /?
for /?
if /?
move /?
rem /?
set /?
setlocal /?
I'm trying to make a batch script that can take any of the following three inputs:
-drag and drop a folder
-drag and drop a single file
-drag and drop a selection of multiple files
and perform a cmd command (transcoding some video with VLC) on all the files so presented that match a list of file types. I've tried doing this a number of different ways, but each way seems to have a showstopping shortcoming of one kind or another.
I can get the script to check for VLC being installed, determine whether it's been given a file, files, or folder, and process an individual file just fine without filtering extensions; it's processing multiple files, processing a folder, and filtering by extension that are tripping me up:
#echo off
Title PPT Transcoder
Mode con cols=120 lines=16
IF [%~1] == "" GoTo :Error_ranDirectly
IF exist "C:\Program Files\VideoLAN\VLC\vlc.exe" (
CD /D "%~1">nul 2>&1 && Goto :Explorer_Folder || Goto :Files
) else (
Goto :Error_VLCNotInstalled
)
Exit /b
::**********************************************************
:Files <File>
Color 0E
ECHO Transcoding %1 to %1_PPT.mp4...
REM I really want to filter for six filetypes here (.mp4, .avi, .mov., .wmv,
REM .flv, .gif) and not affect any others. Forfiles looks like it could
REM work, but I can't figure out how to get it to work on my arguments
REM rather than the entire folder of files that match the filter.
"C:\Program Files\VideoLAN\VLC\vlc.exe" [a bunch of flags] %1 [a bunch more flags]:file{dst=%1_PPT.mp4,no-overwrite} [even more flags] vlc://quit
IF [%~2] == "" Goto :FilesFinished
shift
GoTo :Files
:FilesFinished
Color 0A
Echo Finished processing.
Timeout /T 10 /NoBreak >nul
Exit /b
::**********************************************************
:Explorer_Folder <Folder>
REM This block of code almost works, but i think it malforms the file names
REM fed to vlc. It runs and thinks it's working, but fails to actually
REM accomplish anything.
setlocal
Color 0C
SET /P AREYOUSURE=Transcode all files in folder %1 (Y/[N])?
IF /I "%AREYOUSURE%" NEQ "Y" GOTO :Abort
Color 0F
for %%x in (%1\*.mp4 %1\*.mov %1\*.avi %1\*.wmv %1\*.flv) do (
echo Transcoding %%x to %%x_PPT.mp4...
""C:\Program Files\VideoLAN\VLC\vlc.exe" [a bunch of flags] %%x [a bunch more flags]:file{dst=%%x_PPT.mp4,no-overwrite} [even more flags] vlc://quit
echo Done.)
Timeout /T 10 /NoBreak >nul
endlocal
Exit /b
::**********************************************************
:Error_RanDirectly
Color 0C & echo(
ECHO Drag and drop video files on the icon to transcode them.
Timeout /T 5 /NoBreak >nul
Exit /b
::**********************************************************
:Error_VLCNotInstalled
Color 0C & echo(
ECHO VLC 64-bit (free download from videolan.org) must be installed.
Timeout /T 10 /NoBreak >nul
Exit /b
::**********************************************************
:Abort
Exit /b
I guess to make this a general question: Is there a generally accepted framework for making a batch script handle drag and drop execution intelligently?
Save this as a cmd file and drop directories and files on it. See how it works.
#setlocal ENABLEEXTENSIONS
#rem #set prompt=$G
#call :ShowTypes %*
#pause
#exit /b
:ShowTypes
#echo Processing:
:_showTypes
#rem If it exists with a slash appended to the end,
#rem it's directory, otherwise a file type.
#if exist "%1\\" (#set _type=directory) else (#call :SetFileType "%1")
#if "%1" neq "" (echo %1 as %_type%) else (exit /b 0)
#shift
#goto :_showTypes
:SetFileType
#rem %~x1 is the extension of the first parameter passed by caller.
#set _type=%~x1
#rem Remove the dot from the extension string.
#set _type=%_type:.=%
#rem Now _type is whatever the extension was.
#exit /b 0
Remove the leading # symbol to see that line in action.
I am creating a batch for creation of zip files from folders, I want to check if the zip file has been created succesfully. It does the logging of which zip file has been created but when it goes wrong it should goto a label and stop the operation. This does not work, the ELSE command is echoed and not executed.
SETLOCAL EnableExtensions EnableDelayedExpansion
for /d %%d in (*) do (
"7z.exe" a -r -tzip "%%d.zip" ".\%%d\" & IF %ERRORLEVEL% EQU 0 (echo Archive "%%d.zip" created succesfully >> "Archive-log %date%.txt") ELSE (set fault="%%d.zip" goto createzip))
exit /b
:createzip
echo Failed creating archive %fault% >> "Error-log %date%.txt"
exit /b
Here is the batch code rewritten and extended. The batch file does not immediately stop on failing to compress a subfolder to a ZIP archive.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Get current date in region dependent format with . as delimiter.
set "FileDate=%DATE:/=.%"
set "ErrorCount=0"
set "FolderCount=0"
rem Compress each non hidden subfolder in current folder into a ZIP file.
for /D %%I in (*) do (
set /A FolderCount+=1
"7z.exe" a -r -tzip "%%I.zip" ".\%%I\"
if errorlevel 1 (
echo Failed creating archive: "%%I.zip">>"Error-log %FileDate%.txt"
set /A ErrorCount+=1
) else (
echo Archive "%%I.zip" created succesfully.>>"Archive-log %FileDate%.txt"
)
)
rem Exit batch processing if no subfolder was found in current folder?
if %FolderCount% == 0 endlocal & exit /B
set "ErrorPluralS=s"
if %ErrorCount% == 1 set "ErrorPluralS="
set "FolderPluralS=s"
if %FolderCount% == 1 set "FolderPluralS="
echo Processed %FolderCount% folder%FolderPluralS% with %ErrorCount% error%ErrorPluralS%.>>"Archive-log %FileDate%.txt"
endlocal
if errorlevel 1 working also without usage of delayed expansion means:
IF the exit code of the previous command or executable is greater or equal 1 THEN ...
This is explained in the Microsoft support article Testing for a Specific Error Level in Batch Files and working from MS-DOS to Windows 10 in batch files and on command line.
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.
echo /?
endlocal /?
for /?
if /?
rem /?
set /?
setlocal /?
Read also the answers on:
Single line with multiple commands using Windows batch file
How to get information about current path %CD% in batch in a FOR loop?
I think it's because your ELSE contains 2 statements which aren't separated so the goto ends up being part of the set command. To fix that and for readability, I think you should reformat a bit:
for /d %%d in (*) do (
"7z.exe" a -r -tzip "%%d.zip" ".\%%d\"
IF %ERRORLEVEL% EQU 0 (
echo Archive "%%d.zip" created succesfully >> "Archive-log %date%.txt"
) ELSE (
set fault="%%d.zip"
goto createzip
)
)
Recently I got a script to query the reg set a value and then delete folders under the folder I puled from the query. Looks like this:
pause
FOR /F "TOKENS=2*" %%I IN ('REG QUERY "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\14.0\Outlook\Security" /V OutlookSecureTempFolder') Do SET "ValueData=%%J"
pause
echo Delete Outlook Temp. Files???
echo Enter to continue or Ctrl+C to cancel.
pause
del /q /f /s "%valuedata%\*.*"
del /q /f /s "%systemdrive%\Jacob'sTemp"
pause
echo --------------------------------------------------------------------------------
echo Complete! Goodbye!
echo --------------------------------------------------------------------------------
timeout /t 3
Works great when used locally. So I set up a robo copy to copy a folder with this script in it then use psexec to execute it remotely and it looks like this:
set /p cpu=
robocopy "\\nmcfs01\software\scripts\Jacob's Awesome Outlook Scripts" \\%cpu%\c$\Jacob'sTemp
pause
psexec \\%cpu% -u administrator "%systemdrive%\Jacob'sTemp\outlooktempdelete.bat"
pause
Now it works and it will run but here is the kicker when it goes back to the reg query batch to do the reg query it will run but it skips the 1st pause following the query and it always says it can not find the registry key but I can follow the path and it is there. The worst part is once I end the script there it wipes the computer of everything the user has access to. Not folders but all files/subfiles everywhere. Any insight is greatly appricated!
Here's a quick tidy up of your script:
#Echo Off
SetLocal EnableExtensions
(Set OV=14.0)
Choice /C YN /M "Delete Outlook Temp Files?"
If ErrorLevel 2 Exit/B
Set "BK=HKCU\SOFTWARE\Microsoft\Office\"
Set "EK=\Outlook\Security"
Set "VN=OutlookSecureTempFolder"
For /F "Tokens=2*" %%I In ('Reg Query "%BK%%OV%%EK%" /V %VN%') Do Set "VD=%%J"
PushD "%VD%" && (RD/S/Q "%VD%" 2>Nul) && PopD
REM The below commands will empty Jacob'sTemp:
If Exist "%SystemDrive%\Jacob'sTemp" (PushD "%SystemDrive%\Jacob'sTemp" && (
(RD/S/Q "%SystemDrive%\Jacob'sTemp" 2>Nul) && PopD
REM The below commands without the first two characters will remove Jacob'sTemp
::If Exist "%SystemDrive%\Jacob'sTemp" (RD/S/Q "%SystemDrive%\Jacob'sTemp"
Pause
Echo(------------------------------------------------------------------------------
Echo( Complete! Goodbye!
Echo(------------------------------------------------------------------------------
Timeout 5 >Nul
Give that a try exactly as it is just to see if it makes any difference.
I left the lonely but editable 'set' at the top because this is the only bit that need's changing to cater for earlier or later editions of outlook.
I have a batch script which accepts >=1 files via drag & drop. The full paths are kept in an array and later fed to another program as input. The file name+extension is kept in another array which is then shown to the user.
I am trying to check the file extension and if it is not .bin, automatically rename the file I dragged & dropped to .bin and reload it to be added to the two arrays. How can I do that? I have tried some if commands or %%~xi but usually it doesn't properly detect if it's .bin or not and of course the path is not updated at the array.
#echo off
pushd %~dp0
setlocal enabledelayedexpansion
set /a Count = 0
:START
set file="%~1"
if %file%=="" goto RUN
for %%i in (%file%) do set name=%%~nxi
set /a Count += 1
set [FilePath.!Count!]=%file%
set [FileName.!Count!]=%name%
shift
goto START
:RUN
for /l %%i in (1, 1, %Count%) do (
program.exe -command "![FilePath.%%i]!"
echo.
echo File Name: ![FileName.%%i]!
echo.
pause
cls
if exist file.log del file.log
)
You could just rename it during your array population. There are a few other potential problems with your script (such as pushd to an unquoted directory, delayedexpansion where you don't need it where it will potentially clobber filenames containing exclamation marks, and if %file%=="" should have "%file%" quoted). And there's really no reason to maintain an array of filenames or loop twice. Your script is much more complicated than it needs to be.
#echo off
setlocal
pushd "%~dp0"
for %%I in (%*) do (
if /I not "%%~xI"==".bin" move "%%~fI" "%%~dpnI.bin" >NUL
program.exe -command "%%~dpnI.bin"
echo;
echo File Name: "%%~nxI"
echo;
rem If you want to rename the file back the way it was after running
rem program.exe on it, uncomment the following line:
rem if /I not "%%~xI"==".bin" move "%%~dpnI.bin" "%%~fI" >NUL
pause
cls
if exist file.log del file.log
)