BinToBat.bat - Easily install files of any type or size!

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#16 Post by Aacini » 11 Jan 2014 00:13

siberia-man wrote:Why the number of leading spaces to be trimmed is limited by 3 and 29?
I cannot understand what is the big difference between 29 and 30 leading spaces =)Why leading spaces only, not trailing?
Is it possible to rewrite it to be better understandable? What will happen if I replace the part above by the following example (it looks much better):

Code: Select all

// Encode the number of leading spaces
var re = /^ +/;
var m = re.exec(inputLine) || { lastIndex: 0 };

inputLine = inputLine.slice(m.lastIndex);
outputLine += m.lastIndex;


update

Could you be so kind as to perform the following changes to your script
1. Replace the first line of the script with (append the opening js-comment /*)

Code: Select all

@if (@CodeSection == @Batch) @then /*

2. Put the closing JS-comment between cmd and js parts



The idea is to compress leading spaces in the shortest possible way. The first digit in the number of compressed spaces specify the range of the whole number this way:

0- No compressed spaces
1- From 10 to 19 spaces (2 digits)
2- From 20 to 29 spaces (2 digits)
3 to 9- From 3 to 9 compressed spaces (1 digit each)

This method does not allow to compress 1 or 2 spaces nor more than 29, but it is very efficient in this range because it does not require any additional delimiter character. Of course, it would be possible to compress other ranges and/or trailing spaces, but this modification would require the insertion of delimiter characters that would do the output larger when the input does not have these spaces. I wrote this method based on my personal requirements. The text files that I want to compress are primarily Batch and JScript source code that have left justification margins comprised of multiples of 3 spaces.

The regexp method is "better understandable" if you know regular expressions; otherwise is entirely cryptic! Also, I don't like the /* multi-line comment */ method because the */ closing characters may be easily ignored by people that don't know JScript. Remember that the primary audience for all these programs are Batch file programmers (this is not a JScript forum).

Antonio

siberia-man
Posts: 208
Joined: 26 Dec 2013 09:28
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#17 Post by siberia-man » 12 Jan 2014 04:13

Hi Antonio,

Thank you for your response. Take a look on my critics =)

I don't like the /* multi-line comment */ method because the */ closing characters may be easily ignored by people that don't know JScript. Remember that the primary audience for all these programs are Batch file programmers (this is not a JScript forum).

It is very strange argument. Non-js folks could left alien @end and ignore trailing */

The idea is to compress leading spaces in the shortest possible way

I don't see reasons to dance around spaces because they are similar to other characters. I think it is possible to remove this part of the code without breaking the main functionality. Do you confirm this?

Maybe the more interesting idea is to compress chains of duplicated characters, for example, AAAA -> 41414141 -> 04[41]

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#18 Post by Aacini » 30 May 2016 11:14

I developed a new method to encode binary data into text that may decrease the size of the generated text file; this is achieved using all printable characters of the Ascii extended character set: from 32 to 255. In the encoded text the control characters 0-31 and the Ascii-160 are not used, so 223 different characters can be included in the encoded file. The quote and Ascii-255 are used to escape and delimit other characters, so 221 "literal" characters are directly copied to the output file and the rest of 35 "not-literal" characters are encoded via escaped replacement chars. Note that the 223 base characters are not used in the same way as in Base64 or Base85 methods, so I called "Set223" this method (instead of "Base223"); a complete description of the encoding method is included in the conversion program.

The key point for this method to work is that the values of all bytes posted in a web site be correctly copy-pasted in a text file independently of the way the browser display such bytes on the screen. The Ascii-160 is the only printable character that is changed by some browsers, so it is not included in the encoded text. I correctly copy-pasted a "Set223" encoded test file that include all the 223 characters from this site and from StackOverflow using both Internet Explorer 10 and Google Chrome 49.0, so I think that the posted data can be correctly copied by other web browsers. I'll appreciate it if you may confirm that the "Set223" example data below can be correctly copied in other versions of IE or Chrome, or in other web browsers.

