2018年1月10日水曜日

コマンドプロンプトやタスクスケジューラからPC をスリープ/サスペンドさせたい。(SetSuspendState)

解決方法

ネットが広大すぎて正解が分からなかったため、PCをスリープ (サスペンド) させるためだけのプログラムを自分で書いた。

SetSuspendState.zip (1 KB)

  • このzipファイルには、「SetSuspendState.exe」という実行可能ファイルが入っている。
  • 「SetSuspendState.exe」を実行すると、PCがスリープする
    ※事前の確認メッセージ等は一切出ない。
  • インストールやランタイムライブラリは不要。
  • 動作確認環境: Windows 7 Professional (x64) SP1

※上記プログラムは無保証です。ご利用は各自の自己責任でお願いします。

※リスクの一例として、万が一、スリープやスリープ後の復帰がうまくいかず、保存していなかったメモリ上のデータが失われるリスクもゼロではないため、各自で事前に動作確認をしてからご利用ください。


上記プログラムの説明

  • Windows の API関数 (SetSuspendState) を呼び出すだけのプログラム。
    SetSuspendState(FALSE, FALSE, FALSE)

    第1引数のFALSEは「サスペンド」を意味し、(「休止」か「サスペンド」かの二択)
    第3引数のFALSEは「復帰イベントの許可」を意味する。


上記プログラムのソースコード全文 (C++)

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <powrprof.h>

void WinMainCRTStartup()
{
  ::SetSuspendState(FALSE, FALSE, FALSE);
  ::ExitProcess(0);
}

おまけ: 本質に関係のない技術的注釈

  • 実行可能ファイルのサイズを小さくしてみた。(3,072 バイト)
  • 「KERNEL32.dll」と「POWRPROF.dll」にしか依存していない。

2017年9月22日金曜日

ROBOCOPY の除外オプションの挙動を検証してみた。

序文

近年のWindowsに標準搭載されている ROBOCOPY (高機能なファイルコピーコマンド) について、ヘルプを見ただけではわかりにくい細部の挙動 (除外オプション回り) を検証してみた。

※検証は Windows 7 でしか行っていないため、Windows 10 などでは挙動が異なる可能性あり。


補足: ROBOCOPYを使用する上で、認識しておいた方がよい挙動

  • ROBOCOPYは、ファイルの更新判定を、メタ情報 (更新日時とファイルサイズ) だけで行っている。→ ファイルの中身は比較していない。

  • これは、コピー速度を上げるための有効な戦略で、ほとんどの場合で問題は出ない。

    例外として、もし(パワーユーザが特殊な操作で)ファイルの更新日時を操作していると、ROBOCOPYがファイルの更新に気づけないケースが発生しうる。


検証環境

  • Windows 7 Professional (SP1) 64bit版、日本語
  • コマンドプロンプトのコードページ: 932 (Shift-JIS) と 65001 (UTF-8)

検証結果

検証結果を表にまとめてみたものの、ROBOCOPY にある程度慣れている人にしか伝わらないかもしれない。

No.ファイル有無更新日時サイズ中身表示除外オプション
1コピー先 のみ---「*EXTRA File」/XX
2コピー元 のみ---「New File」
「新しいファイル」
/XL
3両方に存在 同一日時 同一サイズ同じ 「Same」
「同じ」
(デフォルトで
除外される)
4 異なる
5 別サイズ - 「Changed」
「変更済み」
/XC
6コピー元が新しい同一サイズ同じ 「Newer」
「より新しい」
/XN
7 異なる
8 別サイズ -
9コピー元が古い 同一サイズ同じ 「Older」
「より古い」
/XO
10 異なる
11 別サイズ -
No.ファイル有無更新日時サイズ中身表示 (「/XL /V」指定時)
2コピー元 のみ---「lonely」
「コピー元にだけ存在する」

一言コメント

  • 検証の結果分かったこと: 「/XC」の「Changed」(変更された/変更済み) というのは、
    「ファイルサイズが変更されていて、更新日時が変更されていない」という意味だった。
    このオプションを単独で使う状況が思いつかない。
  • コピー元だけに存在するファイルのみをコピーしたいとき (= 両方に存在するファイルは無視したいとき) には、「/XC /XN /XO」を指定すればよい。
  • 除外オプションを試行錯誤するときには、あわせて「/V」オプションも指定しておくと捗る。
  • ROBOCOPYをコピー実行中に Ctrl+C で強制停止させた場合、コピー先にコピー途中の不完全なファイル(更新日付が1980年のファイル)が残るので、適宜手作業で取り除くこと。

読み物 (1): ROBOCOPYの画面表示について

ROBOCOPY を コードページ 65001 で実行すると、きわめて整然とした画面出力がされる。(図1)
非常に見やすく、わかりやすい。

図1. chcp 65001: きわめて整然でわかりやすい

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows                              
-------------------------------------------------------------------------------

  Started : Thu Sep 21 07:21:20 2017

   Source : T:\srcDir\
     Dest : T:\dstDir\

    Files : *.*
     
  Options : *.* /V /L /COPY:DAT /R:1000000 /W:30 

