HTAのこれまでと現状については面倒なので略すが、現状HTAはまだ動くには動くが、デフォルトのままではIE7相当の機能でしか動かず、X-UA-Compatibleの指定でIE10以上に設定すると、HTA固有のHTA:APPLICATIONタグの機能が大きくスペックダウンし、起動パラメータが参照できなくなったり、外観や挙動の制御が制限されたりとかになってしまう。
それを回避するために、起動用のHTAを使って、旧バージョンでのフルスペックの機能設定を行った上で、本命のHTAにリダイレクトする、という方法が編み出された。
IE10モード以上のHTAでHTA:APPLICATIONオプションを使う方法 | while(isプログラマ)
https://am-yu.net/2015/04/26/ie10-ie11-htaapplication/
これは大変すばらしい技だが、構成が2つHTAに分かれてしまう、という欠点がある。そこで1つのHTAでこれを実現できないものか?とあれこれ考えて、とりあえず動くものが出来たのでメモ代わりにここに残す。
基本的な考え方は以下の通り。
・バッチファイルにWSH/JScriptとHTAを埋め込む。
・JScriptで起動用のHTAをテンポラリに生成し、元のHTAのHTA:APPLICATIONタグをコピーする。
・起動用HTAから元のHTAをリダイレクト表示してテンポラリファイルを削除する。
そのためのポイントは以下の通り。
・基本的な考えは前述の「IE10モード以上のHTAでHTA:APPLICATIONオプションを使う方法」。
・Chakraエンジンでは<!--がコメント扱いになることを利用して、バッチファイルとして記述したHTAに、自身をChakraエンジン用JScriptとして起動するバッチコマンドをHTAのコメントとして記述する。(上部)
・さらに同様にHTAのコメントとして起動用HTAの生成と実行を行うChakraエンジン用JScriptを記述する。(下部。HTA部分を/* */ でコメントアウトする都合上、下部に */ の追加が必要なので、ついでにコード部分を下に置いた。)
今回はそこまでやってないが、WSH/JScriptからHTAを起動するので、コマンドラインパラメータをオブジェクトにしてJSON化&encodeURIComponentしてgetパラメータで渡せば、コマンドライン・パラメータをHTAに引き渡せる。HTA:APPLICATIONのcommandLineプロパティを解析して取得するよりは全然楽なはず。
で、これがコード。バッチとして起動するのと、MSHTAコマンドから起動するのとでの微妙な違いをご覧いただきたい。
<!-- : ^
/*
@cscript //nologo //E:{1b7cd997-e5ff-4932-a7a6-2a9e636da385} "%~f0" %*
@exit /B
:↑でバッチ自体は終了するので、ここからはバッチからは無視される。
:↓ここに HTA コードを記述する (/*~*/のコメントは使えないので注意 */
/* /////////////////////////////////////////////////////////////////// -->
<!DOCTYPE html>
<html lang="ja">
<!--
サンプルダミーHTA --- ボタンを押しても何も起きません。
-->
<head>
<meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
<meta http-equiv="content-script-type" content="text/javascript">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="X-UA-Compatible" content="IE=EDGE" />
<title>input box</title>
<hta:application id="oHTA"
applicationname="input box"
border="thick"
caption="yes"
maximizebutton = "no"
minimizebutton = "no"
selection = "no"
showintaskbar="yes"
singleinstance="yes"
sysmenu="yes"
windowstate="nomal">
<style type="text/css">
* { margin: 0; padding: 0; }
</style>
<link rel="stylesheet" type="text/css"
href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" />
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js"></script>
</head>
<body onresize="window.resizeTo(432,188);" onLoad="window.resizeTo(432,188);" style="background-color: whitesmoke;" >
<div style="position: absolute; left: 3mm; top: 3mm; font-size: 10pt;">
入力してください。
</div>
<input id="text1" type="text" name="text1" size="68" style="position: absolute; left: 3mm; bottom: 3mm; font-size: 10pt; height: 1.5em; ">
<button id="btnOK" type="button" name="btnOK" style="position: absolute; right: 3mm; top: 3mm; font-size: 10pt; height: 2em; width: 7em">OK</button>
<button id="btnCAN" type="button" name="btnCAN" style="position: absolute; right: 3mm; top: 13mm; font-size: 10pt; height: 2em; width: 7em">キャンセル</button>
<script type="text/javascript">
//
</script>
</body>
</html>
<!-- */ /////////////////////////////////////////////////////////////////
// ↑ HTA コードここまで。以下は起動用コード
genHTAkicker( WScript.ScriptFullName )();
// HTA 再起動
function genHTAkicker( file ) {
var fso = typeof(fso)==='undefined' ? WScript.CreateObject('Scripting.FileSystemObject') : fso;
var mch, str, xuae, ie=7, app, hta;
file = fso.GetAbsolutePathName( file );
// str = _.file2text( file );
var f = fso.OpenTextFile( file, 1 ); // iomode 1:ForReading
if( ! f.AtEndOfStream ) str = f.ReadAll();
f.close();
// 雑な正規表現(1) X-UA-Compatible 定義の抽出
if( mch = str.match(/\<.*"X\x2DUA-Compatible".*\>/) ) {
xuae = mch[0];
if( mch = xuae.match(/"IE=([^"]+)"/) ) ie = mch[1];
}
// 雑な正規表現(2) HTA:APPLICATION 定義の抽出
if( mch = str.match(/\<HTA\x3AAPPLICATION[\S\s]*?\>/im) ) app = mch[0];
if( parseInt(ie) <=9 ) return void 0;
hta = "\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta http-equiv='X-UA-Compatible' content='IE=9' />\n\
<meta http-equiv='refresh' content='0;URL=" + file + "?kicked'>\n\
" + app + "\n\
</head>\n\
<body>\n\
<script>\n\
var fso = new ActiveXObject('Scripting.FileSystemObject');\n\
window.addEventListener('unload', function(event) {\n\
fso.DeleteFile('@@@@@@@@');\n\
});\n\
<\x2Fscript>\n\
</body>\n\
</html>";
// kicker生成
return function kickHTA(){
var fso = typeof(fso)==='undefined' ? WScript.CreateObject('Scripting.FileSystemObject') : fso;
var WshShell = typeof(WshShell)==='undefined' ? WScript.CreateObject('WScript.Shell') : fso;
// var tempfile = _.genTempPathEasy();
var tempfile = ( ((new Date()).toLocaleString()).replace( /([^\d])(\d)(?=[月日:]|$)/g, "$10$2" ) ).replace( /[^\d]+/g, "" );
tempfile = fso.BuildPath( fso.GetSpecialFolder(2), tempfile );
hta = hta.replace( /@@@@@@@@/, tempfile.replace(/\\/g,"/") );
// _.text2file( hta, tempfile );
var f = fso.CreateTextFile( tempfile, true );
f.Write(hta);
f.close();
// WshShell.Run( 'MSHTA ' + tempfile + ' & del ' + tempfile, 1, true );
WshShell.Run( 'MSHTA ' + tempfile, 1 );
}
}
// この行は消さないこと。 -->
作るには作った。が、大袈裟すぎる。微妙な違いのためにこれかよ。どうしても1ファイルにしたいとき以外は2ファイル構成にする方がお手軽だし、IE10以降固有の機能まで必要ないなら、IE=9を指定してやればES5で使えるし、commandLineプロパティも含めHTA:APPLICATIONの機能がフルセットで動くので、それでいいじゃないのよ。というのが結論である。やれやれ。