This method was designed to perform best when encoding small Windows .exe executable files that contain large sets of literal and not-literal characters; in this case, the overhead is minimum (about 3-5 %) because just one or two escape characters are inserted before each set. If the file have also large groups of binary zeros (common in .exe files) or groups of bytes with values below 32 then they are compressed in a few characters, so the "Set223" encoded text file may even be smaller than the original. If the input file don't have this format, then the encoded file will be larger; for example, three escape characters are inserted at end of each line in text files. Below there is a table with the sizes of some typical .exe files I wrote and the very large CMD.EXE Windows file (that I correctly encoded/decoded using this method), and the sizes of the generated "Set223" encoded files with the percentage of this size vs. the original one:

Code: Select all

Original .exe file and size       "Set223" file size and percentage

CursorPos.exe         1,536       1,013       66%
StdDate.exe           3,072       2,033       66%
ColorShow.exe         3,584       2,540       71%

printf.exe            5,120       4,847       95%
Test1.exe             7,168       6,888       96%
Test2.exe             9,216       9,211      100%

cmd.exe             404,992     376,168       93%   Version 6.2.9200 (Windows 8.1 Spanish)

The first 3 programs have not any text, just executable code, and the next 3 programs have a lot of text messages. CMD.EXE file have several very large groups of repeated binary bytes, like zeros, that are compressed in the encoding.

Unlike the former versions of the encoding/decoding programs posted on this thread, the new BinToBat223.bat encoding program is very simple to use: just place in the parameters the names of the files to encode (wild-cards allowed) and the conversion program will create a self-extracting Batch file called MakeFiles.bat that will recover the original files; you may rename such a file if you wish. If an encoded file is a .CAB compressed one, it is automatically expanded after it was decoded. The conversion program is written in pure Batch code; this point assures that it will run on any computer no matter permissions or restrictions on downloaded .exe or WSH programs, although the program may be somewhat slow when processing large files.

EDIT 2016/10/03: I modified the original method to create a file with binary zeros via "fsutil file createnew" command by another method based on :genchr subroutine because fsutil requires admin permissions in certain Windows versions.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "lineLen=120"

rem BinToBat223.bat: Embed binary files into a self-extracting "Set223" encoded Batch file
rem Antonio Perez Ayala

if "%~1" neq "" if "%~1" neq "/?" goto begin
echo Usage: %0 filename.ext ... wild-card ...
goto :EOF

:begin
set "literal= ^!'#$%%&'()*+,-./0123456789:;<=>?"
set "literal=!literal!@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^_`abcdefghijklmnopqrstuvwxyz{|}~"
set "literal=!literal!€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿"
set "literal=!literal!ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ"

rem Replacement characters used to encode the notLiteral chars:
set "notLit=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]$/ .'#"
rem Ascii160 is not used, Quote is used as delimiter between parts, Ascii255 is used as mark at beginning of partC
set delim="
set "partCmark=ÿ"

echo Note that the encoding of each file will start *after* the corresponding FC
echo command had ended; this may take awhile depending on file size...
echo/

for /F "delims=:" %%a in ('findstr /N "@echo" "%~F0"') do set /A "skip=%%a+1"
more +%skip% "%~F0" > temp1.tmp
for /F %%a in ('find /C /V "" ^< temp1.tmp') do set /A "skip=%%a+3"
set "last=0"
set "lines="
del zero.tmp 2> NUL
< NUL (
   for %%f in (%*) do (
      if not exist "%%~f" (
         echo File not found: "%%~f" > CON
      ) else (
         set /P "=Encoding %%~f" > CON
         echo ^<resource id="%%~NXf"^>
         call :EncodeSet223 "%%~f"
         for /F "delims=:" %%a in ('findstr /N "^" temp2.tmp') do set /A "lins=%%a-last-1"
         set "lines=!lines! !lins!"
         set /A "last+=lins+1"
         echo  done > CON
      )
   )
   echo ^</resource^>
) > temp2.tmp
(
   echo @echo off ^& setlocal EnableDelayedExpansion
   echo set "lineLen=%lineLen%" ^& set "skip=%skip%" ^& set "lines=%lines:~1%"
   type temp1.tmp
   type temp2.tmp
) > MakeFiles.bat
del temp1.tmp temp2.tmp
echo/
echo File MakeFiles.bat created
goto :EOF


