My batch files (.cmd) sometimes execute partial lines - windows

I've a strange problem that I have never seen before in my ~30 years of working with batch files. Given a dummy CMD file such as this:
#echo off
:somelabel
echo Testing something
dir /b
echo All is well.
:end
This mostly runs as expected, but sometimes I get output such as 'ing something' is not recognized as an internal or external command, operable program or batch file.
That's clearly an occurrence where it has chopped off a bit of a line and attempted to execute the rest of it. When this happens, it's always a 'random' fraction of a 'random' line; it's not always line X, or losing Y characters, or occurring where I have a particular character combination. Nor does it affect only echo statements, it could just as well try to execute abel or ir /b.
My system is a fully updated Win2008 R2, running in VirtualBox 5.0.2, running in a fully upgraded Linux Mint, running on a Lenovo ThinkPad. The scripts are all UTF-8 encoded.
... what's going on? How can I avoid this?

Well, in my experience there is no way that a normal Batch file may present this behavior. The only way this can happen is if the Batch file is modified while it is running, so the cmd.exe processor continue reading the "next line" of the Batch file, but at that position in the modified file there is a part of another line. The example below show this behavior:
#echo off
:somelabel
(for /F "skip=1 delims=" %%a in (%~NX0) do echo %%a) > temp.tmp
del "%~NX0" & ren temp.tmp "%~NX0"
echo Testing something
echo All is well.
:end
In this example after the del ... & ren ... line is executed, the next line to execute will be read at the beginning of original position of echo Testing something line, but now at that point there is its ing something part because the first #echo off line was deleted. See this:
#echo offRL
echo Testing something
In previous scheme the RL letters exemplify the CR+LF control characters, so the next position is at the "ing".

Credit goes to #SomethingDark for the comment:
The command line doesn't play nice with UTF-8. Use ANSI instead.
This seems to have resolved the issue (as far as I can be sure with an intermittent problem).

I know this is a couple years late but I actually found the most accurate answer.
I actually did some testing on why it could register only partial code and got the answer. If you are editing the code and run batch while still open, it has a partial chance of only registering partial code. This is actually correct, nothing with encoding although that might be part of it except still does it to me with ANSI but with some testing, I realize that isn't it and that it is because batch cannot catch up with you when editing the code.
I did type a comment on the answer marked as best and said what I think but after further testing on the question I realized the pattern is when editing the code and running the batch file while still open, almost right away it seems to only read partial code.
When you said it seems to work when changing encoding to ANSI, did you just run it or did you edit it and run it at the same time. The main reason I did want to answer this is because my encoding method on a batch file I am working on is in ANSI and still causes the error of partially reading the code. Once I read Aacini answer, it gave me a thought of it and that he is partially correct to KlaymenDK situation.
Do prevent the error of partially reading the code modify and wait a bit than run and if that doesn't work than restart it. If you are planning on publicly posting it, you don't really have to worry about the problem because it would most likely only occur if you edit the code while running it. Nothing that could really be a problem with your code as I know.

Recently I run into the same problem, although the cause might be different.
In my case there was an REM command with text which have special characters in other languange. After I erased the REM command, the problem was solved.
For disclosure the problem did not happened in all computers the code was executed, and still dont know why will special characters cause the batch file to execute partial lines.

Related

Batch file "to many command-line parameters"

So, for Windows 2000, I'm making kind of a program spammer thing. There is another batch file, that, at the end, calls in the program spammer file. The problem I'm having is adding it saying "to many command-line parameters". This is the current code I have to add it to startup.
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v begin-second /t REG_SZ /f /d C:\Documents and Settings\%LOCALUSER%\Desktop\bat script\begin-second.bat
The rest of the script consists of lines like this:
start <EXE file in system32 or WINNT openable by Run>
And there are a few of these "ping" commands serving as a pause in the program for a selectable amount of time:
ping 1.1.1.1 -n 1 -w 1000>nul
Can somebody help me here? The code to add it to the startup throug the registry probably has something wrong with it. When I launch the .bat file, it just spams the programs. I have Registry Editor open, but nothing changes in this directory, the same one the command uses to write the SZ key to the registry, at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.
I'm kind of a person learning Batch, so it's pretty obvious why I'm having issues. I'm not experienced enough. What I'm looking for is a workaround, or something to fix this "to many parameters" thing. Also, remember, I'm programming this in Windows 2000.
You need to put your data (after the /d) in quotes, or else it will interpret the spaces in the filename as separators between different parameters.

