Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@riafeed

TypeScriptでWSH(Chakra)を書く(2020年版)

概要

WSHのJScriptは大変古いES3相当のJavascriptですが、Windows10ではEdgeで使われているChakraエンジンを指定することでES2015(ES6)相当のJavascriptをWSHで使うことができるようになっています。

この環境なら制限の多いES3とは違いES2015なのでTypescriptでも十分現実的にコーディングできるのではないかということでやってみました。

インストール

Typescriptでコーディングするなら型定義ファイルがないと話になりませんが、さすがにどちらもMicrosoft製なので用意されていました。

npm install @types/windows-script-host

これでWSHの型定義ファイルがインストールされますが、これにはWSH使うなら避けて通れないであろう各種COMオブジェクトの型定義が入っていないので、必要に応じてインストールします。(activex-interopとactivex-iwshruntimelibraryはwindows-script-hostインストール時に一緒にインストールされるようです)

npmパッケージ一覧から探すと便利です。

Typescript設定

WSHへのトランスパイルでは2つ注意点があり、libの設定をデフォルトにするとTypescriptのScriptHostライブラリと競合してトランスパイルに失敗するので必ずtargetと同じバージョンのライブラリだけを指定すること、moduleはnoneに設定する必要があります。
モジュールは使えませんが、そもそもCOMオブジェクトを扱うのが中心でWSH向けのモジュールはほとんど存在しないのでまず問題にはなりません。
(もしかするとAMDやUMDならいけるかもしれませんが未確認です、Webpack等のモジュールハンドラを使う場合は話が変わりますがこの記事では扱いません)

tsconfig.jsonを使う場合は下記の設定でトランスパイルできます。

tsconfig.json
{
  "compilerOptions": {
    "target": "es2015",
    "module": "none",
    "lib": ["es2015"],
    "strict": true,
  }
}

コーディング

WSHでは.jsファイルをダブルクリックで起動すると古いJScriptエンジンで実行するため、
Chakraエンジン対応のWSHスクリプトをダブルクリックで実行できるようにする
という記事でダブルクリックでもChakraエンジンで起動するようにしましたが、このVer.2の内容をTypeScriptで実装するとこうなります。

test.ts
/*@cc_on
@if (1)
var sh = WScript.CreateObject("WScript.Shell");
var fso = WScript.CreateObject("Scripting.FileSystemObject");
var ads = WScript.CreateObject("ADODB.Stream");

ads.charset =  "UTF-8";
ads.Open();
ads.LoadFromFile(WScript.ScriptFullName);
var text = ads.ReadText(-1);
ads.Close();

var outf = fso.GetFile(WScript.ScriptFullName).ParentFolder.Path + "\\_" + WScript.ScriptName;

ads.charset = "Shift-JIS";
ads.Open();
ads.WriteText(text, 1);
ads.SaveToFile(outf, 2);
ads.Close();

var command = sh.ExpandEnvironmentStrings("%windir%") + "\\System32\\wscript.exe //E:{1B7CD997-E5FF-4932-A7A6-2A9E636DA385} " + outf;

sh.run(command, 1, true);

fso.DeleteFile(outf);

WScript.Quit();

@end
@*/
//@if (0)
class Test {
  private name : string;

  constructor(name : string) {
    this.name = name;
  }

  output() {
    return 'Hello ' + this.name;
  }
}

class ExTest extends Test {
  output() {
    return  super.output() + '!!';
  }
}

var test = new Test('わーるど');
WScript.Echo(test.output()); //Hello わーるど

var extest = new ExTest('わーるず');
var sh = WScript.CreateObject("WScript.Shell");
sh.Popup(extest.output()); //Hello わーるず!!

//@end

これを先ほどの設定でトランスパイルするとそのままダブルクリックで実行できるWSHスクリプトが完成します。

gulp等のタスクランナーでトランスパイル後のコードをShift-JISに変換すればいいのでは…

タスクランナーのgulpにはgulp-convert-encodingなるプラグインがあるようなので、Typescript使うなら上記Ver2で呼びなおしの際に変換するよりもこのプラグインで変換したほうがいいに決まってますよね…

参考: gulp:ビルド時にcharsetやファイルエンコードをShift_JISに変換する方法

インテリセンス

@types/windows-script-hostをインストールしていればWScript.CreateObject()でCOMオブジェクトを作っても対応する適切な型を推測してコード補完してくれる仕組みになっているようです。
ただし、型定義に存在しないCOMオブジェクトを指定するとエラーになってトランスパイルできません。
なので繰り返しになりますが、Microsoft OfficeなどのWSHとは本来無関係のCOMオブジェクトを使う場合は対応した型定義をインストールする必要があるので、npmパッケージ一覧で探してみてください。

どうしても型定義が存在しないCOMオブジェクトを使いたい場合は以下のように引数をanyにキャストします。当たり前ですがコード補完は効きません。

var ie = WScript.CreateObject("InternetExplorer.Application" as any);

ChakraとJScriptの相違点(メモ)

  • new ActiveXObjectは使えません。代わりにWScript.CreateObjectを使います。
  • なぜかWScript.Quitは使えません(型定義には入っていますが)。代替方法は基本的にないようです。
  • 条件付きコンパイルは一切使えません。JScriptとChakraの判別で有難く使ってますがそれ以外ではJscript独自仕様でぶっちゃけ不要なので問題ないです。

参考

[Office]TypescriptとWebpackを使ってWSHを書いてOfficeを操作する
TypeScriptでWSHを書いちゃおう

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What is going on with this article?