Batch script terminates in case of error when using pipe operator - batch-file

I need to perferm error handling (check ERRORLEVEL) on an operation involving the pipe operator, but instead of the script continuing with a non-zero ERRORLEVEL, it terminates immediately. How can I avoid this behavior?
Consider the following example. (Note that is a simplified constructed example to illustrate the problem - not a meaningful script)
someinvalidcommand
echo nextline
This will result in
> 'someinvalidcommand' is not recognized as ... command...
> nextline
In other words, the script continues after the error.
Now consider
echo firstline | someinvalidcommand
echo nextline
This will result in only
> 'someinvalidcommand' is not recognized as ... command ...
That is, it terminates before evaluating "echo nextline"
Why this behavior and how to avoid it ? The purpose is to perform something similar to
someoperation | someotheroperation
IF NOT %ERRORLEVEL% == 0 (
handleerror
)
but the error handling has no effect since it stops early.

Delegate it to another cmd instance
cmd /c" someoperation | someotheroperation "
if errorlevel 1 (
handleerror
)

Related

AIX Shell Prepend code being run to an output logfile along with stdout data

How do I prepend the code I ran, either directly at the shell prompt or via shell-script to an output logfile I created.
#something like this
echo ' Until < code > do ; <code> done; case <code> esac ; ' >> op.log ;
Until < code > do ; <code> done; case <code> esac ; | tee -a op.log
Instead of crafting an echo statement I'd like to know if its poss through a 'cody' approach to capture whatever you just ran and stick that in your log file, ( at the beginning ) so when I open that log - I 'll know what code produced this . It should be a one time prepend as against repeating with every loop iteration.

Getting a Windows command prompt contents to a text file

I want to write a batch utility to copy the output of a command prompt window to a file. I run my command prompt windows with the maximum depth of 9999 lines, and occasionally I want to grab the output of a command whose output is off-screen. I can do this manually with the keys Ctrl-A, Ctrl-Cand then pasting the result into Notepad - I just want to automate it in a batch file with a call to:
SaveScreen <text file name>
I know I can do it with redirection, but that would involve knowing that I will need to save the output of a batch command sequence beforehand.
So if I had a batch script:
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 goto :ErrorExit
I could write:
cls
call BuildPhase1.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase1.err & goto :ErrorExit
call BuildPhase2.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase2.err & goto :ErrorExit
call BuildPhase3.bat
if "%ErrorLevel% gtr 0 call SaveScreen.bat BuildPhase3.err & goto :ErrorExit
or I could just type SaveScreen batch.log when I see that a run has failed.
My experiments have got me this far:
<!-- : Begin batch script
#cscript //nologo "%~f0?.wsf" //job:JS
#exit /b
----- Begin wsf script --->
<package>
<job id="JS">
<script language="JScript">
var oShell = WScript.CreateObject("WScript.Shell");
oShell.SendKeys ("hi folks{Enter}") ;
oShell.SendKeys ("^A") ; // Ctrl-A (select all)
oShell.SendKeys ("^C") ; // Ctrl-C (copy)
oShell.SendKeys ("% ES") ; // Alt-space, E, S (select all via menu)
oShell.SendKeys ("% EY") ; // Alt-space, E, Y (copy via menu)
// ... invoke a notepad session, paste the clipboard into it, save to a file
WScript.Quit () ;
</script>
</job>
</package>
My keystrokes are making it to the command prompt so presumably I have the correct window focused - it just seems to be ignoring the Ctrl and Alt modifiers. It also recognises Ctrl-C but not Ctrl-A. Because it has ignored the Ctrl-A to select all the text, the Ctrl-C causes the batch file to think it has seen a break command.
I've seen the other answers like this one but they all deal with methods using redirection, rather than a way of doing it after the fact "on demand".
* UPDATE *
On the basis of #dxiv's pointer, here is a batch wrapper for the routine:
Get-ConsoleAsText.bat
:: save the contents of the screen console buffer to a disk file.
#set "_Filename=%~1"
#if "%_Filename%" equ "" #set "_Filename=Console.txt"
#powershell Get-ConsoleAsText.ps1 >"%_Filename%"
#exit /b 0
The Powershell routine is pretty much as was presented in the link, except that:
I had to sanitise it to remove some of the more interesting character substitutions the select/copy/paste operation introduced.
The original saved the trailing spaces as well. Those are now trimmed.
Get-ConsoleAsText.ps1
# Get-ConsoleAsText.ps1 (based on: https://devblogs.microsoft.com/powershell/capture-console-screen/)
#
# The script captures console screen buffer up to the current cursor position and returns it in plain text format.
#
# Returns: ASCII-encoded string.
#
# Example:
#
# $textFileName = "$env:temp\ConsoleBuffer.txt"
# .\Get-ConsoleAsText | out-file $textFileName -encoding ascii
# $null = [System.Diagnostics.Process]::Start("$textFileName")
#
if ($host.Name -ne 'ConsoleHost') # Check the host name and exit if the host is not the Windows PowerShell console host.
{
write-host -ForegroundColor Red "This script runs only in the console host. You cannot run this script in $($host.Name)."
exit -1
}
$textBuilder = new-object system.text.stringbuilder # Initialize string builder.
$bufferWidth = $host.ui.rawui.BufferSize.Width # Grab the console screen buffer contents using the Host console API.
$bufferHeight = $host.ui.rawui.CursorPosition.Y
$rec = new-object System.Management.Automation.Host.Rectangle 0,0,($bufferWidth - 1),$bufferHeight
$buffer = $host.ui.rawui.GetBufferContents($rec)
for($i = 0; $i -lt $bufferHeight; $i++) # Iterate through the lines in the console buffer.
{
$Line = ""
for($j = 0; $j -lt $bufferWidth; $j++)
{
$cell = $buffer[$i,$j]
$line = $line + $cell.Character
}
$line = $line.trimend(" ") # remove trailing spaces.
$null = $textBuilder.Append($line)
$null = $textBuilder.Append("`r`n")
}
return $textBuilder.ToString()
The contents of the console buffer can be retrieved with the PS script from PowerShell's team blog Capture console screen mentioned in a comment, now edited into OP's question.
The last line could also be changed to copy the contents to the clipboard instead of returning it.
Set-Clipboard -Value $textBuilder.ToString()
As a side note, the reasons for using a StringBuilder rather than direct concatenation are discussed in How does StringBuilder work internally in C# and How the StringBuilder class is implemented.

