Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
561 views
in Technique[技术] by (71.8m points)

vbscript - Currupted file in non-english locale (encoding problem?)

In my MSI Windows Installer I have a custom VBScript action which extracts some files from the 'Binary' table to the filesystem. This is the code I'm using:

Inspired by: https://www.itninja.com/question/how-to-call-an-exe-which-is-stored-in-a-binary-table-through-a-vbscript-custom-action-in-the-msi

Function ExtractFromBinary(ByVal binaryName, ByVal binaryOutputFile)

 Dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")

 Const msiReadStreamInteger = 0
 Const msiReadStreamBytes = 1
 Const msiReadStreamAnsi = 2 
 Const msiReadStreamDirect = 3

 Dim binaryView : Set binaryView = Session.Database.OpenView("SELECT Data FROM Binary WHERE Name = '" & binaryName & "'") 
 binaryView.Execute

 Dim binaryRecord : Set binaryRecord = binaryView.Fetch 
 Dim binaryData : binaryData = binaryRecord.ReadStream(1, binaryRecord.DataSize(1), msiReadStreamAnsi) 
 Set binaryRecord = Nothing

 Dim binaryStream : Set binaryStream = oFSO.CreateTextFile(binaryOutputFile, True, False) 
 binaryStream.Write binaryData
 binaryStream.Close
 Set binaryStream = Nothing 

End Function

This has been used without any issues in production for 2-3 years now. However now we have a case on a Japanese Windows installation where the extracted binary files are corrupted:

enter image description here

As you can see, the problem typically after a '?' where the script either inserts an 'E', or overwrites the following character.

Both the ReadStream method and the CreateTextFile method have a parameter which affect encoding. The combination shown above seems to be the only one which works on my English Windows 10.

What do I need to change in the code above to make it work also on a Japanese system?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@Robert-Hegner I'll propose this as an answer, even though it is subject to your testing (I have no way of testing where I am)!

I've included an updated approach here (you will need to scroll down to the second example)

It uses msiReadStreamDirect (not msiReadStreamAnsi) to extract a string of Byte pairs, converts these into binary and creates the output file using the ADODB.Stream (not the FSO).

Dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")

Dim tempFolder : tempFolder = oFSO.GetSpecialFolder(2) 
Dim outputFile : outputFile = tempFolder & "
otepad.exe"

extractFromBinary "notepad", outputFile

Function MultiByteToBinary(MultiByte)
  'obtained from http://www.motobit.com
  'MultiByteToBinary converts multibyte string To real binary data (VT_UI1 | VT_ARRAY)
  'Using recordset
  Dim RS, LMultiByte, Binary
  Const adLongVarBinary = 205
  Set RS = CreateObject("ADODB.Recordset")
  LMultiByte = LenB(MultiByte)
  If LMultiByte>0 Then
    RS.Fields.Append "mBinary", adLongVarBinary, LMultiByte
    RS.Open
    RS.AddNew
      RS("mBinary").AppendChunk MultiByte & ChrB(0)
    RS.Update
    Binary = RS("mBinary").GetChunk(LMultiByte)
  End If
  Set RS = Nothing
  MultiByteToBinary = Binary
End Function

Function SaveBinaryData(FileName, ByteArray)
  Const adTypeBinary = 1
  Const adSaveCreateOverWrite = 2

  'Create Stream object
  Dim BinaryStream
  Set BinaryStream = CreateObject("ADODB.Stream")

  'Specify stream type - we want To save binary data.
  BinaryStream.Type = adTypeBinary

  'Open the stream And write binary data To the object
  BinaryStream.Open
  BinaryStream.Write ByteArray

  'Save binary data To disk
  BinaryStream.SaveToFile FileName, adSaveCreateOverWrite

  Set BinaryStream = Nothing
End Function

Function extractFromBinary(ByVal binaryName, ByVal binaryOutputFile)

    Const msiReadStreamInteger = 0 
    Const msiReadStreamBytes = 1 
    Const msiReadStreamAnsi = 2  
    Const msiReadStreamDirect = 3

    Dim binaryView : Set binaryView = Session.Database.OpenView("SELECT * FROM Binary WHERE Name = '" & binaryName & "'")  
    binaryView.Execute

    Dim binaryRecord : Set binaryRecord = binaryView.Fetch  
    Dim binaryData : binaryData = binaryRecord.ReadStream(2, binaryRecord.DataSize(2), msiReadStreamDirect)  
    Set binaryRecord = Nothing  

    'convert to string of byte pairs to binary
    binaryData = MultiByteToBinary(binaryData)

    'save binary data
    SaveBinaryData binaryOutputFile, binaryData

End Function

Set oFSO = Nothing

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...