WSFファイルを1ファイルに結合する:wsf2jse.wsf
自作スクリプトです。便利なので公開します。
WSFへの結合版「wsfpack.wsf」もあります。
wsf2jse.wsf
WSFファイルを1ファイルに結合する。
wsfファイルのXMLを解析して、1つのjseファイルに出力するスクリプトです。ファイルを分割すると開発するには便利ですが、実用には不向きなため、1ファイルにまとめます。
説明
cscript wsf2jse.wsf /?
wsf2jse Conversion tool.
使い方 : wsf2jse.wsf path [jobid]
オプション :
path : WSF file path
jobid : job ID
- wsfファイル名に「.jse」を追加したファイルを作成します
- 既に存在する場合、上書きします
- scriptタグのlanguage属性がJavaScriptかJScript以外の場合、動作を停止します
- 外部スクリプトが指定位置に格納されていな場合、動作を停止します
- wsfファイルをドラッグ&ドロップすることでも実行できます
- 拡張子が「.jse」なのは、「.js」の関連付けを変更しているWindows環境が多いと考えたため、「.jse」を採用しています(「.js」拡張子でも動作します)
- 「.jse」も「.js」同様のスクリプトです(「.exe」の様に実行されます)
ソースコード
wsf2jse.wsf<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
<job>
<?job error="false" debug="false" ?>
<runtime>
<description>wsf2jse Conversion tool.</description>
<unnamed name="path" many="false" required="true" helpstring="WSF file path" />
<unnamed name="jobid" many="false" required="false" helpstring="job ID" />
</runtime>
<script language="JavaScript">
//<![CDATA[
/*!
* wsf2jse.wsf v5
*
* Copyright (c) 2018 toshi - https://www.bugbugnow.net/p/profile.html
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
*/
/**
* WSFファイルを1ファイルに結合する
* wsfファイルのXMLを解析して、1つのjseファイルに出力するスクリプトです。
* @requires module:WScript
* @auther toshi(https://www.bugbugnow.net/p/profile.html)
* @version 5
* @see 1 - 20180512 - add - 初版
* @see 2 - 20180513 - update - リファクタリング
* @see 3 - 20190403 - update - Process.jsライブラリから分離
* @see 4 - 20190525 - fix - 相対パスが正常に読み込めない問題修正
* @see 5 - 20200116 - update - FileUtility.jsから分離(単独ファイル化)
*/
(function () {
"use strict";
var fs = new ActiveXObject('Scripting.FileSystemObject');
var sh = new ActiveXObject('WScript.Shell');
/**
* PrivateUnderscore.js
* @version 5
*/
{
function _FileUtility_createFolder(folderpath) {
var ret = false,
fullpath = fs.GetAbsolutePathName(folderpath);
if (!(fs.FolderExists(fullpath) || fs.FileExists(fullpath))) {
var parentpath = fs.GetParentFolderName(fullpath);
if (parentpath != '') {
_FileUtility_createFolder(fs.GetParentFolderName(fullpath));
}
try {
fs.CreateFolder(fullpath);
ret = true;
} catch (e) {
// ファイルが見つかりません(パス長問題) || パスが見つかりません(パス不正 || 存在しない)
}
}
return ret;
};
function _FileUtility_createFileFolder(filepath) {
var ret = false;
var fullpath = fs.GetAbsolutePathName(filepath);
var parentpath= fs.GetParentFolderName(fullpath);
if (parentpath != '') {
ret = _FileUtility_createFolder(parentpath);
}
return ret;
};
function _storeText(src, path, opt_option, opt_charset, opt_bom) {
var option = (opt_option === true)? 2:
(opt_option === false)? 1:
(opt_option == null)? 1: opt_option;
var charset = (opt_charset== null)? 'utf-8': opt_charset;
var bom = (opt_bom == null)? true: opt_bom;
var fullpath, skip, bin;
var ret = true;
// 前処理
charset = charset.toLowerCase();
skip = {};
skip['utf-8'] = 3;
skip['utf-16'] = 2;
skip['utf-16le'] = 2;
// UTF-16BEは、スキップ不要(ADODB.StreamがBOMを書き込まないため)
fullpath = fs.GetAbsolutePathName(path);
// (存在しない場合)フォルダを作成する
_FileUtility_createFileFolder(fullpath);
// ファイルに書き込む。
var sr = new ActiveXObject('ADODB.Stream');
sr.Type = 2;
sr.Charset = charset;
sr.Open();
sr.WriteText(src);
if (bom === true && charset == 'utf-16be') {
// ADODB.Streamは、UTF-16BEのBOMを書き込まないため、自力でBOMを書き込む
// LEのBOMを確保
var le = new ActiveXObject('ADODB.Stream');
le.Type = 2;
le.Charset = 'utf-16le';
le.Open();
le.WriteText('');
le.Position = 0;
le.Type = 1;
// BEのバイナリを確保
var be = sr;
be.Position = 0;
be.Type = 1;
bin = be.Read();
be.Close();
be = null;
sr = null;
// 再度BOMありを書き込み
sr = new ActiveXObject('ADODB.Stream');
sr.Type = 1;
sr.Open();
// BOM(LEの1Byteと2Byteが逆)を書き込み
// BEのバイナリを書き込み
le.Position = 1;
sr.Write(le.Read(1));
le.Position = 0;
sr.Write(le.Read(1));
if (bin != null) sr.Write(bin);
le.Close();
le = null;
}
if (bom === false && skip[charset]) {
// BOMなし書込処理
var pre = sr;
pre.Position = 0;
pre.Type = 1;
// skipバイト(BOM)を読み飛ばす
pre.Position = skip[charset];
bin = pre.Read();
pre.Close();
pre = null;
sr = null;
// 再度BOMなしを書き込み
sr = new ActiveXObject('ADODB.Stream');
sr.Type = 1;
sr.Open();
if (bin != null) sr.Write(bin);
}
try {
sr.SaveToFile(fullpath, option);
} catch (e) { // ADODB.Stream: ファイルへ書き込めませんでした。
// ファイルあり時、上書きなし
ret = false;
}
sr.Close();
sr = null;
return ret;
// 補足:LineSeparatorプロパティは、全行読み出しのため、無意味
};
function _loadText(path, opt_charset) {
var ret, fullpath,
charset = opt_charset,
skip = false;
if (charset == null) { charset = '_autodetect_all'; }
charset = charset.toLowerCase();
fullpath = fs.GetAbsolutePathName(path);
if (!fs.FileExists(fullpath)) {
// ファイルなし
return null;
} else if (fs.GetFile(fullpath).size === 0) {
// 空ファイル
return '';
}
var sr = new ActiveXObject('ADODB.Stream');
sr.Type = 2;
if (charset == '_autodetect_all' || charset == 'utf-16be') {
// BOMを確認してUTF-8とUTF-16だけ、手動で判定する
// UTF-16BEは、BOMあり時にBOM削除されないため、手動でスキップする
var pre = new ActiveXObject('ADODB.Stream');
pre.Type = 2;
pre.Charset = 'us-ascii';
pre.Open();
pre.LoadFromFile(fullpath);
var bom = [];
bom.push(pre.EOS || escape(pre.ReadText(1)));
bom.push(pre.EOS || escape(pre.ReadText(1)));
bom.push(pre.EOS || escape(pre.ReadText(1)));
if (charset == 'utf-16be') {
if (bom[0] == '%7E' && bom[1]== '%7F') {
skip = true;
}
} else if (bom[0] == 'o' && bom[1]== '%3B' && bom[2]== '%3F') {
charset = 'utf-8';
} else if (bom[0] == '%7F' && bom[1]== '%7E') {
charset = 'utf-16le';
} else if (bom[0] == '%7E' && bom[1]== '%7F') {
charset = 'utf-16be';
skip = true;
}
pre.Close();
pre = null;
}
sr.Charset = charset;
// ファイルから読み出し
sr.Open();
sr.LoadFromFile(fullpath);
if (skip) {
// 先頭一文字(BOM)を空読み
sr.ReadText(1);
ret = sr.ReadText();
} else {
ret = sr.ReadText();
}
// 終了処理
sr.Close();
sr = null;
return ret;
};
function _Process_createActiveXObjects(progIDs) {
for (var i=0; i<progIDs.length; ++i) {
try {
return new ActiveXObject(progIDs[i]);
} catch (e) {
if (i == progIDs.length - 1) { throw e; }
}
}
return null;
};
function _Process_createDOMDocument() {
return _Process_createActiveXObjects([
'MSXML2.DOMDocument.6.0',
'MSXML2.DOMDocument.3.0',
'Msxml2.DOMDocument',
'Msxml.DOMDocument',
'Microsoft.XMLDOM']);
};
function _Process_getArguments() {
var arg = [];
for (var i=0; i<WScript.Arguments.Unnamed.length; i++) {
arg.push(WScript.Arguments.Unnamed.Item(i));
}
return arg;
};
}
// 標準出力
var stdout = '';
function println(message) {
stdout += ((message !== void 0) ? message: '')+'\n';
}
function main() {
var args = _Process_getArguments();
var path = args[0];
var jobid= args[1];
var fullpath = fs.GetAbsolutePathName(path);
if (fs.FileExists(fullpath) == false) {
WScript.Echo('file not found.\n'+fullpath);
return -1;
} else if (fs.GetExtensionName(fullpath).toLowerCase() != 'wsf') {
WScript.Echo('wsf file not found.');
return -2;
} else {
// ルートディレクトリをパックファイルのパスに設定(相対パス対策)
sh.CurrentDirectory = fs.GetParentFolderName(fullpath);
// wsfを読込み
var text = _loadText(fullpath)
.replace(/\r\n?/g,'\n');
var xml = _Process_createDOMDocument();
xml.loadXML(text);
// wsfを解析
var job = xml.selectSingleNode((jobid == null)? '//job': '//job[@id="'+jobid+'"]');
var descript = null;
var scripts = [];
if (job != null) {
descript = job.selectSingleNode('runtime/description');
scripts = job.selectNodes('script');
}
if (scripts.length == 0) {
WScript.Echo('script not found.');
return -3;
}
// ヘッダ部書込み
var lines = [];
var filename = fs.GetFileName(fullpath);
lines.push('// ==wsf2jse:header==');
lines.push('// file: '+filename);
for (var i1=0; i1<scripts.length; i1++) {
var src = scripts[i1].getAttribute('src');
if (src != null) {
lines.push('// subfile: '+src);
}
// スクリプトの言語をチェック
var lang = scripts[i1].getAttribute('language');
if (lang == null) {}
else if (lang.toLowerCase() == 'jscript') { continue; }
else if (lang.toLowerCase() == 'javascript') { continue; }
// 非対応言語
WScript.Echo('unsupported script is included.');
return -4;
}
if (descript != null) {
var descripts = descript.text.split('\n');
for (var i2=0; i2<descripts.length; i2++) {
lines.push('// descript: '+descripts[i2]);
}
}
lines.push('// ==/wsf2jse:header==');
lines.push('');
// スクリプト書き込み
println(filename);
lines.push('// ==wsf2jse:'+filename+'==');
for (var i3=0; i3<scripts.length; i3++) {
var src = scripts[i3].getAttribute('src');
if (src == null) {
} else if (!fs.FileExists(fs.GetAbsolutePathName(src))) {
WScript.Echo('file not found.\n'+src);
return -5;
} else {
println(src);
lines.push('// ==wsf2jse:'+src+'==');
lines.push(_loadText(src));
lines.push('// ==/wsf2jse:'+src+'==');
}
if (scripts[i3].text != '') {
lines.push(scripts[i3].text);
}
}
lines.push('// ==/wsf2jse:'+filename+'==');
// ファイル出力
_storeText(lines.join('\n'), fullpath+'.jse', true, 'utf-16', true);
println();
println('complete.');
WScript.Echo(stdout);
}
return 0;
}
main();
})();
//]]>
</script>
</job>
</package>
変更履歴
更新日 | 説明 |
---|---|
2018/05/12 | v1 - add - 初版 |
2018/05/13 | v2 - update - リファクタリング |
2019/04/03 | v3 - update - Process.jsライブラリから分離 |
2019/05/25 | v4 - fix - 相対パスが正常に読み込めない問題修正 |
2020/01/16 | v5 - update - FileUtility.jsから分離(単独ファイル化) |