TypeScript の async/await を Electron で使ってみる

TypeScript とは、 いわゆる altJS のひとつで、 ECMAScript (JavaScript) に静的型付けを加えたスーパーセットとなるプログラミング言語だ。
この TypeScript には、 ES6 (ECMAScript 6, Harmony) 相当のコードから ES5, ES3 にコンパイル (トランスパイル) する機能のほか、 ES7 で予定されている一部の機能を先取りし ES6 にコンパイルして使用することもできる。

そんな時代を先取りした機能の一つが "async/await" だ。

"async/await" とは 2012年に C# 5.0 とともに登場した記述方法で、 これを使うと、 非同期な処理を コールバック地獄にならず、 あたかも同期的な処理のように書くことができる。
同様の記述が、最近 Python 3.5 でもサポートされ、これからの非同期処理のスタンダードとなるだろう。

しかし、 TypeScript で async/await を使うには コンパイル後の ECMAScript の実行環境が ES6 をサポートしていなくてはならない。
現行のブラウザのシェアを考えると、 ES6 をサポートしないブラウザ (主に IE, Safari だが) を切り捨てる選択肢はちょっと厳しい。

一方でサーバサイド JavaScript として有名な node.js では、最近になって組織の変更のおかげで開発が活発化し、 ES6 のサポートが入ってきている。
しかし、 node.js はサーバサイドの技術。 クライアントアプリで使えた方がいろいろな用途で使えて夢が広がる気がする。

そこで Electron ですよ。

Electron (旧 Atom-Shell) とは、 Chromium の HTML5 と node.js の技術を使って、クロスプラットフォームのデスクトップアプリを作れるアプリケーションエンジンだ。

JavaScript エンジンごと中に内包しているため、 OS や インストールされたブラウザのバージョンを一切気にせずに HTML5 アプリケーションが作れるという、 IE に苦しめられている諸兄には夢のような技術 (?) だ。
Slack のデスクトップクライアントや、Visual Studio Code なんかも、 Electron を使って作られている。

そしてこの Electron は node.js の技術を使っていると述べたとおり、 ES6 がつかえるではないか!

…ということで、 Electron + TypeScript で async/await を使ってみようと思う。

続きを読む

Redmine + SQLite を Windows で ササっと 0 からインストール する 6つ のステップ

自分でローカルで動かして プロジェクト管理 したり、開発環境としていろいろ試してみるために、 Windows に Redmine を極力簡単に 0 からインストールする方法を紹介する。

Ruby と DevKit と Redmine を落とす

まずは Ruby が無くては始まらないので、 RubyInstaller つかって Ruby を入れる。
Redmine が使っている Rails を、 gam を使ってインストールするには、 Cコンパイル環境がないといけない。しかし、標準の Windows の環境では残念ながらCコンパイルできない。 このため、 RubyInstaller で公開されている Devkit も入れておく必要ある。 (「はじめてのRuby on Rails3」サポートページ「DevKitの使い方」 のページが詳しい) 続きを読む

PowerShell で 配列をシャッフルする

コード

PowerShell で 極力簡単に配列をシャッフル (ランダムにソート) する方法。
速度や制度などはガン無視して、簡単に書けることを重視。

$shuffled = $array | sort -prop @{Exp={[Guid]::NewGuid()}}

ハイ終わり。

検証

ホントに実用的なシャッフルになっているか心配なので、実際に 0~19 のシャッフルを 2000 回行って、先頭に来た数字と、10 が来たインデックスを集計してみる。

$r = 0..1999
$r | %{ $r[$_] = 0..19 | sort -prop @{Exp={[Guid]::NewGuid()}}; }
$r | %{ $_[0] } | group | Format-Table -AutoSize
$r | %{ $_.IndexOf(10) } | group | Format-Table -AutoSize
Count Name Group
----- ---- -----
  104 16   {16, 16, 16, 16...}
   91 19   {19, 19, 19, 19...}
  111 8    {8, 8, 8, 8...}
  102 7    {7, 7, 7, 7...}
   95 18   {18, 18, 18, 18...}
  105 3    {3, 3, 3, 3...}
   95 12   {12, 12, 12, 12...}
   83 15   {15, 15, 15, 15...}
  100 17   {17, 17, 17, 17...}
   89 5    {5, 5, 5, 5...}
  103 13   {13, 13, 13, 13...}
  103 11   {11, 11, 11, 11...}
  101 10   {10, 10, 10, 10...}
  110 4    {4, 4, 4, 4...}
  100 6    {6, 6, 6, 6...}
   88 2    {2, 2, 2, 2...}
  123 9    {9, 9, 9, 9...}
   92 1    {1, 1, 1, 1...}
  107 0    {0, 0, 0, 0...}
   98 14   {14, 14, 14, 14...}

