如何在 WSH (JScript) 中创建二进制文件并将其保存到本地文件系统?

How can I create a binary file and save it to local file system in WSH (JScript)?

我一整天都在寻找一种方法来从本地文件系统读取二进制文件,对其进行一些修改并将其保存回磁盘。该脚本必须是 运行 批处理,因为其他脚本必须是 运行 之后。

阅读不是问题:您始终可以将其作为文本阅读,然后将字符转换为字节。问题是将它写入磁盘。 ActiveXObject("Scripting.FileSystemObject") 设施无法使用,因为某些字节未映射到字符,然后 Write 方法抛出异常。 我读过一篇 post,在其他地方建议使用 ADODB.Stream,这是我所能做的:

var foo = ...
var stream = new ActiveXObject('ADODB.Stream');
stream.Type = 1; //Means "binary".
stream.Open();
stream.Write(foo);
stream.SaveToFile('C:\foo.bin', 2); //2 means save/create/overwrite

关于我输入的变量类型 foo,Windows 脚本宿主声明:

Error:    Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
Code:     800A0BB9
Source:   ADODB.Stream

似乎 ADODB Stream.Write 方法需要 A Variant that contains an array of bytes to be written. Since such things doesn't exist in Javascript, I tried with an array filled with numbers, a string, a single number, a single char, an hex expression... I've found VBArray 但实际上您不能在其中写入任何内容。

有人知道必须使用哪种类型吗?或任何其他方式来保存二进制数据?

改编自ADODB.Stream writing binary file, JScript only。注释以在代码中进行解释。

var adTypeBinary = 1 
var adTypeText   = 2 
var adSaveCreateOverWrite = 2
var stdout = WScript.StdOut;

// Read a binary file, particularly for debugging purposes
var inStream = new ActiveXObject("ADODB.Stream");
    inStream.Type = adTypeBinary;
    inStream.Open();
    inStream.LoadFromFile("d:\bat\cliParser.exe");
    inStream.Position = 0;
var binData = inStream.Read();
    inStream.Close();

stdout.WriteLine( "binData " + typeof(binData)); // returns: "undefined"

// Convert binary value of "undefined" data type to "string" data type
var objRS = new ActiveXObject("ADODB.Recordset");
var DefinedSize = 1024; /* A Long value that represents the defined size, 
      in characters or bytes, of the new field. Fields that have a DefinedSize 
      greater than 255 bytes are treated as variable length columns. */
var adFldLong = 0x80;   /* Indicates that the field is a long binary field.  
      Also indicates that you can use the AppendChunk and GetChunk methods. */
var adVarChar = 201;   /* Indicates a long string value. */
    objRS.Fields.Append("test", adVarChar, DefinedSize, adFldLong);
    objRS.Open();
    objRS.AddNew();
    objRS.Fields("test").AppendChunk(binData);
var binString = objRS("test").value;
    objRS.close();

stdout.WriteLine( "binString " + typeof(binString));  // returns: "string"
    // String is now manipulable (unlike "undefined" data type)

// Write string to a file (converting string in one-byte encoding schema)

var outStreamW = new ActiveXObject("ADODB.Stream");
    outStreamW.Type = adTypeText;
      // Charset: the default value seems to be `UTF-16` (BOM `0xFFFE` for text files)
    outStreamW.Open();
    outStreamW.WriteText(binString);
    outStreamW.Position = 0;

var outStreamA = new ActiveXObject("ADODB.Stream");
    outStreamA.Type = adTypeText;
    outStreamA.Charset = "windows-1252"; // important, see `cdoCharset Module Constants`
    outStreamA.Open();

    outStreamW.CopyTo(outStreamA);      // convert encoding

    outStreamA.SaveToFile("D:\test\fooRus.exe", adSaveCreateOverWrite);

    outStreamW.Close();
    outStreamA.Close();

// Done. Make certain of input and output file oneness!

输出:

==> cscript D:\VB_scripts\JScripts330187my.js
binData unknown
binString string

==> echo n|COMP "d:\bat\cliParser.exe" "D:\test\fooRus.exe" 2>NUL
Comparing D:\bat\cliParser.exe and D:\test\fooRus.exe...
Files compare OK

==>