Equal symbol in the title [duplicate] - batch-file

Obviously it is possible to set title that contains cmd's standard delimiters but through TITLE command looks impossible to set a title that starts with a delimiter.
It is possible to create a new instance of CMD with such title:
start "==" cmd.exe
but not possible for the same instance.
It is possible also with .NET and Console.Title property but when it's called from batch file the tile lasts as long as the compiled exe runs:
#if (#X)==(#Y) #end /* JScript comment
#echo off
setlocal
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)
if not defined jsc (
echo !!! Installation of .NET framework needed !!!
pause
exit /b 3
)
rem echo %jsc%
::if not exist "%~n0.exe" (
del /q /f %~n0.exe
call "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
::)
call %~n0.exe %*
endlocal & exit /b %errorlevel%
*/
import System;
var arguments:String[] = Environment.GetCommandLineArgs();
//Console.WriteLine(Console.Title);
if (arguments.length>0){
Console.Title=arguments[1];
}
//Console.WriteLine(Console.Title);
(Probably is possible through code injection)
Is there a windows 'native' way?

With Win7 x64, I can produce it when a linefeed is in front of the problematic characters.
#echo off
setlocal EnableDelayedExpansion
set LF=^
title !LF!,bc
In Win7 there seems no difference in the height or position of the title when LF is used.
Tested with
cmd /V:on
#for /L %n in (1 1 1111) do #(title !LF!=Hello& title +Hello)
But the current program is shown for the time it's running in the title, so the TITLE command itself produces a flicker.