Batch wont execute but just re-print its content

No matter what my code is, even if my batch file is syntactically incorrect, even if it is absolutely correct and even if there is nothing to display on the screen the batch file when executed just displays the code as it is.
I read a similar question MSDOS prints the whole batch file on screen instead of executing but since that was on MS-DOS I hoped my issue could have a solution different than that.
Eg,
#echo off
set abcd=4
Even its batch file would just display the same lines as it is.
Please help.
Try "resetting" cmd if possible. U can try copying someone else's "cmd.exe" and replace it with yours using another bootable OS as windows wont allow that.
Here use my cmd.exe. https://drive.google.com/open?id=0B6ghonMKBfUSLVpRV0U5bG5pQTQ
Just in case u need to know I am using Windows 10 64 bit.
Check the file with an editor that allows you to see the encoding.
For example Notepad++ , you will see is very different the end of line via CF (\r) and LF (\n)
Your CMD can be recognizing EOL via \n only.
To determine whether your issue is really with line breaks being converted by your text editor (as the post you mention suggests), perform the following test:
Open a Command Line Window
Type the following command: copy con test.bat
The cursor will reposition itself under the command prompt, this is normal
Type the following 3 commands, each followed by the [Enter] key:
.
Echo Off
Set abcd=4
Echo abcd
Press CTRL-Z simultaneously (it will show up on screen as ^Z)
A confimation message should state: 1 file(s) copied.
Now type Test to run the batch file. If it runs properly, it means you are indeed dealing with line termination issues. Use a different text editor (don't use Notepad!!!), ideally one where you have an option to display the line termination characters (I personnally use NotePad++, it works great for these kinds of things but there are many others out there).
Perhaps there is a problem with your environment variables. Check the following:
Press WIN + R and run "%SYSTEMROOT%\System32\SystemPropertiesAdvanced.exe"
Click on "Environment Variables"
The system variables are listed at the bottom. Select the variable "Path" and click "Edit..."
Check whether the list contains "C:\Windows\System32" or "%SYSTEMROOT%\System32". If not, add one of those. You may have to restart your computer afterwards.

CMD: Fails with %1

Recently i posted a question about what the variable is of a file which you open with a batch file, which is %1.
I used this, to let my batch file copy %1 to a specific location.
After doing this, debugging and a lot of time, and it actually worked, after debugging it more, adding some features, and some more debugging, it stopped working. This is a snippet, where it seems it goes wrong (i tried #echo on to get my info.)
if not "%1:~-8%"==".package" (
set error=yes
set errmes1=File %1 does not have a .package extension.
goto :errpkg
)
copy "%1" "C:\path_to\folder"
:errpkg
cls
echo %errmes1%
...
(%1=C:\path\to\it\file_something.package)
This is the point were it goes wrong, i guess. Because it ends up with this message. What it SHOULD do, is at if not checking if the file has a .package extension. then, set error=yes, just says what it does, set errmes1 sets an error message. and then the goto just goes to some place in the batch file where it explains what the problem is. (using %errmes1%)
So, that's it. Here is where it goes wrong. I am 100% sure it has a .package extension. Could anyone help me, to tell me what the problem is?
I seriously wonder how you ever got that to work. The substring syntax only works on environment variables (well, and pseudo-variables such as %cd%). That means you can do
%foo:~-8%
but not
%1:~-8%
This wouldn't even work if you had an environment variable named %1%.
Anyway, the usual idiom to check for the extension of an argument is
%~x1
So why complicate things more than necessary?
Tried using %~x1 to extract the extension? Your syntax doesn't work for me.
Also, can't setting variables inside the conditional get screwy in cmd.exe?

Why "The system cannot find the batch label specified" is thrown even if label exists?

While running a batch file in Windows XP I have found randomly occurring error message:
The system cannot find the batch label specified name_of_label
Of course label existed. What causes this error?
Actually, you need 2 conditions for this to happen:
the batch file must not use CRLF line endings
the label you jump to must span a block boundary (as opposed to and :end label wich is just a shortcut to the end of your script)
See. The system cannot find the batch label specified (by and Batch-as-batch-can!
David A. Gray mentions in the comments seeing (on Windows 10) what Marshal's answer showed in 2014 (presumably on Windows 7 or 8): a script/batch program (.bat or .cmd) executed without CALL would trigger an eol conversion.
I've written hundreds of batch scripts over the last 35 years, and the only time I've ever had an issue with labels not being found was when the file's line breaks got converted from Windows (CR/LF), which works, to Unix (LF), which doesn't.
Feb. 2020, kinar adds in the comments:
Just encountered this issue on a Win7 machine.
Turns out this error can also be generated when trying to CALL another .bat file if that file doesn't exist on the system.
In my case, I was trying to call the Visual Studio vcvarsall.bat file on a system without VS installed.
See jeb's answer for more: it was a case of an undefined label.
Note: in a Git repository, I would recommend a .gitattributes file with the directive:
*.bat text eol=crlf
I have got the same issue before. However, the root cause was not CRLF at all. It was because in the script I executed an external program such as Ant, but did not put a CALL before Ant. So, make sure you CALL every external program used in your batch script.
If batch file has unix line endings (line separators) this can sometimes happen.
Just unix2dos it and problem should be solved.
Here is the issue and how to fix it. The issue is a bug or a feature in DOS batch cmd program. First the clear problem statement. If you have a DOS batch file with target labels like, ":dothis", and at the end of the label you do not have space then the batch file will not work if the line ending are UNIX line endings. This means you have to run unix2dos on the file before you can use it.
The root cause is the DOS command line processor, (shell program), takes the UNIX end-of-line character as part of the label. Since the go to part never uses this as the label, it is never found since such a label truly does not exist. The solution is to put an extra space at the end of each target label, or even better every line. Now UNIX end of lines do not come to play since the space acts as the separator and it all works.
You should also make sure that when calling other scripts you use CALL, instead of calling them in the caller's environment.
I encountered a similar issue just now with a .cmd file and Windows 8.
The solution was to change all line endings to CR+LF DOS style.
The issue was confusing because the batch file mostly worked and rearranging lines changed the effect.
The .cmd file looked like:
call:function_A "..\..\folderA\"
call:function_B "..\..\folderB\"
call:function_C "..\..\folderC\"
call:function_D "..\..\folderD\"
goto:eof
:function_A
rem do stuff
goto:eof
...etc...
Function C would cause error "The system cannot find the batch label specified". Strangely it could go away by rearranging the calls.
Changing line endings from 0x0A to 0x0D0A seems to have fixed it.
Perhaps VonC meant "the batch file must use CRLF line endings".
There are multiple possible ways to get the error.
Described by VonC - Wrong line endings, LF instead of CR/LF
Obscure long lines (if that happens accidential, your code is incredible worse)
Direct start another batch after calling a function.
Sample:#echo off
call :func
echo back from second
exit /b
:func
second.bat
echo NEVER COME BACK HERE
This unexpectedly tries to goto to the label :func in second.bat.
But this can be (mis)-used to directly call labels in another batch file
This is the described behaviour of the answer of Marshal
i had this issue after copying a start command from word and paste it into the command window. There was a option with "-" on front, and thought the looks the same as the DOS "-" it wasn't :) After typing the "-" by myself the issue was solved and the batch worked ... a hard to find issue ....
Little different use case ...
I was calling a bat script during packer build of Windows Server 2012 Server, using the shell provisioner (OpenSSH).
Now, the script was working fine through cmd in the provisioned Virtual Machine (put breakpoint in packer build to stop and confirmed this) ... but, it was failing with these call labels not found issues.
The Line Endings were fine, CRLF (confirmed in Notepadd++). The script was working fine through command line as well. What more, sometimes, it just use to run fine and sometime fail, but once failed for some label, the failure was consistent.
Initially, I just started removing the subroutines altogether by expanding the call itself and putting subroutine code inline. I did this for all instances where there was only one call (no code duplication).
But, yeah, i did stumble upon one sub which was called from 3,4 places. After trying everything, this is what worked for me
Adding 8-10 REM statements just above the subroutine. Yes, I am not kidding !!
PS : The script is very very old, but management needed me to make that work through packer (we have a Day-2 plan of this to replace it with Ansible/Chef).
I had the error :
The system cannot find the batch label specified -
and I found that on a line I used
goto : eof
instead
goto :eof
So check for the same issue of using labels, if the solutions from above didn't worked out.

How to capture and display output from a task via Windows CMD

I've got a PHP script which I'm running from a command line (windows) that performs a variety of tasks, and the only output it gives is via 'print' statements which output direct to screen.
What I want to do is capture this to a log file as well.
I know I can do:
php-cli script.php > log.txt
But the problem with this approach is that all the output is written to the log file, but I can't see how things are running in the mean time (so I can stop the process if anything dodgy is happening).
Just to pre-empt other possible questions, I can't change all the print's to a log statement as there are far too many of them and I'd rather not change anything in the code lest I be blamed for something going fubar. Plus there's the lack of time aspect as well. I also have to run this on a windows machine.
Thanks in advance :)
Edit: Thanks for the answers guys, in the end I went with the browser method because that was the easiest and quickest to set up, although I am convinced there is an actual answer to this problem somewhere.
You can create a powershell script that runs the command, reads the data from the command's STDOUT then outputs the output to both the log file and the terminal for you to watch. You can use the commands Write-Output and Write-Host.
Microsoft's site: http://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/tee-object.mspx
Another option would be use find a tee program that will read input and divert it to two different outputs. I believe I have seen these for windows but I don't think they are standard.
Wikipedia: http://en.wikipedia.org/wiki/Tee_(command)
I have always opened the log file up in my web browser. This allows me to refresh it easily and does not interrupt any writing to the file that windows does. It isn't particularly elegant but it does work!
You want the "tee" command for Windows. See http://en.wikipedia.org/wiki/Tee_(command)
Powershell includes a tee command, and there are also numerous versions of tee for Windows available, for instance:
http://unxutils.sourceforge.net/
http://www.chipstips.com/?p=129
Also can be implemented in VBScript if you prefer.
EDIT: Just occurred to me I should also mention the tail command: http://en.wikipedia.org/wiki/Tail_(Unix). Tail allows you to read the last N lines of a file, and also includes a "file monitor" mode that just continually displays the end of the file in real-time. This is perfect for log file monitoring since it allows you to watch the log in real-time without interfering with the process that's writing to the log. There are several implementations of tail for Windows, both command line and GUI based. Microsoft's Services For UNIX packages (or whatever they're calling it now) also include a version of tail. Some examples:
mTail
Tail for Win32
WinTail
MakeLogic Tail
Some of these go far beyond just displaying the file in real-time as it updates and can send email alerts and colorize string matches, monitor multiple files at once, etc.
Slow:
for /f "delims=" %a in ('php-cli script.php') do #echo %a&echo %a>>log.txt
or in a batch file:
for /f "delims=" %%a in ('php-cli script.php') do #echo %%a&echo %%a>>log.txt

Resources