Count Name Group
----- ---- -----
  102 17   {17, 17, 17, 17...}
   93 15   {15, 15, 15, 15...}
  100 9    {9, 9, 9, 9...}
  109 18   {18, 18, 18, 18...}
   91 4    {4, 4, 4, 4...}
  104 5    {5, 5, 5, 5...}
  111 3    {3, 3, 3, 3...}
  107 7    {7, 7, 7, 7...}
   83 1    {1, 1, 1, 1...}
  106 10   {10, 10, 10, 10...}
  101 13   {13, 13, 13, 13...}
   93 8    {8, 8, 8, 8...}
  111 16   {16, 16, 16, 16...}
  101 0    {0, 0, 0, 0...}
   83 2    {2, 2, 2, 2...}
  104 14   {14, 14, 14, 14...}
  103 12   {12, 12, 12, 12...}
   98 11   {11, 11, 11, 11...}
   81 19   {19, 19, 19, 19...}
  119 6    {6, 6, 6, 6...}

だいたい 100 に収束しているし、問題ないんじゃない?

とはいえ、 Guid クラスは、一意性はある程度期待できると書かれているものの、ランダム性は特に言及されていない。
出現にパターンがある可能性もあるし、厳密にランダムである必要がある場合は、使わない方がいいかもしれない。

続きを読む

スクリプト言語などから、共有フォルダにある .NET アセンブリを完全信頼で読み込む

PowerShell や IronPython などで ネットワーク共有フォルダに置かれている .NET アセンブリを読み込むと、このアセンブリのパスが実行ファイルの起動パスと異なるため、部分信頼での実行となってしまい、ファイルの読み書きなどの多くのコードが実行できない。
参考: MSDN | イントラネット アプリケーションの完全信頼での実行

一旦バイナリファイルをメモリに読み込んでから、アセンブリとしてロードするなどと言う方法もあるが、アセンブリからの相対パスなどが利用できなくなったりと、若干使い勝手が悪くなってしまう。

その回避方法として、Vista 以降限定ながら、アセンブリのフォルダをローカルにシンボリックリンクを貼って、そのシンボリックリンクを経由してアセンブリにアクセスすれば、完全信頼として実行することができる。

例えば、複数の PC で同じスクリプトを実行する様な場合、バージョンアップするときに全部の PC をもれなく更新するなど環境をそろえるが面倒だ。
このようなとき、イントラネットの共有ディレクトリにスクリプト置いて、ローカルからシンボリックリンクを通して実行すれば、更新するときはネットワーク共有のスクリプトを書き換えるだけで済み、コードも完全信頼で実行されるので、なかなか便利になる。

サンプルコード

実際に nasne の共有ディレクトリに、ファイルの読み込みを行えるコードを持ったアセンブリを作成して、読み込んでみよう。

続きを読む

相対パスを指定して、UAC が働く「管理者として」、バッチを起動するショートカットを作る

相対パスを指定して、コマンドやアプリケーションを管理者権限で実行するような、ショートカットを作成したい。

管理者としてでなければ、ショートカットのプロパティで「作業フォルダ」を空白にしておくと、エクスプローラからショートカットを起動したときに、ショートカットの場所がカレントディレクトリ(作業フォルダ)になることを利用して、

"%ComSpec%" /C START "" "<相対パス>" [引数...]

としたショートカットを作成することで実現できる。
(一瞬コマンドプロンプトが立ち上がる問題は、「実行時の大きさ」を最小化にしておくことである程度回避可能)