I found another way:
title ^A,string
where ^A is produced by entering 0 1 while holding down the ALT-key ( <pressALT><0><1><releaseALT> ).
You can get it into a file with echo ^A>>batch.bat and then moving it to the correct position with notepad (it's not shown in notepad, like a whitespace; broader than a space, but not as broad as a TAB)

The LF is the answer to the question , but there's also a workaround. I think I've checked all the ASCII characters and looks like FS and GS characters are not displayed in title of command prompt (here's an example with FS):
#echo off
setlocal
::dbenham's hexprint was used here
::http://www.dostips.com/forum/viewtopic.php?p=23888
::Define a Linefeed variable
set LF=^
::above 2 blank lines are critical - do not remove.
::Create a FS variable
call :hexprint "0x1C" FS
title %FS%=;=
exit /b
:hexPrint string [rtnVar]
for /f eol^=^%LF%%LF%^ delims^= %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(%~1"'
) do if "%~2" neq "" (set %~2=%%A) else echo(%%A
exit /b
But this is not a 'perfect' solution as AppActivate or Tasklist command will detect the FS and GS characters (no such problem with LF).
Also SOH character can be used but it is displayed as space.
FS can be produced also with ctrl+]
GS with ctrl+\
SOH with ctrl+A

Related

Can't get the ä, ç, or ã to print correctly using colorEcho in batch

So I want to print Jäger bomb and maçã in yellow where the rest of the line is standard white. The code I have is:
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
call :colorEcho 0e "Jäger bomb"
echo Jäger bomb
call :colorEcho 0e "maçã"
echo maçã
pause
exit
:colorEcho
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1i
The issue is that when it outputs it outputs as "J,,ger" and gives an error saying "FINDSTR: Cannot open maøa". But using the standard echo command both print fine. What's causing this and how do I fix it? Any help is much appreciated!
You need add at the begin of the batch script the chcp command telling the codepage of the encoding of your script file.
If you save your script on utf-8 add: chcp 65001 > nul
If you save your script on ansi add: chcp 1252 > nul
All this is needed for cmd for interpret the extended characters of the batch file using the declared codepage instead the system codepage.
(save the next script with notepad++) :
It produces:
#Echo Off
::This script file is encoded using utf-8
chcp 65001 >nul
::
::Call :Color A "######" \n E "" C " 23 " E "!" \n B "#&calc" \n
Call :Color 0e "Jäger bomb" \n
call :Color 0e "maçã" \n
Pause >Nul
Exit /B
:Color
:: v23c
:: Arguments: hexColor text [\n] ...
:: \n -> newline ... -> repeat
:: Supported in windows XP, 7, 8.
:: This version works using Cmd /U
:: In XP extended ascii characters are printed as dots.
:: For print quotes, use empty text.
SetLocal EnableExtensions EnableDelayedExpansion
Subst `: "!Temp!" >Nul &`: &Cd \
SetLocal DisableDelayedExpansion
Echo(|(Pause >Nul &Findstr "^" >`)
Cmd /A /D /C Set /P "=." >>` <Nul
For /F %%# In (
'"Prompt $H &For %%_ In (_) Do Rem"') Do (
Cmd /A /D /C Set /P "=%%# %%#" <Nul >`.1
Copy /Y `.1 /B + `.1 /B + `.1 /B `.3 /B >Nul
Copy /Y `.1 /B + `.1 /B + `.3 /B `.5 /B >Nul
Copy /Y `.1 /B + `.1 /B + `.5 /B `.7 /B >Nul
)
:__Color
Set "Text=%~2"
If Not Defined Text (Set Text=^")
SetLocal EnableDelayedExpansion
For %%_ In ("&" "|" ">" "<"
) Do Set "Text=!Text:%%~_=^%%~_!"
Set /P "LF=" <` &Set "LF=!LF:~0,1!"
For %%# in ("!LF!") Do For %%_ In (
\ / :) Do Set "Text=!Text:%%_=%%~#%%_%%~#!"
For /F delims^=^ eol^= %%# in ("!Text!") Do (
If #==#! EndLocal
If \==%%# (Findstr /A:%~1 . \` Nul
Type `.3) Else If /==%%# (Findstr /A:%~1 . /.\` Nul
Type `.5) Else (Cmd /A /D /C Echo %%#\..\`>`.dat
Findstr /F:`.dat /A:%~1 .
Type `.7))
If "\n"=="%~3" (Shift
Echo()
Shift
Shift
If ""=="%~1" Del ` `.1 `.3 `.5 `.7 `.dat &Goto :Eof
Goto :__Color
The error is a result of a limitation of the FINDSTR command, as described at https://stackoverflow.com/a/8844873/1012053. Here is the relevant portion of the extensive answer, with the most important bits in bold italics
Character limits for command line parameters - Extended ASCII transformation
The null character (0x00) cannot appear in any string
on the command line. Any other single byte character can appear in the
string (0x01 - 0xFF). However, FINDSTR converts many extended ASCII
characters it finds within command line parameters into other
characters. This has a major impact in two ways:
1) Many extended ASCII characters will not match themselves if used as
a search string on the command line. This limitation is the same for
literal and regex searches. If a search string must contain extended
ASCII, then the /G:FILE option should be used instead.
2) FINDSTR may fail to find a file if the name contains extended ASCII characters and the file name is specified on the command line.
If a file to be searched contains extended ASCII in the name, then the
/F:FILE option should be used instead.
So the problem can be solved by writing the name of the file to a file and using the /F:file option.
Note there is no need to write a new file with the backspace character for every call. You can use a constant file named # if you treat your string as a folder, and then append \..\#. Your # file content should contain 6 backspace characters to get back to the desired string.
The file paths cannot be quoted within the "files.txt" file. This could cause a problem if your string contains a poison character like &. So I store the string in a variable within quotes, and then write using delayed expansion without quotes to preserve the poison character.
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in (
'"prompt #$H#$E# & echo on & for %%b in (1) do rem"'
) do (
set "DEL=%%a"
)
<nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%" > "#"
call :colorEcho 0e "Jäger bomb"
echo(
call :colorEcho 0e "maçã"
echo(
call :colorEcho 0e "this & that"
echo(
pause
exit /b
:colorEcho
setlocal
set "str=%~2"
>files.txt echo !str!\..\#
findstr /v /a:%1 /f:files.txt /r "^$"
This code solves your immediate problem, but the code is still not very robust. Without too much thought, I know of 3 things that will cause it to fail
\ anywhere in the string
/ anywhere in the string
: in the 2nd position
I'm sure there are many other potential problems.
You can find much more robust code at How to have multiple colors in a Windows batch file?.
Look at all the answers, as there are many variations on the theme.
You can choose your favorite :-)

Set CMD title to a forward slash and a question mark (batch)

I am wondering if it is possible to change CMD's window title to /?
I've tried using ^/?, ^/^?, and "/?" but none of them seem to work.
Anyone got any suggestions?
Thanks
It's possible with adding some invisible characters.
The idea is taken from #npocmaka SO: How can I set set a title that start with coma,semicolon or equal sign?
The problem of a title with a starting comma it can be solved also with a LF character, but in your case the LF doesn't help anywhere in the string.
#echo off
(set LF=^
%=empty=%
)
::Create a FS variable
call :hexprint "0x1C" FS
title /%FS%?
exit /b
:hexPrint string [rtnVar]
for /f eol^=^%LF%%LF%^ delims^= %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(%~1"'
) do if "%~2" neq "" (set %~2=%%A) else echo(%%A
exit /b
#ECHO OFF
if "%~1"=="_SO42546112_" (
shift
) else (
start "/?" cmd /D /K ""%~f0" "_SO42546112_""
exit
)
To launch a new CMD command prompt with /? window title, double click above .bat script.
To run a .bat script with /? window title, use above concept e.g. as follows:
#ECHO OFF
SETLOCAL EnableExtensions
rem self wrapper - start
if "%~1"=="_SO42546112_" (
shift
) else (
start "/?" cmd /D /C ""%~f0" "_SO42546112_" %*"
exit /B
rem ↑↑ omit the `/B` switch to close calling `cmd` window
)
rem self wrapper - end
rem check whether the self wrapper works - start
echo 1st "%~1"
echo 2nd "%~2"
echo 3rd "%~3"
echo all %*
pause
rem check whether the self wrapper works - end
rem original script continues here:

How can I set a title that starts with comma, semicolon or equal sign?

Obviously it is possible to set title that contains cmd's standard delimiters but through TITLE command looks impossible to set a title that starts with a delimiter.
It is possible to create a new instance of CMD with such title:
start "==" cmd.exe
but not possible for the same instance.
It is possible also with .NET and Console.Title property but when it's called from batch file the tile lasts as long as the compiled exe runs:
#if (#X)==(#Y) #end /* JScript comment
#echo off
setlocal
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)
if not defined jsc (
echo !!! Installation of .NET framework needed !!!
pause
exit /b 3
)
rem echo %jsc%
::if not exist "%~n0.exe" (
del /q /f %~n0.exe
call "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
::)
call %~n0.exe %*
endlocal & exit /b %errorlevel%
*/
import System;
var arguments:String[] = Environment.GetCommandLineArgs();
//Console.WriteLine(Console.Title);
if (arguments.length>0){
Console.Title=arguments[1];
}
//Console.WriteLine(Console.Title);
(Probably is possible through code injection)
Is there a windows 'native' way?
With Win7 x64, I can produce it when a linefeed is in front of the problematic characters.
#echo off
setlocal EnableDelayedExpansion
set LF=^
title !LF!,bc
In Win7 there seems no difference in the height or position of the title when LF is used.
Tested with
cmd /V:on
#for /L %n in (1 1 1111) do #(title !LF!=Hello& title +Hello)
But the current program is shown for the time it's running in the title, so the TITLE command itself produces a flicker.
I found another way:
title ^A,string
where ^A is produced by entering 0 1 while holding down the ALT-key ( <pressALT><0><1><releaseALT> ).
You can get it into a file with echo ^A>>batch.bat and then moving it to the correct position with notepad (it's not shown in notepad, like a whitespace; broader than a space, but not as broad as a TAB)
The LF is the answer to the question , but there's also a workaround. I think I've checked all the ASCII characters and looks like FS and GS characters are not displayed in title of command prompt (here's an example with FS):
#echo off
setlocal
::dbenham's hexprint was used here
::http://www.dostips.com/forum/viewtopic.php?p=23888
::Define a Linefeed variable
set LF=^
::above 2 blank lines are critical - do not remove.
::Create a FS variable
call :hexprint "0x1C" FS
title %FS%=;=
exit /b
:hexPrint string [rtnVar]
for /f eol^=^%LF%%LF%^ delims^= %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(%~1"'
) do if "%~2" neq "" (set %~2=%%A) else echo(%%A
exit /b
But this is not a 'perfect' solution as AppActivate or Tasklist command will detect the FS and GS characters (no such problem with LF).
Also SOH character can be used but it is displayed as space.
FS can be produced also with ctrl+]
GS with ctrl+\
SOH with ctrl+A

Find the version of a installed program from batch file

We have a batch file that installs several programs as part of the developers setup. This is ran periodically when we get new versions of used components. So it would be nice only to install if the versions are different.
At the command prompt I can run this and get back the version installed:
wmic datafile where name='C:\\Program Files (x86)\\Common Files\\Company\\Product\\Version12\\Product.exe' get version /format:list
Which gives the output Version=12.1.369.0.
However when I put this into a batch file like this and try to extract the version:
echo off
FOR /F "tokens=2 delims==" %%I in ('"wmic datafile where^(name^="C:\\Program Files (x86)\\Common Files\\Company\\Product\\Version12\\Product.exe" get version /format:list"') DO (SET "RESULT=%%I")
ECHO %RESULT%
I get the response \\Common was unexpected at this time.
Some parts may be redundant as I've been trying stuff off the 'Net to correct this.
What have I missed?
You have a set of misplaced double quotes, as well as an extra (.
WMIC uses SQL syntax, and strings are enclosed in single quotes.The internal single quotes do not interfere with the command enclosing single quotes.
You can put double quotes around the WHERE clause (not including the WHERE keyword) to avoid some escape issues within the FOR DO() clause.
#echo off
FOR /F "tokens=2 delims==" %%I IN (
'wmic datafile where "name='C:\\Program Files (x86)\\Common Files\\Company\\Product\\Version12\\Product.exe'" get version /format:list'
) DO SET "RESULT=%%I"
ECHO %RESULT%
But this may not quite be the whole solution. You can't see it with the above code, but RESULT actually contains a trailing carriage return (0x0D). This is due to a quirk with how FOR /F handles WMIC unicode output. Every line of WMIC output will have the extra trailing carriage return.
As long as you always access RESULT using %RESULT% (normal expansion), then you will not have any problems. But if you should ever need delayed expansion, then you can have problems, as demonstrated below.
#echo off
setlocal enableDelayedExpansion
FOR /F "tokens=2 delims==" %%I IN (
'wmic datafile where "name='C:\\Program Files (x86)\\Common Files\\Company\\Product\\Version12\\Product.exe'" get version /format:list'
) DO SET "RESULT=%%I"
ECHO %RESULT%xxx
ECHO !RESULT!xxx
One convenient method to strip the unwanted carriage return is to use an extra level of FOR.
#echo off
setlocal enableDelayedExpansion
FOR /F "tokens=2 delims==" %%I IN (
'wmic datafile where "name='C:\\Program Files (x86)\\Common Files\\Company\\Product\\Version12\\Product.exe'" get version /format:list'
) DO FOR /F "delims=" %%A IN ("%%I") DO SET "RESULT=%%A"
ECHO %RESULT%xxx
ECHO !RESULT!xxx
Here's the subroutine I use for this in my own software update batch script:
:getfattr
set %1=
setlocal
set "name=%~f2"
set "name=%name:\=\\%"
for /f "delims=" %%A in ('wmic datafile where "name='%name:'=\'%'" get %1 /format:list') do #^
for /f "delims=" %%B in ("%%A") do endlocal & set "%%B" & goto :eof
echo>&2 getfattr failed
endlocal
goto :eof
It can get any file attribute supported by wmic datafile get. For example, here's how you might get the file version for the currently installed Adobe Reader:
call :getfattr version "%ProgramFiles(x86)%\Adobe\Reader 11.0\Reader\AcroRd32.exe"
echo "!version!"
After doing that, environment variable version will contain the requested version string. If :getfattr fails, version is guaranteed to be unset.
A test execution trace for that example looks like this (delayed expansion was already enabled, though this is not assumed by :getfattr):
>call :getfattr version "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe"
>set version=
>setlocal
>set "name=C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe"
>set "name=C:\\Program Files (x86)\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe"
>for /F "delims=" %A in ('wmic datafile where "name='C:\\Program Files (x86)\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe'" get version /format:list') do #for /F "delims=" %B in ("%A") do endlocal & set "%B" & goto :eof
>endlocal & set "Version=11.0.18.21" & goto :eof
>echo "!version!"
"11.0.18.21"
As you can see, it's pretty direct and doesn't faff about too much. It does, however, tiptoe through a minefield of cmd and wmic gotchas.
First, the name of the attribute you want to get is also the name used for the variable you want the result to end up in (version in the test above). Inside the subroutine, that name is %1, so set %1= clears it.
The filename you pass in needs a bit of preprocessing before it can be safely handed to wmic and a shell variable is required for that, so setlocal is issued to avoid stomping the caller's variables.
set "name=%~f2" copies the name to an environment variable after stripping off any surrounding double-quotes and expanding it to a full pathname. Double quotes surround the entire set argument to prevent grief caused by ampersands or parentheses in pathnames.
wmic queries use a SQL-like syntax, where string values are surrounded by single quote ' characters and \ is an escape that suppresses any special meaning of the following character. Since both of these are legal in Windows pathnames, all occurrences of either need a \ prefix. set "name=%name:\=\\%" escapes embedded backslashes, and the '%name:'=\'%' construct in the wmic command line escapes embedded single quotes and adds the required surrounding ones.
cmd's parser doesn't turn off special processing between single quotes, and the name no longer has any surrounding double quotes, so embedded spaces, parentheses or ampersands could potentially break things. To guard against that, wmic's entire name= argument gets double quoted. There's no need for special handling for double quotes already inside the name, because double quotes are prohibited in Windows filenames so there can't be any.
The for command line containing the wmic command ends with a #^ sequence. The ^ serves to attach the next line as the payload of the outer for command; the # prevents that payload being echoed in an execution trace even if ECHO is on.
That echo suppression is done mainly because the inner for exists only to get rid of the spurious CR characters injected by cmd's buggy conversion of wmic's output from Unicode to ASCII (the same technique used in #dbenham's answer) and if it's allowed to echo, those CRs just filthy up the trace with confusing overwrites. As a side benefit, the inner for won't execute its own payload when the line it's handed from the outer for contains only a CR, a version-dependent number of which wmic insists on emitting. The inner for's payload does get echoed if ECHO is on, so tracing still captures all the useful happenings.
That payload consists of three &-separated commands, which for will expand as a single command line before cmd gets to process the individual commands. In particular, this means that set "%%B" gets expanded before endlocal runs, which puts the variable created by that set outside the setlocal/endlocal scope and makes it available to the caller.
%%B will always expand in the format name=value because of the /format:list switch passed to wmic; the name will be the same as that specified with the get verb, and this is how the name you pass in ends up choosing the variable you get back. The entire name=value argument to set is quoted in case the requested attribute contains shell-special characters. This makes :getfattr itself safe, but you might want to use !delayed! expansion rather than %premature% expansion wherever you actually use the variable it hands back to you.
The & goto :eof on that same line breaks from both for loops and returns to :getfattr's caller as soon as the inner one actually does anything, just in case you pass in some weird name and wmic get produces more than one non-blank line of output.
The last three lines only ever run if wmic produces no output at all, which is what happens when it fails.
and two ways without external tools
1.WMIC
WMIC DATAFILE WHERE name="C:\\install.exe" get Version /format:Textvaluelist
Pay attention to the double slashes of file name.
Ready to use script/subroutine:
#echo off
:wmicVersion pathToBinary [variableToSaveTo]
setlocal
set "item=%~1"
set "item=%item:\=\\%"
for /f "usebackq delims=" %%a in (`"WMIC DATAFILE WHERE name='%item%' get Version /format:Textvaluelist"`) do (
for /f "delims=" %%# in ("%%a") do set "%%#"
)
if "%~2" neq "" (
endlocal & (
echo %version%
set %~2=%version%
)
) else (
echo %version%
)
exit /b %errorlevel%
Example (it needs a full file path):
call wmicVersion.bat "C:\Windows\System32\cmd.exe" cmdver
echo %cmdver%
2.MAKECAB
as the WMIC is not installed on home versions of windows here's a way with makecab that will run on every windows machine:
; #echo off
;;goto :end_help
;;setlocal DsiableDelayedExpansion
;;;
;;;
;;; fileinf /l list of full file paths separated with ;
;;; fileinf /f text file with a list of files to be processed ( one on each line )
;;; fileinf /? prints the help
;;;
;;:end_help
; REM Creating a Newline variable (the two blank lines are required!)
; set NLM=^
; set NL=^^^%NLM%%NLM%^%NLM%%NLM%
; if "%~1" equ "/?" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; if "%~2" equ "" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; setlocal enableDelayedExpansion
; if "%~1" equ "/l" (
; set "_files=%~2"
; echo !_files:;=%NL%!>"%TEMP%\file.paths"
; set _process_file="%TEMP%\file.paths"
; goto :get_info
; )
; if "%~1" equ "/f" if exist "%~2" (
; set _process_file="%~2"
; goto :get_info
; )
; echo incorect parameters & exit /b 1
; :get_info
; set "file_info="
; makecab /d InfFileName=%TEMP%\file.inf /d "DiskDirectory1=%TEMP%" /f "%~f0" /f %_process_file% /v0>nul
; for /f "usebackq skip=4 delims=" %%f in ("%TEMP%\file.inf") do (
; set "file_info=%%f"
; echo !file_info:,=%nl%!
; )
; endlocal
;endlocal
; del /q /f %TEMP%\file.inf 2>nul
; del /q /f %TEMP%\file.path 2>nul
; exit /b 0
.set DoNotCopyFiles=on
.set DestinationDir=;
.set RptFileName=nul
.set InfFooter=;
.set InfHeader=;
.Set ChecksumWidth=8
.Set InfDiskLineFormat=;
.Set Cabinet=off
.Set Compress=off
.Set GenerateInf=ON
.Set InfDiskHeader=;
.Set InfFileHeader=;
.set InfCabinetHeader=;
.Set InfFileLineFormat=",file:*file*,date:*date*,size:*size*,csum:*csum*,time:*time*,vern:*ver*,vers:*vers*,lang:*lang*"
example output (it has a string version which is a small addition to wmic method :) ):
c:> fileinfo.bat /l C:\install.exe
file:install.exe
date:11/07/07
size:562688
csum:380ef239
time:07:03:18a
vern:9.0.21022.8
vers:9.0.21022.8 built by: RTM
lang:1033
3 Using shell.application and hybrid batch\jscript.Here's tooptipInfo.bat :
#if (#X)==(#Y) #end /* JScript comment
#echo off
rem :: the first argument is the script name as it will be used for proper help message
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%
#if (#X)==(#Y) #end JScript comment */
//////
FSOObj = new ActiveXObject("Scripting.FileSystemObject");
var ARGS = WScript.Arguments;
if (ARGS.Length < 1 ) {
WScript.Echo("No file passed");
WScript.Quit(1);
}
var filename=ARGS.Item(0);
var objShell=new ActiveXObject("Shell.Application");
/////
//fso
ExistsItem = function (path) {
return FSOObj.FolderExists(path)||FSOObj.FileExists(path);
}
getFullPath = function (path) {
return FSOObj.GetAbsolutePathName(path);
}
//
//paths
getParent = function(path){
var splitted=path.split("\\");
var result="";
for (var s=0;s<splitted.length-1;s++){
if (s==0) {
result=splitted[s];
} else {
result=result+"\\"+splitted[s];
}
}
return result;
}
getName = function(path){
var splitted=path.split("\\");
return splitted[splitted.length-1];
}
//
function main(){
if (!ExistsItem(filename)) {
WScript.Echo(filename + " does not exist");
WScript.Quit(2);
}
var fullFilename=getFullPath(filename);
var namespace=getParent(fullFilename);
var name=getName(fullFilename);
var objFolder=objShell.NameSpace(namespace);
var objItem=objFolder.ParseName(name);
//https://msdn.microsoft.com/en-us/library/windows/desktop/bb787870(v=vs.85).aspx
WScript.Echo(fullFilename + " : ");
WScript.Echo(objFolder.GetDetailsOf(objItem,-1));
}
main();
used against cmd.exe :
C:\Windows\System32\cmd.exe :
File description: Windows Command Processor
Company: Microsoft Corporation
File version: 6.3.9600.16384
Date created: ?22-?Aug-?13 ??13:03
Size: 347 KB
This is my filever bat file.
#echo off
If "%~1"=="" goto help
If "%~1"=="/?" goto help
If /i "%~1"=="/h" goto help
If "%~1"=="-?" goto help
If /i "%~1"=="-h" goto help
set filepath=%~f1
set file=%filepath:\=\\%
wmic datafile where name^="%file%" get version|findstr /i /v /c:"version"
echo %errorlevel%
goto finish
:help
Echo.
Echo. FileVer
Echo. -------
Echo.
Echo. Purpose:
Echo.
Echo. Reports the version number for an exe, dll, and similar files.
Echo.
Echo. Usage:
Echo.
Echo. filever ^<executable file^>
Echo.
Echo. filever [/h ^| -h ^| /? ^| -?] Starts this help
Echo.
echo. Examples:
Echo.
Echo. filever c:\windows\explorer.exe
Echo. filever "C:\Program Files\Windows NT\Accessories\wordpad.exe"
Echo. filever shell32.dll
Echo.
Echo. For Help
Echo.
Echo. filever
Echo. filever /?
Echo.
:finish
rem Pause if command double clicked
If /i "%cmdcmdline:~0,6%"=="cmd /c" pause
You seem to have an extra set of quotes around the whole command
One problem with for loops is it wmic outpus a blank line after the version.
set filepath=%~f1
set file=%filepath:\=\\%
for /f "tokens=1 eol= " %%A in ('wmic datafile where name^="%file%" get version^|findstr /i /v /c:"version"') do set a=%%A & echo %%A
Put it in a file. Although the file has two blank lines.
set filepath=%~f1
set file=%filepath:\=\\%
wmic datafile where name^="%file%" get version|findstr /i /v /c:"version">test.txt
Maybe this could work
set filepath=%~f1
set file=%filepath:\=\\%
for /f "tokens=1 eol= " %%A in ('wmic datafile where name^="%file%" get version^|findstr /i /v /c:"version"') do if not ""==%%A set a=%%A & echo %%A
Or call another batch file and don't return.
Here's a way to getrid of blank lines.
set filepath=%~f1
set file=%filepath:\=\\%
for /f "tokens=1 eol= " %%A in ('wmic datafile where name^="%file%" get version^|findstr /i /v /c:"version"^|findstr /i /v /r "^$"') do set a=%%A & echo %A%
wmic datafile where name^="%file%" get version|findstr /i /v /c:"version"|findstr /i /v /r "^$">test.txt
Here is an alternative method, bypasses WMIC for powershell Get-WmiObject.
#ECHO OFF
start /b powershell.exe -command "Get-WmiObject -Class CIM_DataFile -Filter \"Name='C:\\Program Files (x86)\\Knuckle.dll'\" | Select-Object Version"
PAUSE
Returns this result when double clicking a .cmd batch file.
Version
-------
0.0.0.0

Batch script, re-formatting output of a cli application

I have a very small batch script which is extracting a quite amount of files.
The script is meant to be delivered with the compressed data to other users.
Now my problem is that this compression tool is outputting a ton of data into the cmd window.
I think this will confuse a lot of useser because the output is really "running". It basically shows a percentage with each line and how it decompressed at which speed (CPU and HDD).
A lot of confusing data that no one needs to see. Now I don't really like suppressing all the output of the program, giving the user feedback on how far the decompression already got would be important in my opinion.
So is it possible to redirect the output and read just the first three digits of that output and deliver that to the users in a single line? So the users only sees an advancing percantage (in one line) and not 20 new lines every second with all this data?
Here an example of how it looks at the moment:
http://i.imgur.com/5w5LH.png
The compression tool is SREP, my OS Win 7 x64.
If you use windows batch, it can be done, but it's not simple, as you would normally do this with a FOR/F-Loop.
Like for /f "delims=" %%a in (7z packit ...) do ...
The problem is here, that the for-loop will first collect all data and wait for the end of 7z before it process any line of the output.
The only way is to redirect the output, and to scan it simultaneously.
But to do that you need a second thread (at best in the same cmd-window).
Something like this would do the job
#echo off
echo start
setlocal EnableDelayedExpansion
if "%1"=="internal" goto :readThread
start /b cmd /c ""%~f0" internal"
rem *** myPacker pack here and redirect the output
del archive.7z
del output.tmp
start "title" /b /wait cmd /c "%ProgramFiles%\7-Zip\7z" u archive \tempx\*.rtf \tempx\*.pdf ^> output.tmp
echo EOF>>output.tmp
echo ENDE
:waitForEnd
(
> lock (
rem
) || goto :waitForEnd
) 2> nul
exit /b
:readThread
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
echo ####!cr!x
echo(
<output.tmp (
echo ## before
call :readData 2> lock
echo after
)
exit /b
:readData
set "var="
set /p var=
if "!var!"=="EOF" exit /b
if defined var (
<nul set /p ".=Processing files, currently at !var:~0,4!!CR!"
)
goto :readData
Here is a simple hybrid batch/JScript script that I think will do what you want.
show3.bat
#if (#X)==(#Y) #end /* harmless hybrid line that begins a JScrpt comment
::: Batch part ::::
#cscript //nologo //e:JScript "%~f0"
#exit /b
*** JScript part ***/
while( !WScript.StdIn.AtEndOfStream ) {
WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();
Usage:
yourCommand | show3
The script could be simplified to pure JScript, but then it won't be as convenient to use:
show3.js
while( !WScript.StdIn.AtEndOfStream ) {
WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();
Usage:
yourCommand | cscript //nologo show3.js
EDIT As jeb commented, you should not need any redist to use this solution.
I've taken some of the concepts in jeb's answer and combined the entire process into one hybrid script. No need for a standalone "show3" file.
#if (#X)==(#Y) #end /* harmless hybrid line that begins a JScrpt comment
:: ***** Batch part ******
#echo off
REM whatever batch code you need goes here
yourCommand | cscript //nologo //e:JScript "%~f0"
REM whatever batch code you need goes here
exit /b
****** JScript part ******/
while( !WScript.StdIn.AtEndOfStream ) {
WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();
yourCommand would be whatever compression command you are using. Based on your comments, it sounds like you might have to use yourCommand 2>&1 if the output you want is printing to stderr instead of stdout.
I've created a "yourCommand.bat" file for testing purposes. It crudely emulates the output behavior you describe for your compression program.
#echo off
for /l %%A in (1 1 100) do (
echo %%A "I don't want to see this quoted text"
for /l %%B in (1 1 50000) do rem
)
Finally, if you really want a pure batch solution, I greatly simplified jeb's solution. I eliminated the temp file and used a pipe instead.
#echo off
if "%~1"==":show3" goto :show3
REM whatever batch code you need goes here
(yourCommand & echo EOF) | "%~f0" :show3
REM whatever batch code you need goes here
exit /b
:show3
setlocal enableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
:read
set "ln="
set /p "ln="
if not defined ln goto :read
for /f "tokens=1* delims= " %%A in ("!ln!") do if "%%A%%B" equ "EOF" (
echo(
exit /b
)
<nul set /p "=!ln:~0,3! !cr!"
goto :read
Edit - I modified the EOF test to ignore any leading or trailing spaces. This should make the code more robust.

Resources