I recently needed to email binary attachments directly to (and from) gmail accounts.
To achieve this, I created the VBS script below (I call it "MakeTextCabDropIn.vbs"), into which you drag and drop your binary file or directory structure. It then creates a self-extracting VBS file with a ".txt" extension ("Delete my .txt extension and run me.vbs.txt").
The end user simply saves the attachment, deletes the ".txt" extension and runs the VBS file.
The extracted binary is placed in a temp directory sub-folder, which is opened by the script in File Explorer. Directory structures are replicated as sub-folders in the temp directory.
When compressing directories, the script looks for "makeddf.exe" in the same folder as itself. If it cannot find it, it will try to create it using (you've guessed it) a compressed version at the line starting "makeddf_exe_base64_ =".
To get the Base64 string for it, drop your copy of "makeddf.exe" into the script and copy it from the "Delete my .txt extension and run me.vbs.txt" created.
Obviously, if you use a zip file as your input then "makeddf.exe" is not needed.
Dim wsh, fso
Set wsh = wscript.CreateObject("wscript.Shell")
Set fso = CreateObject("Scripting.fileSystemObject")
'DRAG AND DROP YOUR BINARY FILE INTO THE ICON
'********************************************
If WScript.Arguments.Count > 0 Then
For each arg in WScript.Arguments
path_and_filename = path_and_filename & arg
Next
tokens = Split(path_and_filename, "\")
infilename = tokens(UBound(tokens))
For i=0 To UBound(tokens)-1
path = path & tokens(i) & "\"
Next
else
WScript.Quit
End If
isfolder = False
filepath = fso.GetParentFolderName(WScript.ScriptFullName) & "\"
'CHECK IF A DIRECTORY STRUCTURE HAS BEEN DROPPED IN
'**************************************************
if (fso.FolderExists(path_and_filename)) then
'IF makeddf.exe IS NOT PRESENT IN THE SAME DIRECTORY THEN CREATE IT
'******************************************************************
if not fso.FileExists(filepath & "makeddf.exe") then
'THIS FUNCTION WILL END THE WHOLE SCRIPT IF THE BASE64 IS EMPTY
'**************************************************************
create_makeddf_exe()
end if
isfolder = True
wsh.CurrentDirectory = filepath
wsh.Run ("makeddf /p """ & path_and_filename & """ /c makeddf.cab /d makeddf.ddf /a"),0,True
wsh.Run ("makecab /F makeddf.ddf"),0,True
'MAKECAB PUTS A LF ( 0Ah , CHR(10) ) AFTER 72 BYTES (SPEC SAYS 76) ...SO WE'LL TAKE THEM OUT
'*******************************************************************************************
base64_ = Replace(encodeBase64(readBytes("makeddf.cab")), vblf, "")
'TIDY UP
'*******
wsh.Run ("cmd /c del *.inf"),0,false
wsh.Run ("cmd /c del *.rpt"),0,false
wsh.Run ("cmd /c del *.ddf"),0,false
wsh.Run ("cmd /c del *.cab"),0,false
else
tempfile = fso.GetTempName
'MAKECAB NEEDS THE TRAILING "\" REMOVED FROM path
'************************************************
wsh.run ("cmd /c makecab /L """ & left(path,len(path)-1) & """ """ & WScript.Arguments(0) & """ " & tempfile ),0,True
base64_ = Replace(encodeBase64(readBytes(path & tempfile)), vblf, "")
'TIDY UP
'*******
if fso.FileExists(path & tempfile) then
Set aFile = fso.GetFile(path & tempfile)
aFile.Delete
end if
end if
'READ ANY LINES AT THE BOTTOM OF THIS FILE PREFIXED WITH '+>
'AND USE THEM TO CREATE "Delete my .txt extension and run me.vbs.txt"
'********************************************************************
Set objInputFile = fso.OpenTextFile(WScript.ScriptFullName, 1)
inputData = Split(objInputFile.ReadAll, vbNewline)
For each strData In inputData
if left(strData,3)="'+>" then
line_ = rtrim(replace(strData,"'+>","")) 'STRIP OFF THE PREFIX
line_ = replace(line_,"~",infilename) 'INSERT THE BINARY FILE NAME
line_ = replace(line_,"$",isfolder) 'INSERT THE FOLDER MODE
line_ = replace(line_,"@",base64_) 'INSERT THE BASE64 STRING
vbsfile = vbsfile & line_ & vbcrlf
end if
Next
objInputFile.Close
Set file = fso.CreateTextFile(filepath & "Delete my .txt extension and run me.vbs.txt", True)
file.Write(vbsfile)
file.Close
wscript.quit()
private function create_makeddf_exe()
' DROP A COPY OF makeddf.exe INTO THIS SCRIPT, COPY THE base64_ STRING IN THE
' "Delete my .txt extension and run me.vbs.txt" CREATED, AND THEN PASTE IT TO
' makeddf_exe_base64_ BELOW:
' ***************************************************************************
makeddf_exe_base64_ = ""
if Len(makeddf_exe_base64_)<10000 then
msgbox "Unable to find (or create) makeddf.exe in " & vbcrlf & vbcrlf & filepath & vbcrlf & vbcrlf & "This file is required when compressing directories."
wscript.quit()
end if
localpath = fso.GetParentFolderName(WScript.ScriptFullName) & "\"
tempfilename = localpath & fso.GetTempName
bytes_ = decodeBase64(makeddf_exe_base64_)
writeBytes tempfilename , bytes_
wsh.run ("cmd /c expand """ & tempfilename & """ """ & localpath & "makeddf.exe""" ),0,True
wsh.Run ("cmd /c del """ & tempfilename & """"),0,false
end function
private function readBytes(file)
dim inStream
set inStream = WScript.CreateObject("ADODB.Stream")
inStream.Open
inStream.type= 1 'TypeBinary
inStream.LoadFromFile(file)
readBytes = inStream.Read()
end function
private Sub writeBytes(file, bytes)
Dim binaryStream
Set binaryStream = CreateObject("ADODB.Stream")
binaryStream.Type = 1 'adTypeBinary
binaryStream.Open
binaryStream.Write bytes
binaryStream.SaveToFile file, 2
end Sub
private function encodeBase64(bytes)
dim DM, EL
Set DM = CreateObject("Microsoft.XMLDOM")
Set EL = DM.createElement("tmp")
EL.DataType = "bin.base64"
EL.NodeTypedValue = bytes
encodeBase64 = EL.Text
end function
private function decodeBase64(base64)
dim DM, EL
Set DM = CreateObject("Microsoft.XMLDOM")
Set EL = DM.createElement("tmp")
EL.DataType = "bin.base64"
EL.Text = base64
decodeBase64 = EL.NodeTypedValue
If err.number <> 0 then
errorhandler()
End If
end function
'THE LINES BELOW WILL FORM "Delete my .txt extension and run me.vbs.txt"
'***********************************************************************
'+>filename = "~"
'+>isfolder = $
'+>base64_ = "@"
'+>Dim wsh
'+>Set wsh = CreateObject("wscript.Shell")
'+>Set fso = CreateObject("Scripting.FileSystemObject")
'+>tempFolderPath = fso.GetSpecialFolder(2) & "\" & CreateGUID & "\"
'+>fso.CreateFolder tempFolderPath
'+>tempfilename = tempFolderPath & fso.GetTempName
'+>bytes_ = decodeBase64(base64_)
'+>writeBytes tempfilename , bytes_
'+>if(isfolder) then
'+> fso.CreateFolder tempFolderPath & filename
'+> wsh.run ("cmd /c expand -F:* """ & tempfilename & """ """ & tempFolderPath & filename & """" ),0,True
'+>else
'+> wsh.run ("cmd /c expand """ & tempfilename & """ """ & tempFolderPath & filename & """" ),0,True
'+>end if
'+>wsh.run (tempFolderPath),1,False
'+>Set aFile = fso.GetFile(tempfilename)
'+>aFile.Delete
'+>
'+>private function CreateGUID
'+> Dim TypeLib
'+> Set TypeLib = CreateObject("Scriptlet.TypeLib")
'+> CreateGUID = Mid(TypeLib.Guid, 2, 36)
'+>End function
'+>
'+>private function decodeBase64(base64)
'+> dim DM, EL
'+> Set DM = CreateObject("Microsoft.XMLDOM")
'+> Set EL = DM.createElement("tmp")
'+> EL.DataType = "bin.base64"
'+> EL.Text = base64
'+> decodeBase64 = EL.NodeTypedValue
'+> If err.number <> 0 then
'+> errorhandler()
'+> End If
'+>end function
'+>
'+>private Sub writeBytes(file, bytes)
'+> Dim binaryStream
'+> Set binaryStream = CreateObject("ADODB.Stream")
'+> binaryStream.Type = 1 'adTypeBinary
'+> binaryStream.Open
'+> binaryStream.Write bytes
'+> binaryStream.SaveToFile file, 2
'+>end Sub
Powershell can be used to achieve the same results, but recently I found that some users' anti-virus software disables the Powershell functionality. Also, ".ps1" scripts are often not run if double-clicked in Explorer directories with a space in the name, unless the user's Powershell registry settings have been changed.
The commented out sections (starting '+> ) that form the child files could be replaced with compressed versions. I left them visible so you can see (and trust) them. I didn't include a compressed version of "makeddf.exe" for the same reason.
The only "gotcha" experienced so far is that when sent from gmail, some HTML email clients display the attachment's file name as oriental characters. However, the saved file can be renamed and run as normal.
The archive contained a Kicad project.
.000
files which are used as temporary files. Do you have one of those files in the zip? If so, I wonder if Google is thinking it's a part of a multi-volume archive file (since programs like 7-zip sometimes split archive files up and use the file extension.000
). If so, that would conflict with Google's other rule: "zip file within another zip file".