------------------------------------------------------------------------------

                   10 T:\srcDir\
   *EXTRA File          6 dstExtra.txt
           same         6 same.txt
           same         6 sameTime_diffContent_sameSize.txt
     Changed            6 sameTime_diffContent_diffSize.txt
     New File           6 srcLonely.txt
     Newer              7 srcNewer_diffContent_diffSize.txt
     Newer              6 srcNewer_diffContent_sameSize.txt
     Newer              6 srcNewer_sameContent.txt
     Older              6 srcOlder_diffContent_diffSize.txt
     Older              6 srcOlder_diffContent_sameSize.txt
     Older              6 srcOlder_sameContent.txt

------------------------------------------------------------------------------

               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         1         0         1         0         0         0
   Files :        10         8         2         0         0         1
   Bytes :        61        49        12         0         0         6
   Times :   0:00:00   0:00:00                       0:00:00   0:00:00

   Ended : Thu Sep 21 07:21:20 2017

しかしながら、我々の コードページ 932 (日本語Windows環境のデフォルト) では、画面表示の桁がそろっておらず、見づらい。(図2)
日本語翻訳チームさんたちには、もう少し頑張ってもらいたかった。

図2: chcp 932: 桁合わせがうまくいっておらず、わかりづらい。

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Windows の堅牢性の高いファイル コピー                              
-------------------------------------------------------------------------------

  開始: Thu Sep 21 07:21:20 2017

   コピー元 : T:\srcDir\
     コピー先 : T:\dstDir\

    ファイル: *.*
     
  オプション: *.* /V /L /COPY:DAT /R:1000000 /W:30 

------------------------------------------------------------------------------

                   10 T:\srcDir\
   *EXTRA File          6 dstExtra.txt
           同じ         6 same.txt
           同じ         6 sameTime_diffContent_sameSize.txt
     変更済み            6 sameTime_diffContent_diffSize.txt
     新しいファイル           6 srcLonely.txt
     より新しい              7 srcNewer_diffContent_diffSize.txt
     より新しい              6 srcNewer_diffContent_sameSize.txt
     より新しい              6 srcNewer_sameContent.txt
     より古い              6 srcOlder_diffContent_diffSize.txt
     より古い              6 srcOlder_diffContent_sameSize.txt
     より古い              6 srcOlder_sameContent.txt

------------------------------------------------------------------------------

                  合計     コピー済み      スキップ       不一致        失敗    Extras
   ディレクトリ:         1         0         1         0         0         0
     ファイル:        10         8         2         0         0         1
      バイト:        61        49        12         0         0         6
       時刻:   0:00:00   0:00:00                       0:00:00   0:00:00

       終了: Thu Sep 21 07:21:20 2017

読み物 (2): 除外オプションの挙動

ここでいう「除外オプション」とは、一部のファイルをバックアップ対象外とするためのオプションを意味する。 これらは、ROBOCOPYのコマンドラインオプション内の「ファイル選択オプション」(File Selection Options)グループに属している。

以下は、ROBOCOPYのコマンドラインヘルプからの抜粋である。(図3、図4)

図3: ROBOCOPYのコマンドラインヘルプ (日本語版) からの抜粋

/XC :: 変更されたファイルを除外します。
/XN :: 新しいファイルを除外します。
/XO :: 古いファイルを除外します。
/XX :: コピー先にだけ存在するファイルとディレクトリを除外し
      ます。
/XL :: コピー元にだけ存在するファイルとディレクトリを除外し
      ます。
/IS :: 同一ファイルを含みます。
/IT :: 異常なファイルを含めます。

図4: ROBOCOPYのコマンドラインヘルプ (英語版) からの抜粋

/XC :: eXclude Changed files.
/XN :: eXclude Newer files.
/XO :: eXclude Older files.
/XX :: eXclude eXtra files and directories.
/XL :: eXclude Lonely files and directories.
/IS :: Include Same files.
/IT :: Include Tweaked files.

とりあえず、日本語版のヘルプは、「ヘルプ上の文言」と「実際に画面表示される文言」とが一致してないため、非常にわかりづらい。わかりづらいというよりは、用語の混乱がある。

ROBOCOPYの概念上、「新しいファイル (New File/Lonely)」と「より新しい (Newer)」は全く別の意味をあらわす用語になっている。これが混乱の元である。

たとえば、「/XN」というオプションの説明文として、
「/XN :: 新しいファイルを除外します。」
とあるが、このオプションでは 画面上で「新しいファイル」と表示されるファイルは除外されない。このオプションで実際に除外されるのは、画面上で「より新しい」と表示されるファイルである。

「新しいファイル」と表示されるファイルを除外するには、「/XL」を指定する必要がある。

(もし「/XN」オプションの説明文が、
「/XN :: コピー先より新しいコピー元ファイルを除外します。」
だったなら、もう少し親切だったように思う)

なお、英語版のヘルプにもあいまいなところ(説明不足による複数の解釈の余地)があり、あまりわかりやすいとは言えない。日本語翻訳チームも苦労したのかもしれない。

2017年9月16日土曜日

ckw-mod を個人的に改造してみた。(その2)

(ckw-mod を個人的に改造してみた。 の続き)

ダウンロード

※動作確認は、Windows 7 Professional SP1 (64bit) で実施。


リリースノート

