11

I am trying to use a BATCH file as a choose your own adventure story in which the user can create a character and be called by name and such by the characters in the story. It hit me an hour back that it would be cool if as or after the BATCH file containing the story was run it made a log of all of the ECHO commands so that later the player could read what they did on any given play threw.

I would like the log file to read like this:

%date% %time% (all text displayed by echo commands for the length the file runs)

Unfortunately all I can figure out how to do is to make a loge file with just the date and time. Putting ">> StoryLog.txt" works to make the .txt file and I get the date and time in there but it just displays the text ">> StoryLog.txt" after what I want the batch file to display in echoed txt as in "You go north down the path >> StoryLog.txt" is shown on the screen. This naturally just wont work. What do I do?

Sean McLain
  • 317
  • 2
  • 3
  • 12

4 Answers4

8

for this purpose I use the following:

set LogFile=somepath\logfile.txt
set logg=^> _^&type _^&type _^>^>%LogFile%
echo this goes to screen AND file! %logg%

This is a bit tricky. So let's disassemble that line to four parts:

set logg=      ^> _          ^&type _           ^&type _^>^>%LogFile%

The Idea is to print the line to a temporary file (named _) (second part) then type the contents of that file to screen (third part) then type it to the logfile (fourth part).

Put that all to a variable (first part), so you don't have to type that monsterstring to every line. (this is the reason why the > and & are escaped with ^)

So every time you use

echo whatever %logg%

it will appear on the screen AND write to %logfile%

Note that this will also work:

 %logg% echo whatever

Edit djangofan: Also, you can do it with functions:

@ECHO off
:: do not enable delayed expansion since it will break this method
SETLOCAL ENABLEEXTENSIONS
SET LogFile=logfile.out
SET Logg=^> tmp.out^&^& type tmp.out^&^&type tmp.out^>^>%LogFile%

CALL :logit "This is my message!"
CALL :logit "Hear my thunder?"

GOTO :end
:logit
ECHO %~1 %Logg%
DEL /Q tmp.out
EXIT /B 0
:end
pause

Edit Stephan: If you use CALL, the %logg% would be overkill. In that case I would just use:

:logit
echo %~1
echo %date%,%time% - %~1 >>logfile
exit /b 0

This might be the best solution to the original question, because the Date/Time will be written into logfile, but not on the screen. Btw: you don't have to delete the tempfile every time you use it, just delete it one time, just before the batch ends.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • Interesting technique. I had hoped that was a nifty in-memory temporary file trick, but it gets written to disk as a file with the single underscore filename. Also in my tests I found that only one `&` is needed ... i.e. `set testout=^>_ ^& type _` ... `dir %testout%` – AjV Jsy Mar 21 '13 at 20:44
  • _ is just used as a buffer - because I need the output (given one time) two times. It is in fact a file and is overwritten every time. And yes, since it is a file, you can use it however you want - until you overwrite it at the next "echo blablabla %logg%" And you are right, a single "&" should do (It was late at night, when I worked this out - and never touched it again, once it worked) – Stephan Mar 21 '13 at 20:44
4

As my other answer got quite long due to some edits, here is a new suggestion (not much changed, but it makes the code quite easy to read):

@ECHO off
SET LogFile=logfile.out
set "say=call :logit "

%say% "This is my message!"
%say% "Hear my thunder?"

GOTO :end
:logit
ECHO %~1 
echo %date% %time% - %~1 >>%logfile%
EXIT /B 0
:end
Stephan
  • 53,940
  • 10
  • 58
  • 91
  • +1, But it fails with text like `%say% "This should be one caret ^ not two"` and `%say% "An ampersand ^& fails"` – jeb Mar 22 '13 at 09:09
  • also |, <, > will fail. Every trick has it's limitations. But I think, it's ok for the initial question. I think a text-adventure will not make use of those special chars. – Stephan Mar 22 '13 at 09:20
0

You cannot do that in batch script literally, but if you define functions, you can output data within the function block that also writes to a log file before the function returns, like so:

@ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
echo. 2>outfile.log

CALL :functionPerson "Jon Doe" jump
GOTO :END
:functionPerson fullname action
  ECHO fullname is ^"%~1^"
  ECHO action is %2
  ECHO %1 performs action %2>> outfile.log
EXIT /B 0
:END
pause
djangofan
  • 28,471
  • 61
  • 196
  • 289
0

Each time you echo for the player to know what happens, you could also echo into your log file, adding date and time at the beginning of your line :) Simple as that for me. Don't know how your script looks though.

callisto
  • 55
  • 1
  • 9
  • Scruffy coding to have pairs of lines everywhere. Better to create a new LogEcho routine which Echos to the screen AND also logs to the file. – AjV Jsy Mar 21 '13 at 15:27