ところが、ショートカットの詳細設定から「管理者として実行」を選んでしまうと、カレントディレクトリが %SystemRoot%\system32 へ勝手に変更されてしまう。
こうなると、上記のショートカットでは %SystemRoot%\system32 からの相対パスを開こうとするため、意図した動作にならない。

このため、 UAC を起動させる ものと、カレントディレクトリの情報を渡す ものの 2つのショートカットを作成することで実現させる。

START コマンドを使うので、内容を理解する場合はこのコマンドのヘルプをよく読み込んでおくと良いかも知れない。

START ["タイトル"] [/D パス] (中略) [コマンド/プログラム] [パラメーター]

    "タイトル"  ウィンドウのタイトル バーに表示するタイトル。
    パス        開始するディレクトリ。

    コマンド/プログラム
                内部コマンドまたはバッチ ファイルの場合、コマンド プロセッサ
                は cmd.exe の /K オプションを使用して実行されます。
                これは コマンドの後でもウィンドウが残ることを意味
                します。

                内部コマンドまたはバッチ ファイルではない場合、そのプログラム
                はウィンドウ モードのアプリケーションまたはコンソール
                アプリケーションとして動作します。

   パラメーター
               コマンド/プログラムに渡すパラメーターです。

UAC を起動させるショートカット

まずは、指定した プログラム/コマンド を パラメータ付きで 管理者として実行するショートカットを作成する。

以下の様にプロパティを設定したショートカットを作成しよう。

続きを読む

リモートデスクトップ時に、バッチでサーバ側のPCをスリープさせる

リモートデスクトップとかやっていると、WoL で遠隔起動はできるのに、コマンドプロンプトにも PowerShell にも、(休止じゃなくて)スリープができるコマンドがなくて困る。
そんなときに、Windows7 以降で標準搭載している PowerShwll を使って、Win32API を直呼び出しして、休止する方法をご紹介。

使い方はとっても簡単。
下記の一行を hoge.bat fuga.cmd などと、適当なバッチファイルにして保存するだけ。
後はダブルクリックすれば、その PC をスリープ状態にできる。

@echo (Add-Type TempClass -Member '[DllImport("powrprof.dll")]public static extern bool SetSuspendState(bool Hibernate,bool ForceCritical,bool DisableWakeEvent);' -PassThru)::SetSuspendState($false,$false,$false) | powershell -c -

呼び出している Win32API については、MSDN の記事を参照: SetSuspendState function (Windows)
「SetSuspendState を呼び出す C# の関数を、PowerShell でコンパイルし、PowerShell から呼び出すようになっているコード」を、コマンドプロンプトで echo し、実行コマンドとして PowerShell にパイプで渡しているだけだ。

やってることはめんどくさいが、Windows7 以降なら追加のツールのインストールとかも必要なくすぐに作れるのがミソ。
PowerShell + Add-Type は本当に何でもできるから困る。

ちなみに、ちまたで見かける

shellrundll32.exe PowrProf.dll,SetSuspendState 0,1,0

とか言うのは間違った使い方だ。
Rundll32.exe の仕様 を見ればわかるとおり、このアプリケーションは、特定のプロトタイプに従った関数を呼び出すためのもので、任意の関数を呼ぶためのものではない。
上記のような呼び出し方をすると、実際には

   hwnd = (parent window handle)
   hinst = HINSTANCE of PowrProf.dll
   lpszCmdLine = "0,1,0"
   nCmdShow = (whatever the nCmdShow was passed to CreateProcess)

としたうえで、

   SetSuspendState(hwnd, hinst, lpszCmdLine, nCmdShow)

という呼び出しをしていることになってしまう。
これはもちろん SetSuspendState の本来の引数である (BOOLEAN Hibernate, BOOLEAN ForceCritical, BOOLEAN DisableWakeEvent) の bool 値3つに換算すると、(true, true, true) となるため (hwnd, hinst, lpszCmdLine いずれも 0 にならないj)、意図したスリープ状態にならない。
それどころか、イベントやタイマ、WoL から起動できなくなったりする為、Rundll32.exe を使うのは避けた方がいいだろう。