Release 0.9.1-mod-amdkkj-2 amdkkj/ckw-mod GitHub
  • 複数行貼り付け時の確認ダイアログをモーダルに変更
  • コードページの動的変更に対応 (by rururu)
    • 隠しコンソールのコードページを常に監視し、
      chcp コマンド等で動的にコードページが変更された場合にも追従するように変更
  • システムメニュを日本語で表示するように変更
    ただし、OSの言語設定が日本語「以外」の環境では、これまで通り英語のシステムメニュが表示される
    • システムメニュで使用している文字列をリソースファイルに切り出したため、
      今後はリソースファイルを編集するだけで日本語以外にも対応可能
  • システムメニュに、標準コマンドプロンプト互換の「貼り付け」を追加
    • 標準コマンドプロンプト同様に、Alt + スペース → e → p の
      キーコンビネーションで クリップボードからの貼り付けができるようになった

関連記事

2017年9月12日火曜日

結局のところ、blockquote要素の内部にcite要素を入れてもよいのか? (HTML)

結論

入れてもOK。
blockquote要素の内部(配下)に、cite要素を入れてもよい。(と思われる)

根拠

下記は、引用についての引用。(※ただし、強調部分は引用者による)

The <blockquote> element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.

Content inside a blockquote other than citations and in-line changes must be quoted from another source, whose address, if it has one, may be cited in the cite attribute.


経緯

以前にどこかで、「blockquote要素の内部には絶対に絶対にcite要素を入れては駄目だblockquote要素配下には純粋に引用されたものだけを書くんだcite要素は外に出せもしくは代わりにcite属性の方を使え」という主張を見た記憶があったため、調べてみた。

HTML5仕様はまだドラフト段階なので、二転三転することもあるのかもしれない。

2017年9月10日日曜日

ckw-mod を個人的に改造してみた。

※2017/9/16 追記: 最新バージョンはこちら。→ ckw-mod を個人的に改造してみた。(その2)

まとめ


ダウンロード

※動作確認は、Windows 7 Professional SP1 (64bit) で実施。


リリースノート

Release 0.9.1-mod-amdkkj-1 amdkkj/ckw-mod GitHub
  • クリップボードから貼り付けられる文字列が複数行だった場合に、確認ダイアログを表示するよう変更
  • 「--chdir (-cd)」オプション処理の変更 (失敗時の救済処理を追加)
    • 指定されたパスへの SetCurrentDirectory() がエラーになった場合に、
      指定されたパスの「親ディレクトリ」に対し
      再度 SetCurrentDirectory() を試みる処理を追加
  • Windows 7 のエクスプローラで ckw.exe のプロパティを表示したとき、
    「製品名」「著作権」が表示されていなかったため、表示されるように修正
  • ウインドウタイトルが128文字以上の時に落ちる不具合を修正 (by rururu)

関連記事

2017年9月4日月曜日

ckw-mod の系譜を追ってみた。

まとめ

ckw-mod*1 には、本家バージョンよりもさらに開発がすすんでいる派生版 (フォーク) が存在する。

そこで、「(実質上の) 最新版がどこにあるのか」を調査した。※野良ビルドは調査対象外

*1: ckw-mod は、Windows標準のコマンドプロンプトの代替として使えるフリーソフト (オープンソース)

調査結果

Q. ckw-mod の最新は、どこにあるのか?

A. 2017年9月現在でもアクティブに更新されているのは、rururutan さん版 だと思われる。


備考1: ckw-mod の歴史

  1. 始祖 ckw (ckw-mod の派生元)

    はじめに ckw が あった。
    • http://www.geocities.jp/cygwin_ck/ ※リンク切れ
  2. ckw の消滅と、その亜種の乱立

    始祖 ckw は、なくなってしまった。
    しかしながら、ckw はオープンソースだったため、いろいろな人が各所でそれぞれ開発を引き継ぎ、それぞれの修正版を公開した。
  3. ckw-mod 本家 の誕生

    有志の方 (おそらく、deflis さん) が、多数に枝分かれした ckw の各修正版の変更内容を ほぼ すべて取り込んだ統一版である、ckw-mod を作った。(偉業)
  4. ckw-mod 本家 の発展 (~2013年ごろ)

    有志の方々 (deflis さん や、southly さん 他多数) により、本家の ckw-mod はさらに改良されていった。
    本家の更新は 2013年8月ごろまで続いた。
  5. ckw-mod 派生版の台頭

    本家 ckw-mod の更新は落ち着いたが、それ以降も、本家から派生 (fork) したプロジェクト (ckw-mod 派生版) では 引き続き開発が続けられた。
    たとえば、rururutan さんの rururutan/ckw-mod は 2017年現在でもアクティブであり、本家をベースとして UNICODE対応 や Windows 10対応 も行われている。

備考2: 2017年9月初時点での、ckw-mod 派生プロジェクトについて

2017年9月初現在で、ckw-mod の派生 (fork) は、24個 存在する。

この調査を始めた当初は、24個の中の どのプロジェクト (リポジトリ) が最新なのかが分からなかった。そこで、各プロジェクトの状況*1を簡単に調べてみた。(*1: 2017年9月初 現在)

0.@ckw-modckw-mod / ckw-mod本家
1.@abedasterabedaster / ckw-modコミットなし
2.@amuramatsuamuramatsu / ckw-mod独自ブランチあり: improvement-stability (stale)
3.@comuttuncomuttun / ckw-mod独自ブランチあり: b_dist (stale)
4.@deflisdeflis / ckw-mod(本家のプロジェクトメンバー)
5.@iusenix├→ iusenix / ckw-modコミットなし
6.@kkawa└→ kkawa / ckw-modコミットなし
7.@draftcodedraftcode / ckw-mod独自ブランチあり: FontHack (stale)
8.@Fuj18Fuj18 / ckw-modコミットなし
9.@hmrhmr / ckw-modコミットなし
10.@hokorobihokorobi / ckw-modコミットあり: master
11.@lillycodelillycode / ckw-modコミットなし
12.@mallowlabsmallowlabs / ckw-mod独自ブランチあり: high_dpi_support (stale)
13.@MatsuyanagiMatsuyanagi / ckw-modコミットなし
14.@mecabmecab / ckw-mod独自ブランチあり: high_dpi_compat, envvar,
more_bgimage_type (いずれも stale)
15.@mwparkmwpark / ckw-modコミットなし
16.@nocd5nocd5 / ckw-modコミットあり: master
独自ブランチあり: nocd5Feature (stale)
17.@ousttrueousttrue / ckw-modコミットあり: master
18.@rururutanrururutan / ckw-modコミットあり: master, develop ※active
独自ブランチあり: unicode (stale)
19.@tesurijp└→ tesurijp / ckw-mod独自ブランチあり: AdhocForceV2 (stale)
20.@southlysouthly / ckw-mod(本家のプロジェクトメンバー)
21.@staniastania / ckw-modコミットなし
22.@tipjstipjs / ckw-modコミットなし
23.@wantorawantora / ckw-modコミットあり: master
独自ブランチあり: support_gcc, totray, chdir_lock,
remove_warnings (いずれも stale)
24.@yukke64yukke64 / ckw-modコミットなし

おまけ

25.@amdkkjamdkkj / ckw-mod諸般の事情(?)により、私もフォークしました。

関連記事

2017年8月31日木曜日

MinGW の make だけを手動でインストールする

必要なアーカイブ


インストール手順

  1. make-3.82.90-2-mingw32-cvs-20120902-bin.tar.lzma から
    「mingw32-make.exe」を取り出して、パスの通ったディレクトリに格納する。
    ※お好みで、「mingw32-make.exe」を「make.exe」にリネームする。
  2. libintl-0.18.3.2-2-mingw32-dll-8.tar.xz から
    「libintl-8.dll」を取り出して、前手順と同じディレクトリに格納する。
    ※このDLLがないと、make に
    「コンピューターに libintl-8.dll がないため、プログラムを開始できません。この問題を解決するには、プログラムを再インストールしてみてください。 」
    と怒られる。
  3. libgcc-6.3.0-1-mingw32-dll-1.tar.xz から
    「libgcc_s_dw2-1.dll」を取り出して、前手順と同じディレクトリに格納する。
    ※このDLLがないと、make に
    「コンピューターに libgcc_s_dw2-1.dll がないため、…」と怒られる。
  4. libiconv-1.14-3-mingw32-dll.tar.lzma から
    「libiconv-2.dll」を取り出して、前手順と同じディレクトリに格納する。
    ※このDLLがないと、make に
    「コンピューターに libiconv-2.dll がないため、…」と怒られる。
  5. おわり。

補足

各アーカイブからのファイル取出しは、7-Zip があれば 事足りる。

2017年8月27日日曜日

Googleの検索結果リンクを、直接リンクに書き換えるブックマークレット

概要

Googleの検索結果リンクを、「検索結果への直接リンク」に置き換えるブックマークレットを書いた。

いわゆる一般的なブックマークレットの用法と同様だが、
Googleの検索結果ページを表示している状態で実行することで、表示中ページの全検索結果リンクを更新する。

具体的には、検索結果の各リンクのURLが下記のようにGoogleサーバ経由となっている場合に、

  • https://www.google.co.jp/url?q=http://example.com/&sa=~
  • https://www.google.co.jp/url?url=http://example.com/&rct=~

これを下記のような直接リンク (= Googleサーバを経由しない) に置き換える。

  • https://example.com/

ブックマークレットのソース (再掲)

整形すると、下記の通り。

javascript:(
  function() {
    var a = document.getElementsByTagName("a"),
        n = a.length,
        i = 0;

    while (i < n) {
      var u = a[i].href.match(/\/url\?(?:q|url)=(h[^&]+)/);

      if (u) {
        a[i].href = decodeURIComponent(u[1]);
      }
      ++i
    }
  }
)();

備考

  • Firefoxなどは、ブラウザ自体が上記ブックマークレットと同等(以上)の機能を内蔵している模様。

NTFS上の、空ディレクトリのサイズを知りたい。

まとめ

NTFS上で「空ディレクトリがどれだけのディスク容量を消費するのか」を実測した。

さまざまな因子があるため参考にもならない可能性が高いが、今回の検証による結果としては

空ディレクトリ1つあたり、1600バイト程度 のディスク容量

を消費していた。(空ディレクトリ10,000個の平均値、計測ミスの可能性もあり)

※この記事をこれ以降読んでも、とくにオチはありません。

2017年8月24日木曜日

ハードリンクの参照カウント数を考慮してくれる du コマンド が欲しい。 (Windows環境で)

結論

Sysinternals の Du (disk usage) は、
NTFS上での ハードリンクの参照カウント数 を考慮したうえで ディスクの使用量を算出してくれる。

経緯

  • dumpfs 系 のバックアップコマンド (たとえば、mdumpfs) を使うと、NTFSのハードリンク機能を駆使し、ディスク領域を極力消費せずに、各バックアップ断面のスナップショットを取ることができる。
  • たとえば、未変更のファイルに対して3回バックアップ (スナップショット) を取った場合、バックアップ結果のファイルは3つできるが、それらのディスク上の実体は共有されており、実際には ファイル1つ分のディスク領域しか消費しない。
    (参照カウントが 3 のファイルが、1つ存在する状態)
  • しかし、Windows上の一般的なツール (エクスプローラ他) は、NTFS上のハードリンクの参照カウントを考慮しない。
    (上記の3回バックアップの例の場合ならば、同じサイズのファイルがディスク上に3つとも存在し、ファイル3つ分のディスク領域を消費しているかのように報告する)
  • なお、本家(unix、linux環境) の du コマンドは、ハードリンクの参照カウントを考慮しているようである。
    (参考: ハードリンクがある場合の du によるディスク消費量表示の注意 - 学習する機械、学習しない人間)
  • いわゆる Win32 port の du コマンド をいくつか試してみたが、ハードリンクの参照カウントを考慮してしているものは、ほとんどなかった。
    冒頭で掲示した Sysinternals版 の du コマンド は、数少ない例外である。

補足

上記の 「Sysinternals版 の du コマンド」は、「Size」と「Size on disk」(= ディスク上のサイズ) の両方をレポートしてくれるが、
「空のディレクトリ」の「Size on disk」については
1ディレクトリあたり「4,096 bytes」
とレポートしているように見える。
※「4,096 bytes」というのは、対象NTFSボリュームの クラスタサイズ (アロケーションユニットサイズ) だと思われる。

NTFSの内部構造については詳しくないのだが、空ディレクトリ1つ 4KB は大きすぎる気がする(*1) ので、別途調査予定。
*1 … MFT (Master File Table) の1レコード分である、1KB で収まるのではないか?


関連記事

2017年8月2日水曜日

CCleaner の v5.32.6129 には致命的なバグあり。Thunderbird のプロファイルデータが破損し、すべてのメールアカウント情報が白紙 (初期状態) に戻る。

本気で危険

  • メールクライアントのThunderbird を使用している人は、安易に CCleaner の「v5.32.6129」を使用しては駄目 (*1)。
  • 「v5.32.6129」を使用すると、(*1)
    Thunderbird のプロファイル(アカウント情報) を管理する「prefs.js」が 破損する。
    (日本語部分が文字化けし、Thunderbird が読み込みに失敗する)
  • Thunderbird は、起動時に「prefs.js」が読み込めないと「prefs.js」を初期化するため、
    すべてのメールアカウント情報が消える。(初回インストール直後の状態に戻る)
  • メールデータ自体は無事だが、Thunderbird がメールデータを認識できなくなるため、過去のメールも読めなくなる。

*1 … より厳密には、CCleaner v5.32.6129 上のアプリケーション別の設定で、
Thunderbird 配下の「保存場所」という項目にチェックが入っていると発生する模様。
この項目は、デフォルトではチェックされているらしい。

復旧方法

  • システム開発の備忘録: Thunderbirdのアカウントが破損したときの対処法
  • 「prefs.js」のバックアップがないと、もう取り返しがつかない。
  • 「prefs.js」のバックアップがあるならば、Thunderbird を終了させた状態で、
    「prefs.js」をバックアップから戻してやればよい。
  • 「prefs.js」は、プロファイルのディレクトリ
    (「Profiles\<8文字のランダムな文字列>.default」) の直下に存在する。

今後に向けて

  • CCleaner のバージョンを、一つ戻す。
    ひとつ前のバージョンである、CCleaner の「v.5.31.6105」ならば、今回の事象は発生していない。
  • 原理的には、バージョンを戻さずとも、
    CCleanerの設定で Thunderbird 配下の「保存場所」のチェックを外すだけで再発防止できそうだが、当方は不安だったためバージョンを戻した。
  • 日々の運用として、「prefs.js」のバックアップをこまめにとること。複数世代のバックアップが望ましい。

有用な情報

阿鼻叫喚の声

2017年7月23日日曜日

コンピュータ将棋における、SFEN文字列の最大長について

※ネタ記事です。

※SFEN文字列 の詳細については、
「将棋所:USIプロトコルとは」 の 「SFENによる盤面と指し手の表記について」
と、Tord Romstad氏 の USI原案 (現在リンク切れ) を参考にしました。


ぼくのかんがえた さいちょうの えすえふいーえぬ

SFEN文字列 の最大長は、おそらく130文字。
※Move count (「次が何手目か」を表す数字) は、含めず

なお、この記事をこれ以降読んでも、とくにオチはありません。


長さ130文字のSFEN文字列 具体例

1+N1+S1+S1+N1/1+L1+R1+B1+L1/1+P1+P1+P1+P1/1+P1+P1+p1+p1/1+P1K1k1+p1/1+P1+P1+p1+p1/1+p1+p1+p1+p1/1+l1+b1+r1+l1/1+n1+s1+s1+n1 b 2G2g

上記の具体例の BOD形式 表現

後手の持駒:金二 
  9 8 7 6 5 4 3 2 1
+---------------------------+
| ・ 圭 ・ 全 ・ 全 ・ 圭 ・|一
| ・ 杏 ・ 龍 ・ 馬 ・ 杏 ・|二
| ・ と ・ と ・ と ・ と ・|三
| ・ と ・ と ・vと ・vと ・|四
| ・ と ・ 玉 ・v玉 ・vと ・|五
| ・ と ・ と ・vと ・vと ・|六
| ・vと ・vと ・vと ・vと ・|七
| ・v杏 ・v馬 ・v龍 ・v杏 ・|八
| ・v圭 ・v全 ・v全 ・v圭 ・|九
+---------------------------+
先手の持駒:金二 
手数=0    まで

上記の具体例の 局面図 (画像)


「最長」のレギュレーション

  • 平手の初期配置から、合法手で到達できる局面のみを対象とする。


参考リンク

参照したWebページ

使用させていただいたソフトウェア

2017年7月9日日曜日

Javaでの、2次元配列 (多次元配列) の作成方法の違いによるバイトコード差異について

Q. Javaでの2次元配列の作成において、「多次元配列風の作法」と「ジャグ配列風の作法」とでは、バイトコードに違いは出るのか?

多次元配列風の作法 ※正式な用語ではない
int[][] a = new int[3][4];
ジャグ配列風の作法 ※正式な用語ではない
int[][] a = new int[3][];
a[0] = new int[4];
a[1] = new int[4];
a[2] = new int[4];
ジャグ配列風の作法 その2
int[][] a = new int[][] {
  new int[4], 
  new int[4], 
  new int[4]};

A. バイトコードに差異は出る。

Javaの仮想マシンは、「多次元配列作成専用のオペコード」(multianewarray)を持っている。

したがって、「多次元配列風の作法」の方が、バイトコードがコンパクトになる。

調査で使用したJavaコンパイラ
javac 1.8.0_25 (Oracle)
Javaソースコードバイトコード
// 多次元配列風
int[][] a = new int[3][4];
ICONST_3
ICONST_4
MULTIANEWARRAY [[I 2
ASTORE 1
// ジャグ配列風
int[][] a = new int[3][];
a[0] = new int[4];
a[1] = new int[4];
a[2] = new int[4];
ICONST_3
ANEWARRAY [I
ASTORE 1

ALOAD 1
ICONST_0
ICONST_4
NEWARRAY T_INT
AASTORE

ALOAD 1
ICONST_1
ICONST_4
NEWARRAY T_INT
AASTORE

ALOAD 1
ICONST_2
ICONST_4
NEWARRAY T_INT
AASTORE
// ジャグ配列風 その2
int[][] a = new int[][] {
  new int[4], 
  new int[4], 
  new int[4]};
ICONST_3
ANEWARRAY [I

DUP
ICONST_0
ICONST_4
NEWARRAY T_INT
AASTORE

DUP
ICONST_1
ICONST_4
NEWARRAY T_INT
AASTORE

DUP
ICONST_2
ICONST_4
NEWARRAY T_INT
AASTORE

ASTORE 1

参考リンク

2017年7月3日月曜日

Javaにおける、フィールド修飾子 (final や transient 等) の記述順序について

結論

文法上は自由だが、慣習としては下記の順序で記述する。(推奨)

  1. アクセス修飾子 (public、protected、private、もしくは、何も書かない)
  2. static
  3. final
  4. transient
  5. volatile

根拠

  • 「Java 言語仕様」の「8.3.1. Field Modifiers」に、下記の記述あり。

    If two or more (distinct) field modifiers appear in a field declaration, it is customary, though not required, that they appear in the order consistent with that shown above in the production for FieldModifier.

    (日本語訳) フィールド宣言中にフィールド修飾子を複数記述する場合、必須ではないものの、慣習としては 上記の FieldModifier 生成規則に記述された順序で指定する。

  • 「java.lang.reflect.Modifier」の「toString(int mod)」に、下記の記述あり。

    修飾子名は、『Java(tm)言語仕様』のセクション8.1.1、8.3.1、8.4.3、8.8.3、および9.1.1で指定されている推奨修飾子順序に適合する順序で返されます。

補足

「final」と「transient」の組み合わせは、ほとんどの場合でナンセンス。
「transient」だとデシリアライズ時に null になるが、「final」ならば再代入ができない。
(当該フィールドの値は、デシリアライズ後は 常にnull になる)

例外として、シングルトンなどで、デシリアライズ時に readResolve() でインスタンス自体を読み替えてしまう場合だけは、「final transient」が意味を成す。

2017年6月24日土曜日

OpenCV-Python で読み込んだ画像を、wxPython で表示したい。

結論

実現は容易。 (※2017/6/24 全面改訂)

wx.BitmapFromBuffer() で、OpenCV で読み込んだ画像データ (np.ndarray) から wx.Bitmap を作成できる。

ただし、OpenCV で読み込んだ画像データは BGR形式であるため、事前に RGB形式に変換しておく必要あり。


import wx
import cv2
import numpy as np

def create_wx_bitmap_from_cv2_image(cv2_image):
    # type: (np.ndarray) -> wx.Bitmap

    height, width = cv2_image.shape[:2]
    cv2_image_rgb = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)

    return wx.BitmapFromBuffer(width, height, cv2_image_rgb)

上記関数を用いたサンプルコード

実行結果

2017年6月17日土曜日

wxPython 3.0.2.0 (Windows版) をインストールする際の注意事項 (「ImportError: No module named wx」対策)

要旨

  • wxPython 3.0.2.0 (64-bit Python 2.7) の Windows Binaries インストーラ (wxPython3.0-win64-3.0.2.0-py27.exe) には、不具合がある。

  • 上記インストーラは、wxPyhon のモジュールを、Python が認識できない場所にインストールしてしまう。

    誤: python\Lib\site-packages\wx-3.0-msw\wx
    正: python\Lib\site-packages\wx

  • また、インストールオプションによっては、wxPythonモジュール自体をインストールしない場合がある。


wxPython (3.0) のインポートエラー発生時に確認すべきこと

  1. site-packages 直下に、「wx」というディレクトリがあるか?
    → この記事で言及している事象が発生しているのならば、存在しないはず。

  2. site-packages 直下に、「wx-3.0-msw」というディレクトリがあるか?
    → こちらについては、インストーラが正常終了したのであれば、存在するはず。

  3. site-packages\wx-3.0-msw 直下に、「wx」というディレクトリがあるか?
    → インストールオプションにより結果は異なる。詳細は後述。


wxPython (3.0) のインポートエラーの解決方法

ケースA: 上記 3. の答えが 「YES」 の場合

症状: wxPython モジュール自体はインストールできているが、インストール先の場所が正しくない。

「wx」ディレクトリを、一つ上の階層(= site-packages 直下) に移動させることで、インポートエラーが解消する。


ケースB: 上記 3. の答えが 「NO」 の場合

症状: wxPython モジュール自体がインストールできていない。

この事象が発生するのは、インストール時のインストールオプションで「Compact installation」を選んだ場合である。(おそらく、wxPython インストーラの不具合)

解決するためには、wxPyhon の再インストールが必要。

最も手っ取り早いのは、wxPython を「Full installation」で入れなおせばよい。

しかしながら、あくまで「Compact installation」相当でインストールしたい場合には、一度「Full installation」を選んでから、不要なチェックボックスを外せばよい。

※以降は、上記 ケースA と同じ。


(余談) 「Compact installation」インストールオプションの不具合について

「Compact installation」インストールオプションを選択すると、なぜか「wxPython modules and library」が OFF かつ 非活性(チェック不可) となる。

気づかずにこのままインストールを進めると、(アンインストーラ以外は)何もインストールされずにインストーラが正常終了する。

OpenCV-Python 動画再生メモ for Windows

※このメモの前提となる環境

  • OpenCV 3.2.0
  • Python 2.7.13 (x64)
  • Windows 7 (Professional) SP1, 64bit

cv2.VideoCapture で mp4ファイル等が再生できない場合の解決方法。

※前提: サンプルデータのaviファイルは再生できること。

  • 原因: OpenCV に同梱されている ffmpegのDLL (opencv_ffmpeg*_*.dll) に、パスが通っていない。 パスを通すか、カレントディレクトリにコピーすることで、ffmpeg が対応している動画であれば、 OpenCV でも開けるようになる。

  • ffmpegのDLL は、「opencv\build\bin」直下 に格納されている。


cv2.VideoCapture で開いている動画のコーデック(FourCC)を特定する方法。

import cv2

def decode_fourcc(v):
  v = int(v)
  return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])

cap = cv2.VideoCapture("input.mp4")
print decode_fourcc(cap.get(cv2.CAP_PROP_FOURCC))
  • FourCC の取得自体は簡単で、cv2.VideoCapture のインスタンス cap に対して
    「cap.get(cv2.CAP_PROP_FOURCC)」 するだけである。

  • ただし、この戻り値は float 値 (FourCC バイト列のint表現をfloat化したもの) になっている。

  • そのため、文字列として FourCC を得るためには、デコードする必要がある。
    FourCC のバイト列をデコードするための API は用意されていないため、上記の「decode_fourcc()」のような関数を自作して対応する。(元ネタ: video_v4l2.py)

  • なお、FourCC をエンコードするための API (ヘルパ関数) は用意されている。
    → cv2.VideoWriter_fourcc(c1,c2,c3,c4)

    使用例: cv2.VideoWriter_fourcc('a', 'v', 'c', '1')

参考: ビデオコーデック に対する FourCC の一覧


画像の寸法 (縦や横方向のピクセル数) を調べる方法。

  • np.ndarray.shape の第1要素が「縦」、第2要素が「横」方向のピクセル数である。

  • 動画のフレーム画像の場合でも、全く同じ。

import cv2
import numpy as np

img = cv2.imread(filename)  # type: np.ndarray
height, width = img.shape[:2]

OpenCV の ドキュメント(APIリファレンス) について

Python で OpenCV をする場合、少し古いかもしれないが、
「Sphinx HTML」の方を参照したほうがよさそう。(2017年6月現在)

※APIリファレンス「以外」の部分、たとえばチュートリアル (OpenCV-Python Tutorials) については、この限りではない。(= 今後も更新されていくと思われる「Doxygen HTML」系統の最新版を見たほうがよい)

Open Live Writer (0.6.2) の実行には、おそらく .NET Framework の 4.6 が必要

総括

Windows 7 環境等で Open Live Writer (0.6.2) がまったく起動しない場合、Microsoft .NET Framework 4.6 をインストールすることで解決できる可能性がある。
※.NET Framework の バージョン4 や バージョン4.5 ではなく、バージョン4.6 が必要。


経緯

Open Live Writer (0.6.2) をインストールしてみたが、まったく起動しなかった。
※起動直後に「OpenLiveWriter.exe は動作を停止しました」(APPCRASH) になる。再現性あり。

上記事象が発生した際の当方のPC環境は、下記の通り。

  • OS: Windows 7 (Professional) SP1, 64bit
  • .NET Framework: バージョン2.0/3.0/3.5/4.5 導入済

Open Live Writer をデバッグしてみた。

  • OpenLiveWriter.ApplicationMain.Main で、「System.MissingMethodException」が発生している。
    ※メソッド「System.Array.Empty()」が見つからない模様。

  • System.Array.Empty(T) メソッド のリファレンス を確認したところ、

    バージョン情報
    .NET Framework
    4.6 以降で使用可能

    との記載があった。

  • Microsoft .NET Framework 4.6 をインストールしたところ、エラーが解消された。


参考リンク

2017年5月13日土曜日

Could not get unknown property 'assembleRelease' for project ':app' of type org.gradle.api.Project.

経緯

Android Plugin for Gradle をバージョンアップ (*1) したところ、これまで通っていたビルドスクリプトが掲題のエラーを出力するようになってしまった。(Sync が通らない)

どうやら、assembleRelease の定義タイミングが変わった(後回しになった)ようである。

build.gradle (Module: app)
assembleRelease << {
  println 'after assembleRelease'
}
Error:(99, 0) Could not get unknown property 'assembleRelease' for project ':app' of type org.gradle.api.Project.

*1 Stack Overflow の question 39590549 によると、プラグインのバージョン 「2.1.3」と「2.2.0」との間で、当該挙動に変更があった模様。


解決方法 その1

assembleRelease が定義された後のコールバック内で、必要な処理を追加する。
※Android Plugin for Gradle の バージョン 2.3.1 (w/ Gradle 3.3) で動作確認済

tasks.whenTaskAdded { task ->
  if (task.name == 'assembleRelease') {
      task.doLast {
        println 'after assembleRelease'
      }
  }
}

解決方法 その2

ビルドスクリプトが一通り評価された後に、必要な処理を追加する。
※Android Plugin for Gradle の バージョン 2.3.1 (w/ Gradle 3.3) で動作確認済

afterEvaluate {
  assembleRelease.doLast {
    println 'after assembleRelease'
  }
}

素朴な疑問

Q.
「task.doLast」や「assembleRelease.doLast」の部分を、これまで通り
「task <<」や「assembleRelease <<」と書いたらだめなのか?

A.
だめではない (= 現状、正常動作する) が、推奨されない。今後は「doLast」を使っていくべき。
理由: 左シフト演算子「<<」 (Task.leftShift(Closure)) は、Gradle のバージョン 5.0 で廃止される予定のため。

The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.

2017年5月8日月曜日

Android の Support Library が、v4 や v7 でも Froyo (API レベル8) を切り捨てていた件 (minSdkVersion 8 の終焉)

総括

Android の Support Library は、「rev. 24.2.0」にて Android 2.2(API レベル 8)以下のサポートを廃止していた。(2016年8月時点)

つまり、「v4 Support Library」も「v7 Support Library」も「android:minSdkVersion="9"」となり、アプリ側が「minSdkVersion 8」だとビルドエラーになる。

※もはや「v4」や「v7」は、それぞれの minSdkVersion を意味しない。

各 Support Library の minSdkVersion
rev. 24.1.1rev. 24.2.0
support-v449
appcompat-v779

リアクション

下記のいずれか。基本は前者。

  • アプリ側も、「minSdkVersion 9」にする。(Froyo をサポートから外す)
    ※2016年8月時点で、Froyo (8) のシェアは 全体の「0.1%」
  • 使用する Support Library のリビジョンを、「24.1.1」以下にする。

情報源

注: リリース 24.2.0 では、Android 2.2(API レベル 8)以下のサポートが削除されました。これらのシステム バージョンだけに機能を提供するクラスやメソッドは廃止予定としてマークされ、使用できなくなります。廃止予定のクラスやメソッドは、今後のリリースで削除される可能性があります。


経緯

久しぶりに Support Library のリビジョンを上げたら、下記のビルドエラーに遭遇。

Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 9 declared in library [com.android.support:support-v4:24.2.0]
Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smaller than version 9 declared in library [com.android.support:appcompat-v7:24.2.0]

参考情報