Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I Have batch code listed in a password protected word file (so no one can edit my code) and i need a .bat file that can convert the code i have listed in there, to a .txt file that i can have it read. If you know a way to make a .bat file that can read a word doc, that would also be appreciated.
Using a (tested) hybrid batchscript (that encapsulates JScript):
#if (0)==(1) REM BatchScript:
:INIT
#ECHO OFF & CLS
SET DOC=C:\Some folder\tst.doc
SET TXT=C:\Some other folder\res.txt
SET PWD=MySecretPass
:MAIN
cscript //NoLogo //E:JScript "%~f0" /inp:"%DOC%" /outp:"%TXT%" /pass:"%PWD%"
notepad "%TXT%"
GOTO ENDBAT
:ENDBAT
ECHO Press any key to exit...&PAUSE>NUL
GOTO :EOF
#end // JScript:
var FSO = WScript.CreateObject("Scripting.FileSystemObject")
, HND = FSO.CreateTextFile(WScript.Arguments.Named('outp'))
, APP = WScript.CreateObject('Word.Application')
, DOC, str
;
APP.Visible=false; //hide word
DOC = APP.Documents // access interface
.Open( WScript.Arguments.Named('inp') //file location
, false //ConfirmConversions
, true //ReadOnly
, false //AddToRecentFiles
, WScript.Arguments.Named('pass') || '' //PasswordDocument
//, //PasswordTemplate
//, //Revert
//, //WritePasswordDocument
//, //WritePasswordTemplate
//, //Format
//, //Encoding
//, //Visible
//, //OpenConflictDocument
//, //OpenAndRepair
//, //DocumentDirection
//, //NoEncodingDialog
);
str=new String(DOC.Content); //grab content
str=str.replace(/\r\n|\r/g,'\r\n')+'\r\n'; //cleanup line-endings
HND.Write( str ); //write the file
HND.Close(); //close file handle
DOC.Close(); //close word doc
APP.quit(0); //don't forget to close word
Save this as a batchscript, replacing the hardcoded inputfile DOC, outputfile TXT and password PWD. See npocmaka's answer to alter this to accepting arguments on the batchscript call.
Instead of running the resulting txt-file through notepad you might want to call the batchscript directly.
Also you might want to delete the extracted batchfile under the :ENDBAT label.
Also, (to keep it simple and to the core) there is no error-checking provided.
Lastly, it requires MS Word (starting at Office 2000) to be installed.
Usage: simply run it however you please.
UPDATE:
After comparing notes and doing tests in the chat, npocmaka and I concluded that if one uses word's SaveAs, the safest bet is using type 2: wdFormatText. More about that in npocmaka's updated answer.
My example (writing a new file using the FileSystemObject) shows a simpler way of post-processing the fetched text and doesn't update word's internal recent file-list (MRU) that otherwise would be updated when word converts saves the file.
Between the both of our answers there is plenty to choose from, so happy mixing!
See this page:
http://www.abisource.com/wiki/AbiCommand
which describes using the command line options available for AbiWord, including
converttotext "file\path\file.doc" "destingation\file.txt"
(http://www.abisource.com/download/index.phtml)
A smaller install would probably be http://wvware.sourceforge.net/#wv, but apparently the developer considers those utilities to be "deprecated" and probably not as reliable as using AbiWord.
This just in: see http://github.com/tobya/DocTo
Here's a script that I've wrote long ago to save doc(x) to txt. And this is a reworked version that accepts a password:
'>nul 2>&1|| #copy /Y %windir%\System32\doskey.exe '.exe >nul
'&&#echo off && cls &&goto :end_vbs
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = FALSE
'Open doc for reading
Set WordDoc = WordApp.Documents.Open(WScript.Arguments.Item(0),true,true,false,WScript.Arguments.Item(2))
'wdFormatText 2
'wdFormatUnicodeText 7
format = CInt(WScript.Arguments.Item(3) )
WordDoc.SaveAs WScript.Arguments.Item(1) ,format
WordDoc.Close()
WScript.Quit
:end_vbs
'& if "%~1" equ "-help" echo %~n0 word_document destination password [-unuicode]
'& if "%~1" equ "" echo word document not given & exit /b 1
'& if not exist "%~f1" echo word document does not exist & exit /b 2
'& if "%~2" equ "" echo destination not given & exit /b 1
'& set "save_as=%~2"
'& if exist "%~f2" del /s /q "%~f2"
'& if "%~4" equ "-unuicode" ( set "format=7") else ( set "format=2")
'& taskkill /im winword* /f >nul 2>&1
'& cscript /nologo /E:vbscript %~f0 "%~f1" "%save_as%" "%~3" %format%
'& pause
'& del /q /f '.exe
This is a batch/vbscript hybrid and you need to save it as a .bat
Note - will need admin permissions to start "invisible" word application.
An example (if file is saved as doc2txt.bat) (it's better to use full paths):
doc2txt.bat c:\tstpass.docx c:\result\tstpass.txt super_secret_password
doc2txt.bat c:\tstpass.docx c:\result\tstpass.txt super_secret_password -unicode
EDIT jscript/bat hybrid
#if (#x)==(#y) #end /***** jscript comment ******
#echo off
if "%~1" equ "-help" echo %~n0 word_document destination password [-unuicode|-breaks]
if "%~1" equ "" echo %~n0 word_document destination password [-unuicode]
if "%~2" equ "" echo destination not given & exit /b 1
if "%~3" equ "" echo password not given & exit /b 3
if exist "%~f2" del /s /q "%~f2"
if "%~4" equ "-unicode" (
set "format=7"
) else (
if "%~4" equ "-breaks" (
set "format=3"
) else (
set "format=2"
)
)
:: kill winword application to avoid collisions
taskkill /im winword* /f >nul 2>&1
if not exist "%~f1" echo word document does not exist & exit /b 2
cscript //E:JScript //nologo "%~f0" "%~f1" "%~2" %~3 %format%
exit /b 0
***** end comment *********/
var source_file=WScript.Arguments.Item(0);
var destination_file=WScript.Arguments.Item(1);
var confirmConv=false;
var readOnly=true;
var addToRecentFiles=false;
var password=WScript.Arguments.Item(2);
//save format enumaration - http://msdn.microsoft.com/en-us/library/office/ff839952.aspx
// text formats
//wdFormatText 2
//wdFormatUnicodeText 7
//wdFormatTextLineBreaks 3
var encoding=parseInt(WScript.Arguments.Item(3));
var WordApp=new ActiveXObject("Word.Application");
WordApp.Visible = false;
var WordDoc=WordApp.Documents.Open(source_file,confirmConv,readOnly,addToRecentFiles,password);
WordDoc.SaveAs(destination_file,encoding);
WordDoc.Close();
WScript.Quit();
examples:
doc2txtjs.bat "c:\tstpass.docx" "c:\result\tstpass.txt" unhackable_password -breaks
doc2txtjs.bat "c:\tstpass2.docx" "c:\result\tstpass2.txt" unhackable_password -unicode
doc2txtjs.bat "c:\tstpass3.docx" "c:\result\tstpass3.txt" unhackable_password
-breaks/-unicode will save the file respectively with preserved line breaks or in unicode format.You'll need admin permissions again.But as you want to create a bat from doc you dont need to use these additional options.
I figured it out. I made a batch program that creates a temporary VBS file that converts it to a BAT file instead of a TXT. Then I executed the Batch file from the converter. Thanks for all your answers though and I saw some useful ideas. :)
Related
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
I am trying to use the tee code written for a bat file but am having trouble implementing it in my code. I don't want to use any third party installs to solve the tee problem as I want the code to work if I format my computer in a year and want to run the program again.
I have it setup in this fashion:
mycommand.exe | tee.bat -a output.txt
I've tried with a seperate .bat file and tried including as a function (preffered) in the original .bat to no avail with:
myprogram.exe | call tee -a output.txt
echo.
echo.
echo.
SET /P restart="Do you want to run again? (1=yes, 2=no): "
if "%restart%"=="1" GOTO LoopStart
::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------
:tee
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
|
:: Keep variables local
SETLOCAL
:: Check command line arguments
SET Append=0
IF /I [%1]==[-a] (
SET Append=1
SHIFT
)
IF [%1]==[] GOTO Syntax
IF NOT [%2]==[] GOTO Syntax
:: Test for invalid wildcards
SET Counter=0
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"
IF %Counter% GTR 1 (
SET Counter=
GOTO Syntax
)
:: A valid filename seems to have been specified
SET File=%1
:: Check if a directory with the specified name exists
DIR /AD %File% >NUL 2>NUL
IF NOT ERRORLEVEL 1 (
SET File=
GOTO Syntax
)
:: Specify /Y switch for Windows 2000 / XP COPY command
SET Y=
VER | FIND "Windows NT" > NUL
IF ERRORLEVEL 1 SET Y=/Y
:: Flush existing file or create new one if -a wasn't specified
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)
:: Actual TEE
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
> CON ECHO.%%B
>> %File% ECHO.%%B
)
:: Done
ENDLOCAL
GOTO:EOF
:Count
SET /A Counter += 1
SET File=%1
GOTO:EOF
:Syntax
ECHO.
ECHO Tee.bat, Version 2.11a for Windows NT 4 / 2000 / XP
ECHO Display text on screen and redirect it to a file simultaneously
ECHO.
IF NOT "%OS%"=="Windows_NT" ECHO Usage: some_command ¦ TEE.BAT [ -a ] filename
IF NOT "%OS%"=="Windows_NT" GOTO Skip
ECHO Usage: some_command ^| TEE.BAT [ -a ] filename
:Skip
ECHO.
ECHO Where: "some_command" is the command whose output should be redirected
ECHO "filename" is the file the output should be redirected to
ECHO -a appends the output of the command to the file,
ECHO rather than overwriting the file
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO Modified by Kees Couprie
ECHO http://kees.couprie.org
ECHO and Andrew Cameron
I am trying to split the output so I can save the console output to a file while still being able to interact with the program that is running.
How can I get the Tee command to work properly with my .bat so I can split the output to both a file and the console.
Your attempt to call a batch function within a pipe will always fail because of how Windows pipes work - Windows instantiates both sides of the pipe via new CMD shells. See https://stackoverflow.com/a/8194279/1012053 for more info.
That Rob van der Woude version of a batch tee cannot possibly work for you because it uses a FOR /F to read the results of a command - the command must execute to completion before any lines are read. That won't work if you need user interaction during the execution of the command. With that version of tee you might as well simply redirect output to a file and then TYPE the file when finished. Obviously not what you want.
There are pure batch tricks that can get you closer, but I think there is still one problem that can't be solved with pure batch. Your executable may put a prompt on a line without issuing a new line. I believe pure native batch always reads entire lines (except when at end of stream). I'm not aware of a batch method to read character by character.
Slight correction - SET /P can read partial lines of piped input, but it has limitations that prevent it from being used for a robust batch tee solution: There is no way to know for sure when each line ends. It is limited to 1021 characters per "line". It strips control characters from the end of each "line". There is no way to tell when it has reached the end of the input stream.
But there is a simple solution - JScript or VBScript works like a champ, and doesn't require any special installs. Here is a hybrid JScript/batch script that should work for you. The JScript is poorly written with lots of room for improvement. For example, there is no error checking.
I save the script as tee.bat. The first required argument specifies the name of the file to write to. By default, the file is over-written if it already exists. If a second argument is provided (value doesn't matter), then the output is appended to the file instead.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::--- Batch section within JScript comment that calls the internal JScript ----
#echo off
cscript //E:JScript //nologo "%~f0" %*
exit /b
----- End of JScript comment, beginning of normal JScript ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
chr=WScript.StdIn.Read(1);
WScript.StdOut.Write(chr);
out.Write(chr);
}
Usage is pretty much like you would expect.
command.exe | tee.bat output.txt 1
The last 1 argument forces append mode. It could be any value besides 1
It is possible to put everything in one batch script as you seem to prefer.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::--- Batch section within JScript comment ----------------------------
#echo off
::This block of code handles the TEE by calling the internal JScript code
if "%~1"=="_TEE_" (
cscript //E:JScript //nologo "%~f0" %2 %3
exit /b
)
::The rest of your batch script goes here
::This pipes to TEE in append mode
mycommand.exe | "%~f0" _TEE_ output.txt 1
exit /b
----- End of JScript comment, beginning of normal JScript ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
chr=WScript.StdIn.Read(1);
WScript.StdOut.Write(chr);
out.Write(chr);
}
Update
For anyone with an academic interest in batch scripting, I've posted a pure native batch version of tee at Asynchronous native batch tee script over at DosTips. But this hybrid approach is my preferred scripting solution.
So, I've been working on a batch script that essentially helps you with youtube-dl, essentially filing out all the data it needs to download into a directory. I want to be able to make a special shortcut that launches it, and instead of doing what it normally does, I want it to go through a text file (for example, let's call it update list.txt) and update playlists when that shortcut is run. I don't want to make another batch file that does this (for simplicity for user).
Here's what I have so far:
#echo off
:loop
title Welcome to CCF_100's youtube-dl helper!
set /A loop=loop+1
echo.Times Looped: %loop%
cd %~dp0
set /p input=Enter YouTube ID, URL, or Playlist ID:
set /p Output_Dir=Enter Directory you want to save in (Directory will be
created if it does not exist):
set /p flags=Enter flags (Optional):
if exist %Output_Dir%\ (goto Do_the_thing) else (goto make_directory)
:make_directory
mkdir "%Output_Dir%"
if /I %loop% LEQ 2 goto Do_the_thing
explorer "%Output_Dir%"
:Do_the_thing
title CCF_100's ytdl helper: currently downloading: %input% to %Output_Dir%
youtube-dl.exe -i -U %flags% -o "%Output_Dir%\%%(title)s - %%(id)s.%%(ext)s"
%input%
set /p loop=Successfully downloaded file(s). Download more?
if /i %loop%==y goto loop
if /i %loop%==Y goto loop
if /i %loop%==n goto end
if /i %loop%==N goto end
:end
exit
And yes I know the last two if statements are unnecessary.
You can get the arguments of a batchfile by reading the value of %n with n being a number between 0 and 9 or an asterisk. 0 is the batch-file itself (in the sense of the path to it) and the asterisk means any additional argument (excluding the batch-file-path).
So with that you can check for the contents of %1 and see if it is the flag you thought of or existent at all:
REM Demo only!
#echo off
if "%1"=="" (
echo no flags set
) ELSE (
echo flag set: %1
)
or change the if in a similar fashion to react to your flag only.
I need to create a batch script that continually monitors a specific file for changes, in this case, LogTest.txt.
When the file is updated it will trigger a VBScript message box, which displays the last line from within LogTest.txt. The idea is that this will continue monitoring after the message box is cleared.
I have tried using the forfiles option, but this really only lets me deal with the date and not the time. I know that PowerShell and other options are available, but for reasons that are just too long to explain I am limited to being only able to use a batch and VBScript.
Batch File:
#echo off
:RENEW
forfiles /m LogTest.txt /d 0
if %errorlevel% == 0 (
echo The file was modified today
forfiles /M LogTest.txt /C "cmd /c echo #file #fdate #ftime"
cscript MessageBox.vbs "Error found."
REM do whatever else you need to do
) else (
echo The file has not been modified today
dir /T:W LogTest.txt
REM do whatever else you need to do
)
goto :RENEW
MessageBox.vbs:
Set objArgs = WScript.Arguments
messageText = objArgs(0)
MsgBox "This is an error", vbOkCancel + vbExclamation, "Error Found"
There is an archive attribute on every file. Windows sets this attribute on every write access to the file.
You can set it with the attrib command and check it for example with:
#echo off
:loop
timeout -t 1 >nul
for %%i in (LogTest.txt) do echo %%~ai|find "a">nul || goto :loop
echo file was changed
rem do workload
attrib -a LogTest.txt
goto :loop
timeout /t 1 >nul: small wait interval to reduce CPU-Load (never build a loop without some idle time)
for %%i in (logTest.txt) do... process the file
echo %%~ai print the attributes (see for /? for details)
|find "a" >nul try to find the "a"rchive-attribute in the output of the previous echo and redirect any output to nirvana (we don't need it, just the errorlevel)
|| goto :loop works as "if previous command (find) failed, then start again at the label :loop"
If find was successful (there is the archive attribute), then the next lines will be processed (echo file was changed...)
attrib -a LogTest.txt unsets the archive attribute of the 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.