SetSuspendState に限っては、呼ばれる関数に対して呼び出す引数の数(正確には引数の数ではなく、引数の合計サイズ)が多いので問題にはならないが、場合によってはメモリ破壊を引き起こすこともあり得るので、 Rundll32.exe の扱いには注意が必要だ。

Windows コマンドプロンプトで、パイプでつないだコマンドの終了コードを取得

パイプにつないだとあるコマンドの終了コードを読みたい。

しかし、パイプ後の %errorlevel% の中身は、パイプ先の最後のコマンドの終了コードになる。
また、パイプの中身は独立したプロセスになっているようで、この中でいくら環境変数の設定を行っても、消えてしまうのだ。

…となっては仕方ない、いったん一時ファイルに書き出した後、その値を読み出すしかない。

set tmplog=%TEMP%\errlv_%DATE:/=%%RANDOM%%RANDOM%.log
(cd d:\nonexist & call echo %^^errorlevel% ^>"%tmplog%") | sort
for /f "usebackq" %A in ("%tmplog%") do echo result %A
del "%tmplog%"

パイプの呼び出し時と、all echo 時、そして実行時の 合計 3回 環境変数の展開が行われるので、最初の2回分を キャレットで回避しているのがミソ。

ちなみに、cd d:\nonexist は、フォルダが存在しない場合に errorlevel が返されるのを利用したもので、 sort はパイプで文字を受け取るデモになっている。(一行だけなので意味は無いけど…)

ただし、バッチファイルに書くときは、以下の様に % を重ねて書かなくてはならないので注意。

set tmplog=%TEMP%\errlv_%DATE:/=%%RANDOM%%RANDOM%.log
(cd d:\nonexist & call echo %%^^errorlevel%% ^>"%tmplog%") | sort
for /f "usebackq" %%A in ("%tmplog%") do echo result %%A
del "%tmplog%"

続きを読む

System.Data.SQLite でどれをインストールするべきか

ちょっとした宣伝:

NuGet パッケージマネージャを使う場合については、別途

の記事にまとめている。

以下、本題。

メモ: 内容が 2012 年当時のものなので、 引用元の文章がすでになくなっていたりするが、 内容的には問題ないはずだ。

System.Data.SQLite を導入する

SQLite の ADO.NET アダプタである、System.Data.SQLite。
単なるラッパではなく、SQLite 自体もパッケージに持っているので、別途 SQLite をパッケージに含めなくても良いのが利点。
しかも、ライセンスが Public Domain であるのが、非常に使い勝手が良い。

注意: 詳しくは System.Data.SQLite の 著作権表記 を読んでほしいが、"System.Data.SQLite.Linq" と "System.Data.SQLite.EF6" については、ソースコードの一部が Ms-PL ライセンスとなっている。
Ms-PL ライセンスとなっている SQL Generation ディレクトリ のソースは、public domain と明示されているものをのぞくと、すべて copyright (c) Microsoft Corporation と書いてある。 ビルド済みバイナリには Microsoft の著作権表記などが出てこないため、バイナリ配布であれば Public Domain と書かれたライセンスに従えば良いので、特に何も気にする必要はなさそうだ。 ソースコードを配布する場合は、上記ソースコード先頭などに書かれているの著作権表記等の部分をそのまま消さずに表示しなくてはならない点に注意すべきだろう。

さて、いざ使おうとダウンロードページに飛ぶと、それはもうすごい数のパッケージが配布されている。

続きを読む

[WPF] ウィンドウのリサイズが終了するまで、コントロールのリサイズを行わない方法 その2

間が開いてしまったが、ウィンドウのリサイズが終了するまで、コントロールのリサイズを行わない方法 その1 の続き。

このままだと、描画されていない部分が黒く残ってしまい気持ちが悪いので、レイアウトを行わない場合でも、ViewBox を使ってスケーリングして表示してみる。

続きを読む

[WPF] RadioButton の IsChecked バインディングがうまく動かない

ラジオボタンのデータバインディングを、チェックボタンと同様にやっているはずなのに、なぜか途中で動かなくなったりして、かなり詰まっていた。
解決方法…というか、回避策をメモしておこう。

続きを読む