What does "+_" in bash mean? [duplicate]

What does this mean?
if ${ac_cv_lib_lept_pixCreate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
Looks like ac_cv_lib_lept_pixCreate is some variable, so what does +: mean?
Where to learn complete syntax of curly bracket expressions? What is the name of this syntax?
In the “plus colon” ${...+:} expression, only the + has special meaning in the shell. The colon is just a string value in this case, so we could write that snippet as ${...+":"}.
For convenience, let's pretend the variable is called var, and consider the expression:
if ${var+:} false; then ...
If the shell variable $var exists, the entire expression is replaced with :, if not, it returns an empty string.
Therefore the entire expression ${var+:} false becomes either : false (returning true) or false (returning false).
This comes down to a test for existence, which can be true even if the variable has no value assigned.
It is very cryptic, but as it happens, is one of the few tests for the existence of a variable that actually works in most, if not all, shells of Bourne descent.
Possible equivalents: (substitute any variable name here for var)
if [[ ${var+"is_set"} == is_set ]]; then ...
Or, probably more portable:
case ${var+"IS_SET"} in IS_SET) ...;; esac
Shell Parameter Expansion documentation for bash is here. No mention of +:, though it does mention :+:
${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
To illustrate what has already been said:
Unset variable (note the blank lines as a result of some echo commands):
$ unset foo
$ echo ${foo}
$ echo ${foo:+:}
$ echo ${foo+:}
Null variable:
$ foo=""
$ echo ${foo}
$ echo ${foo:+:}
$ echo ${foo+:}
:
Non-null variable:
$ foo="bar"
$ echo ${foo}
bar
$ echo ${foo:+:}
:
$ echo ${foo+:}
:
Simple examples will prove
I check for presence of a parameter TEST, if present echo "Yes" else I echo "No"
openvas:~$ ${TEST+:} false && echo "yes" || echo "no"
no
openvas:~$ TEST=1
openvas:~$ ${TEST+:} false && echo "yes" || echo "no"
yes
openvas:~$
If you see, the parameter TEST is evaluated and it is actually unset, so it returns false and exit the path and goes to the OR
Once I set the same, and test again, it flows to the echo part (continued &&) since it returns true
Refer: this and that

What is the meaning of ':Q=' in variable name in batch cmd

I have the following batch command line:
if not x%COMPUTERNAME%==x%COMPUTERNAME:Q=% (
echo 1
) else (
echo 2
)
What is the meaning of :Q= in the variable COMPUTERNAME
Whatever I enter as value of the variable it always goes to the else block.
%variable:<searchstring>=<replacestring>% replaces one string (in your example Q) with another (in your example an empty string)
The whole if is : "if the variable is the same as when I remove the Q then" or in other words: "is there a Q in the variable?"
Read the help for set /? and if /?

Syntax quirk on assigning a string with parentheses to a variable within an IF block

Below is a BAT file sample which shows a curious behaviour. When a "SET" is used inside () an IF statement we get an error, if we have other code besides a SET then no problem.
I created a work around by doing the SET on the IF line and doing the other logic I need in a normal
IF ... ( stuff ) ELSE ( more )
Does someone know what is going on here?
NB: Same outcome if SETLOCAL is used
::SETLOCAL ENABLEDELAYEDEXPANSION
echo **This works**
#set InstallerTest=false
#IF "%InstallerTest%"=="true" #SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe
#IF NOT "%InstallerTest%"=="true" #SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signfalse.exe
SET SESign_Exe
ECHO **THIS PRODUCES NO ERROR**
#IF "%InstallerTest%"=="true" (
echo IN TRUE PART
) ELSE (
ECHO IN FALSE PART
)
echo **this produces : \Schneider was unexpected at this time.**
#IF "%InstallerTest%"=="true" (
SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe
) ELSE (
SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signfalse.exe
)
::ENDLOCAL
Open a command prompt window and execute there cmd /?. At bottom of the last help page output into the console window you can read which characters in strings require surrounding double quotes: the space character and &()[]{}^=;!'+,`~
The reason is easy to understand. The space character is the separator for the "words" (commands, options, parameters, keywords, ...) on command line.
The other characters have special meanings in Windows command line syntax. A not escaped and not in quoted string defined ( marks beginning of a block an ) marks end of a block if not escaped or within a quoted string.
Therefore you need
set "SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe"
And you should really use always set "variable=value".
See for example answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? for an explanation with an example why using set "variable=value" is always better than using just set variable=value.

Resources