Windows11でIEが消えていたので、IE用のJavaScriptでActiveXを使ってブラウザでMDBの中身を見るツールが使えない。
そこで、C#でローカルWEB(+REST)サーバEXEを作り、ActiveXをEXEで処理してブラウザは非同期通信でリモートでコントロールさせてみたい。
IE用のindex.htmlとJSファイルはEXEのwwwrootフォルダに入れておき
C#のMainから8000ポートを開き、GETコマンドリクエストがあれば、exeファイルのトコのwwwrootフォルダのファイルを返す様にしておく。
参考文献:簡易Webサーバを実装するには?[2.0のみ、C#、VB]
using System;
using System.IO;
using System.Net;
namespace LocalWebServer
{
class WebFileServer
{
static void Main()
{
string root = @"wwwroot\"; // ドキュメント・ルートは好きな場所でOK
string prefix = "http://localhost:8000/"; // URLはしっかり書かないとエラる
// ブラウザでindex.htmlを開く。ココからjsファイルもGETされるハズ
System.Diagnostics.Process.Start(prefix + "index.html");
//
HttpListener listener = new HttpListener();
listener.Prefixes.Add(prefix); // プレフィックスの登録
listener.Start();
while (true) {
HttpListenerContext context = listener.GetContext();
HttpListenerRequest req = context.Request;
HttpListenerResponse res = context.Response;
Console.WriteLine(req.RawUrl);
// リクエストされたURLからファイルのパスを求める
string path = root + req.RawUrl.Replace("/", "\\");
// ファイルがあれば出力
if (File.Exists(path)) {
byte[] content = File.ReadAllBytes(path);
res.OutputStream.Write(content, 0, content.Length);
} else {
// TODO エラー処理 404 あるいはREST処理をしないといけないかもしれない
}
res.Close();
}
}
}
}
とRESTのWEBサービスっぽく
HTMLファイルは、
<script src="./ActiveX.js">
・・・
<script src="./${他のjsファイル}">
と付け加え、JavaScript上のActiveX(“xxxxx”)の実装を差替える。
ActiveX(objectID) => {
let promise = new Promise( (resolve, reject) => {
let domain = "localhost";
let port = 8000;
let xhr = new XMLHttpRequest();
xhr.open('GET', `http://${domain}:${port}/ActiveX/`, true);
xhr.responseType = 'json';
xhr.send(null);
xhr.onload = function(e) {
if (xhr.readyState == 4) {
if (xhr.status == 200 ) {
resolve(JSON.parse(xhr.response));
}
}
};
});
return promise;
};
ActiveXの予備元やそのメソッドの呼び出しは全てawaitを追記
async function xxxx(...)
{
let obj = await ActiveX("xxxxx");
}
プロパティ呼び出しはC#側でデータを展開しておいた方が良さそう
しかし、メソッドもプロパティもいっぱいあるので
class ADODB_xxxxxx
constractor()
{
this.className = "ADODB.xxxxxx";
dummy_properties();
dummy_methods();
}
dummy_properties()
{
let properties = ['BOF','EOF',....,'fields'];
properties.foreach( (p) => {
this[p] = new Function (`
set ${p}(v) {
alert('set ${p} no support.');
}
get ${p}() {
alert('get ${p} no support.');
}
`);
});
}
dummy_methods()
{
let methods = ['BOF','EOF',....,'fields'];
methods.foreach( (m) => {
this[m] = new Function (`
alert('set ${m} no support.');
`);
});
}
で、TODO風に作っておいて、後で実装を考えた方が良さそう。
あるいは、各ActiveX用のクラスJSファイルは、ワーカースレッドよろしく
var adodbWorkers = [];
・・・
adodbWorkers["ADODB.xxxxxx"] = new Worker('ADODB.xxxxxx.js');
とやって
adodbWorkers["ADODB.xxxxxx"].postMessage(${メソッド名},${パラメータ1},...,${パラメータn});
で
onmessage = function(e) {
switch(e)
{
case "BOF":
どうしよう
break;
・・・
}
}
で
adodbWorkers["ADODB.xxxxxx"].onmessage = function(e) {
何とかかんとか
resolve(e,data)とか
}
して、がら空きの実装で使うとこだけ実装する方式で済ませるのがいいかもしれない。