:EncodeSet223 file

set "line="
set "codes="
set /A "addr=0, blkSize=0"

REM The next line requires admin permissions in some Windows versions:
REM fsutil file createnew zero.tmp "%~Z1" > NUL
REM Alternate method using :genchr subroutine
type nul > t.tmp & call :genchr 0
set "size=%~Z1"
(for /L %%i in (1,1,31) do (
   set /A "bit=size&1, size>>=1"
   if !bit! neq 0 type 0.chr
   if !size! neq 0 type 0.chr >> 0.chr
)) > zero.tmp
del t.tmp temp.tmp 0.chr

fc /B "%~1" zero.tmp > fc.tmp
for /F "skip=1 tokens=1,2 delims=: " %%a in (fc.tmp) do (
   if !addr! neq 0x%%a (
      rem Complete previous notLiteral block, if any
      if !blkSize! gtr 1 set "codes=!codes:~0,-1!!blkSize!!codes:~-1!"
      rem Insert a block of zeros
      set /A "blkSize=0x%%a-addr, addr=0x%%a"
      if !blkSize! gtr 1 set "codes=!codes!!blkSize!"
      set "codes=!codes!%notLit:~0,1%"
      set "blkSize=0"
      if "!codes:~%lineLen%!" neq "" (
         rem Not-literal codes exceed the given line length: output they
         if defined line (
            rem There are previous literal chars: output they in a shorter line
            echo(!line!
            set "line="
            set /P "=." > CON
         )
         rem Output a "starting" type C part: Cmark + partC; in the whole line
         echo(%partCmark%!codes!
         set "codes="
      )
   )
   set /A addr+=1, lit=0x%%b-32, nLit=0x%%b
   rem If Char is greater or equal 32=space, mark it as "isLit" excepting 3 special cases:
   rem Ascii160 is notLit[33]=".", quote is notLit[34]="'" and Ascii255 is notLit[35]="#"
   set "isLit="
   if !lit! geq 0 (
      set "isLit=1"
      if !nLit! equ 160 set "isLit=" & set "nLit=33"
      if !nLit! equ 34  set "isLit="
      if !nLit! equ 255 set "isLit=" & set "nLit=35"
   )
   if defined isLit (
      rem Char isLiteral: insert it in the line
      if defined codes (
         rem There are previous notLiteral codes: output them before the Char
         rem Complete previous notLiteral block, if any
         if !blkSize! gtr 1 set "codes=!codes:~0,-1!!blkSize!!codes:~-1!"
         set "blkSize=0"
         if defined line (
            rem There are previous literal chars: insert a type B or C part after them
            if "!codes:~1!" neq "" (
               rem NotLiteral codes are more than one:
               rem insert a type C part: delim + Cmark + partC
               set "line=!line!!delim!%partCmark%!codes!"
               if "!line:~%lineLen%!" neq "" (
                  rem Line exceed the given line length: output it
                  echo(!line!
                  set "line="
                  set /P "=." > CON
               ) else (
                  rem Insert the partC delimiter
                  set "line=!line!!delim!"
               )
            ) else (
               rem NotLiteral codes is just one replacement char:
               rem insert it in a type B part: delim + replaceChar
               set "line=!line!!delim!!codes!"
            )
         ) else (
            rem No previous literal chars = beginning of line:
            rem Insert a "starting" type C part: Cmark + partC
            set "line=%partCmark%!codes!"
            if "!line:~%lineLen%!" neq "" (
               rem Line exceed the given line length: output it
               echo(!line!
               set "line="
               set /P "=." > CON
            ) else (
               rem Add the partC delimiter
               set "line=!line!!delim!"
            )
         )
         set "codes="
      )
      rem Insert the literal character now, after notLiteral codes was processed
      for %%i in (!lit!) do set "line=!line!!literal:~%%i,1!"
   ) else (
      rem Char is notLiteral: insert it in "codes"
      for %%i in (!nLit!) do if "!codes:~-1!" equ "!notLit:~%%i,1!" (
         rem The new notLit Char is equal to last one: just count it
         set /A blkSize+=1
      ) else (
         rem Complete previous block, if any
         if !blkSize! gtr 1 set "codes=!codes:~0,-1!!blkSize!!codes:~-1!"
         if defined codes if "!codes:~%lineLen%!" neq "" (
            rem Not-literal codes exceed the given line length: output they
            if defined line (
               rem There are previous literal chars: output they in a shorter line
               echo(!line!
               set "line="
               set /P "=." > CON
            )
            rem Output a "starting" type C part: Cmark + partC; in the whole line
            echo(%partCmark%!codes!
            set "codes="
         )
         rem Insert the new notLit Char
         set "codes=!codes!!notLit:~%%i,1!"
         set "blkSize=1"
      )
   )
   rem If line exceed the given line length: output it
   if defined line if "!line:~%lineLen%!" neq "" (
      if "!line:~-1!" equ "!delim!" set "line=!line:~0,-1!"
      echo(!line!
      set "line="
      set /P "=." > CON
   )
)

if %blkSize% gtr 1 set "codes=!codes:~0,-1!%blkSize%!codes:~-1!"
for %%a in (%~1) do set /A blkSize=%%~Za-addr
if %blkSize% gtr 0 set "codes=!codes!%blkSize%%notLit:~0,1%"
if defined codes set "line=!line!!delim!%partCmark%%codes%"
if defined line (
   if "!line:~-1!" equ "!delim!" set "line=!line:~0,-1!"
   echo(!line!
)
del zero.tmp fc.tmp
exit /B


==================================================================================

Description of the Set223 encoding format. Method designed by Antonio Perez Ayala.

- The 256 binary byte values are encoded in two sets: "literal" and "not-literal" characters.
- The "literal" characters are: Ascii 32-254 excepting quote and Ascii-160; these chars are just copied to the encoded file;
  the rest are "not-literal" characters: 32 control characters (0-31), quote (34), Ascii-160 and Ascii-255.
- The "not-literal" characters are encoded via the following 35 replacement characters:
  "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]$/'.#", in the same order given above.
- The encoded text file is comprised of lines of a given maximum length, but it may be longer lines.

Set223 syntax. Encoded lines are split by quotes (delimiter character) in one of 3 possible parts:

- Part A: Literal chars. This part appear at beginning of the line or after a part C.
- Part B: One not-literal char. Its first character is not Ascii-255, but a not-literal char and the rest are literals.
- Part C: Several not-literal chars. Its first character is Ascii-255 ("C mark") that is ignored, the rest are not-literals.
          If Ascii digits appear in part C, they specify a group of the not-literal char placed after the number.

literals   "   <not Ascii255>literals   "   <Ascii255>NOTLITERALS   "   ...   "   <Ascii255>NOTLIT####XNOTLITERALS
PartA   delim  |          /  PartB    delim  |      /  PartC      delim     delim  |      /       |   \
               NOTLIT-char is decoded        "Cmark" is omitted,                   "Cmark"        Number of X chars
                                             notLiterals are decoded

Set223 grammar. Allowed sequence of parts in encoded lines:

- The line may start with Part A or Part C.
- After Part A, a Part B or Part C may follow.
- After Part B, another Part B or Part C may follow.
- After Part C, just a Part A may follow.


==================================================================================


@echo off & setlocal EnableDelayedExpansion
set "lineLen=0"

rem This self-extracting Batch file was created with BinToBat223.bat encoding program written by Antonio Perez Ayala
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=4842&p=46795#p46795

echo Preparing extraction... & set "digits=0123456789" & set "notLit=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]$/ .'#" & set "Cmark=ÿ"
type nul > t.tmp & for /L %%i in (0,1,34) do set "chr[!notLit:~%%i,1!]=%%i" & call :genchr %%i
call :genchr 61 & set "chr[%notLit:~33,1%]=160" & call :genchr 160 & set "chr[%notLit:~35,1%]=255" & call :genchr 255
del t.tmp temp.tmp   &   call :DecodeAllSet223 < "%~F0" & del *.chr & goto :EOF

:DecodeAllSet223
(for /L %%l in (1,1,%skip%) do set /P "=") & (for %%l in (%lines%) do ( set /P "n="
 for /F "tokens=2 delims==>" %%n in ("!n!") do ( set /P "=Extracting %%~n"<NUL & >%%n call :DecodeSet223 %%l & set "n=%%~n"
  if /I "!n:~-4!" equ ".cab" echo done & set /P "=Expanding cabinet file..."<NUL & expand %%n "!n:~0,-4!" >NUL & del %%n
  echo done ) ))  &  exit /B

REM To expand *several* files in a cabinet file, replace "expand %%n "!name:~0,-4!" " by "expand %%n -F:* ."

:DecodeSet223 lines
for /L %%a in (1,1,%1) do (set /P "=." <NUL >CON & set /P "line=" & set "nextPart=AorC"
 for /F delims^=^ eol^= %%b in (^"!line:^"^=^
% Do NOT remove this line %
!^") do (setlocal DisableDelayedExpansion & set "part=%%b" & setlocal EnableDelayedExpansion
  if !nextPart! equ A (call :litPart & set "nextPart=BorC") else if !nextPart! equ AorC (
   if "!part:~0,1!" neq "%Cmark%" (call :litPart & set "nextPart=BorC") else (call :notLitPart & set "nextPart=A")
  ) else if !nextPart! equ BorC (if "!part:~0,1!" neq "%Cmark%" ((for /F %%c in ("!part:~0,1!") do type !chr[%%c]!.chr)
    set "part=!part:~1!" & call :litPart & set "nextPart=BorC") else (call :notLitPart & set "nextPart=A") )
 for %%c in (!nextPart!) do endlocal & endlocal & set "nextPart=%%c") )
exit /B

:litPart
if "!part:~0,1!" equ " " type 32.chr & set "part=!part:~1!" & goto litPart
if "!part:~0,1!" equ "=" type 61.chr & set "part=!part:~1!" & goto litPart
if defined part set /P "=!part!" <NUL
exit /B

:notLitPart
set "i=1" & for /L %%I in (1,1,%lineLen%) do for %%i in (!i!) do if "!part:~%%i,1!" neq "" ( set "chr=!part:~%%i,1!"
 set /A i+=1 & for /F %%c in ("!chr!") do if "!digits:%%c=!" equ "%digits%" (type !chr[%%c]!.chr) else ( set "blk=!chr!"
 for /L %%J in (1,1,5) do for %%i in (!i!) do for /F %%c in ("!part:~%%i,1!") do (
  if "!digits:%%c=!" neq "%digits%" set "blk=!blk!%%c" & set /A i+=1)
 (for %%i in (!i!) do set "chr=!part:~%%i,1!") & set /A i+=1
 for /F %%c in ("!chr!") do for /L %%J in (1,1,!blk!) do type !chr[%%c]!.chr) )
exit /B

:genchr
REM This code creates one single byte. Parameter: int
REM Teamwork of carlos, penpen, aGerman, dbenham
REM Tested under Win2000, XP, Win7, Win8
if %~1 neq 26 (
   makecab /d compress=off /d reserveperdatablocksize=26 /d reserveperfoldersize=%~1 t.tmp %~1.chr > nul
   type %~1.chr | ( (for /l %%N in (1,1,38) do pause)>nul & findstr "^" > temp.tmp )
   >nul copy /y temp.tmp /a %~1.chr /b
) else (
   copy /y nul + nul /a 26.chr /a >nul
)
exit /B


IMPORTANT: The last two lines of this program must be "exit /B" and a blank line precisely.

In order to test this method I created a binary file comprised of bytes from 0 to 255, bytes from 255 down to 0, and a mix of both (1024 bytes total) that is generated by this MakeBinaryFile.vbs program:

Code: Select all

For i=0 To 255 : WScript.StdOut.Write Chr(i) : Next
For i=255 To 0 Step -1 : WScript.StdOut.Write Chr(i) : Next
For i=0 To 255 : WScript.StdOut.Write Chr(i)+Chr(255-i) : Next

I created the binary file and encoded it this way:

output wrote:C:\> cscript //nologo MakeBinaryFile.vbs > BinaryFile.bin

C:\> BinToBat223.bat BinaryFile.bin
Note that the encoding of each file will start *after* the corresponding FC
command had ended; this may take awhile depending on file size...

Encoding BinaryFile.bin......... done

File MakeFiles.bat created

Then, I posted the created MakeFiles.bat file here:

Code: Select all

@echo off & setlocal EnableDelayedExpansion
set "lineLen=120" & set "skip=61" & set "lines=10"

rem This self-extracting Batch file was created with BinToBat223.bat encoding program written by Antonio Perez Ayala
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=4842&p=46795#p46795

echo Preparing extraction... & set "digits=0123456789" & set "notLit=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]$/ .'#" & set "Cmark=ÿ"
rem File and variable for :genchr
type nul > t.tmp & set "options=/d compress=off /d reserveperdatablocksize=26"
for /L %%i in (0,1,34) do set "chr[!notLit:~%%i,1!]=%%i" & call :genchr %%i
call :genchr 61 & set "chr[%notLit:~33,1%]=160" & call :genchr 160 & set "chr[%notLit:~35,1%]=255" & call :genchr 255
set "options=" & del t.tmp temp.tmp   &   call :DecodeAllSet223 < "%~F0" & del *.chr & goto :EOF

:DecodeAllSet223
(for /L %%l in (1,1,%skip%) do set /P "=") & (for %%l in (%lines%) do ( set /P "n="
 for /F "tokens=2 delims==>" %%n in ("!n!") do ( set /P "=Extracting %%~n"<NUL & >%%n call :DecodeSet223 %%l & set "n=%%~n"
  if /I "!n:~-4!" equ ".cab" echo done & set /P "=Expanding cabinet file..."<NUL & expand %%n "!n:~0,-4!" >NUL & del %%n
  echo done ) ))  &  exit /B

REM To expand *several* files in a cabinet file, replace "expand %%n "!name:~0,-4!" " by "expand %%n -F:* ."

:DecodeSet223 lines
for /L %%a in (1,1,%1) do (set /P "=." <NUL >CON & set /P "line=" & set "nextPart=AorC"
 for /F delims^=^ eol^= %%b in (^"!line:^"^=^
% Do NOT remove this line %
!^") do (setlocal DisableDelayedExpansion & set "part=%%b" & setlocal EnableDelayedExpansion
  if !nextPart! equ A (call :litPart & set "nextPart=BorC") else if !nextPart! equ AorC (
   if "!part:~0,1!" neq "%Cmark%" (call :litPart & set "nextPart=BorC") else (call :notLitPart & set "nextPart=A")
  ) else if !nextPart! equ BorC (if "!part:~0,1!" neq "%Cmark%" ((for /F %%c in ("!part:~0,1!") do type !chr[%%c]!.chr)
    set "part=!part:~1!" & call :litPart & set "nextPart=BorC") else (call :notLitPart & set "nextPart=A") )
 for %%c in (!nextPart!) do endlocal & endlocal & set "nextPart=%%c") )
exit /B

:litPart
if "!part:~0,1!" equ " " type 32.chr & set "part=!part:~1!" & goto litPart
if "!part:~0,1!" equ "=" type 61.chr & set "part=!part:~1!" & goto litPart
if defined part set /P "=!part!" <NUL
exit /B

:notLitPart
set "i=1" & for /L %%I in (1,1,%lineLen%) do for %%i in (!i!) do if "!part:~%%i,1!" neq "" ( set "chr=!part:~%%i,1!"
 set /A i+=1 & for /F %%c in ("!chr!") do if "!digits:%%c=!" equ "%digits%" (type !chr[%%c]!.chr) else ( set "blk=!chr!"
 for /L %%J in (1,1,5) do for %%i in (!i!) do for /F %%c in ("!part:~%%i,1!") do (
  if "!digits:%%c=!" neq "%digits%" set "blk=!blk!%%c" & set /A i+=1)
 (for %%i in (!i!) do set "chr=!part:~%%i,1!") & set /A i+=1
 for /F %%c in ("!chr!") do for /L %%J in (1,1,!blk!) do type !chr[%%c]!.chr) )
exit /B

:genchr
REM This code creates one single byte. Parameter: int
REM Teamwork of carlos, penpen, aGerman, dbenham
REM Tested under Win2000, XP, Win7, Win8
if %~1 neq 26 (
   makecab %options% /d reserveperfoldersize=%~1 t.tmp %~1.chr > nul
   type %~1.chr | ( (for /l %%N in (1,1,38) do pause)>nul & findstr "^" > temp.tmp )
   >nul copy /y temp.tmp /a %~1.chr /b
) else (
   copy /y nul + nul /a 26.chr /a >nul
)
exit /B

<resource id="BinaryFile.bin">
ÿ@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]$/" !"'#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu
vwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ".¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìí
îïðñòóôõö÷øùúûüýþ"ÿ2#"þýüûúùø÷öõôóòñðïîíìëêéèçæåäãâáàßÞÝÜÛÚÙØ×ÖÕÔÓÒÑÐÏÎÍÌËÊÉÈÇÆÅÄÃÂÁÀ¿¾½¼»º¹¸·¶µ´³²±°¯®­¬«ª©¨§¦¥¤£¢¡".Ÿž
œ›š™˜—–•”“’‘ŽŒ‹Š‰ˆ‡†…„ƒ‚€~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$
#"'! "ÿ/$]\[ZYXWVUTSRQPONMLKJIHGFEDCBA2@#A"þ"Bý"Cü"Dû"Eú"Fù"Gø"H÷"Iö"Jõ"Kô"Ló"Mò"Nñ"Oð"Pï"Qî"Rí"Sì"Të"Uê"Vé"Wè"Xç"Yæ"Zå"[ä
ÿ\"ã"]â"$á"/à ß!Þ"'Ý#Ü$Û%Ú&Ù'Ø(×)Ö*Õ+Ô,Ó-Ò.Ñ/Ð0Ï1Î2Í3Ì4Ë5Ê6É7È8Ç9Æ:Å;Ä<Ã=Â>Á?À@¿A¾B½C¼D»EºF¹G¸H·I¶JµK´L³M²N±O°P¯Q®R­S¬T«U
ªV©W¨X§Y¦Z¥[¤\£]¢^¡_".`Ÿažbcœd›ešf™g˜h—i–j•k”l“m’n‘opqŽrsŒt‹uŠv‰wˆx‡y†z…{„|ƒ}‚~€€~‚}ƒ|„{…z†y‡xˆw‰vŠu‹tŒsrŽqpo‘
n’m“l”k•j–i—h˜g™fše›dœcbžaŸ`"._¡^¢]£\¤[¥Z¦Y§X¨W©VªU«T¬S­R®Q¯P°O±N²M³L´KµJ¶I·H¸G¹FºE»D¼C½B¾A¿@À?Á>Â=Ã<Ä;Å:Æ9Ç8È7É6Ê5Ë4Ì3Í
2Î1Ï0Ð/Ñ.Ò-Ó,Ô+Õ*Ö)×(Ø'Ù&Ú%Û$Ü#Ý"'Þ!ß à"/á"$â"]ã"\ä"[å"Zæ"Yç"Xè"Wé"Vê"Uë"Tì"Sí"Rî"Qï"Pð"Oñ"Nò"Mó"Lô"Kõ"Jö"I÷"Hø"Gù"Fú"Eû"Dü
ÿC"ý"Bþ"ÿA#1@
</resource>

Finally, I copy-pasted this code in a test.bat Batch file using the standard Windows Notepad editor, renamed the original binary file to BinaryOrig.bin, run the downloaded Batch file and compare the created binary file vs. the original:

output wrote:C:\> ren BinaryFile.bin BinaryOrig.bin

C:\> test.bat
Preparing extraction...
Extracting BinaryFile.bin..........done

C:\> fc /B BinaryOrig.bin BinaryFile.bin
Comparando archivos BinaryOrig.bin y BINARYFILE.BIN
FC: no se han encontrado diferencias

You may perform the same procedure to test this method in your own computer. If the test fail, please post details including the web browser used, but before that be sure that the text editor you use does NOT change the saved bytes (for example, to match the current code page) and that the file is NOT saved in a format other than plain Ascii text (I don't use Notepad++, but I know that previous points are some of its "features"). If the test works OK, please report the web browser used if it is different than IE 10 or Chrome 49.

Antonio
Last edited by Aacini on 04 Jun 2016 20:45, edited 1 time in total.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: BinToBat.bat - Easily install files of any type or size!

#19 Post by einstein1969 » 02 Jun 2016 05:06

Very cool!

I have not probed but I think that this:

Code: Select all

echo Note that the encoding of each file will start *after* the corresponding FC
echo command had ended; this may take awhile depending on file size...
echo/


can be very faster on big file if you use a file before for /f

Code: Select all

rem for /F "skip=1 tokens=1,2 delims=: " %%a in ('fc /B "%~1" zero.tmp') do (
fc /B "%~1" zero.tmp >fc.tmp
for /F "skip=1 tokens=1,2 delims=: " %%a in (fc.tmp) do (


Francesco

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#20 Post by Aacini » 04 Jun 2016 20:48

einstein1969 wrote:Very cool!

I have not probed but I think that this:

Code: Select all

echo Note that the encoding of each file will start *after* the corresponding FC
echo command had ended; this may take awhile depending on file size...
echo/


can be very faster on big file if you use a file before for /f

Code: Select all

rem for /F "skip=1 tokens=1,2 delims=: " %%a in ('fc /B "%~1" zero.tmp') do (
fc /B "%~1" zero.tmp >fc.tmp
for /F "skip=1 tokens=1,2 delims=: " %%a in (fc.tmp) do (


Francesco


This is a good idea! :D I modified the code accordingly... Thanks!

Antonio

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: BinToBat.bat - Easily install files of any type or size!

#21 Post by Squashman » 03 Oct 2016 10:04

You are using FSUTIL to create the temporary file. Windows 7 requires administrative privileges to run FSUTIL.

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: BinToBat.bat - Easily install files of any type or size!

#22 Post by einstein1969 » 03 Oct 2016 10:46

I think that is possible create a file using this alternte method.

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#23 Post by Aacini » 03 Oct 2016 13:30

Squashman wrote:You are using FSUTIL to create the temporary file. Windows 7 requires administrative privileges to run FSUTIL.


einstein1969 wrote:I think that is possible create a file using this alternte method.


Ok. I modified the method used to create the file with binary zeros for a different one based on :genchr subroutine. Thank you both! :D

Antonio

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: BinToBat.bat - Easily install files of any type or size!

#24 Post by aGerman » 04 Oct 2016 04:07

I tested yesterday on Win10 x86 and today on Win7 x64. Worked like a charme on both machines :)

Steffen

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: BinToBat.bat - Easily install files of any type or size!

#25 Post by Aacini » 04 Oct 2016 22:33

@aGerman (and @Squashman): Could you use BinToBat223.bat to encode some of your .exe files and report the original and encoded sizes, please? The Set223 encoded text appear at end of MakeFiles.bat file, between "<resource ..." and "</resource>" lines.

Perhaps you may also do the same test with a .cab compressed file. Thanks!

Antonio

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: BinToBat.bat - Easily install files of any type or size!

#26 Post by aGerman » 05 Oct 2016 16:06

cmd.exe 10.0.14393.0 (Win10, 32bit)
202752 bytes

MakeFiles.bat
250864 bytes

Set223 section only
247568 bytes

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cmd.cab (contains the above mentioned cmd.exe)
105722 bytes

MakeFiles.bat
126253 bytes

Set223 section only
122958 bytes

Steffen

AppleSeed
Posts: 1
Joined: 30 Aug 2023 12:50

Re: BinToBat.bat - Easily install files of any type or size!

#27 Post by AppleSeed » 31 Aug 2023 14:56

I joined this forum for the express purpose of thanking you. The code posted on page 1 of this thread does exactly what I had been looking for.

I have not had success with your newest "Set223" method. It returns this error:
=====================================================================
C:\CONVERT>bin2bat utorrent.exe
Note that the encoding of each file will start *after* the corresponding FC
command had ended; this may take awhile depending on file size...

Encoding utorrent.exeThe system cannot find the batch label specified - genchr
Invalid number. Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
done
=====================================================================
To my knowledge, I've copied your code correctly, terminating it with exit /B followed by a carriage return.

Again, thank you.

Post Reply