Help us understand the problem. What is going on with this article?

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スクリプトが完成します。

インテリセンス

@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を書いちゃおう

riafeed
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした