WP-Syntax使用時、コードの周辺に妙なスペースが発生する

前回に引き続いて、またWP-Syntaxの表示がおかしいです。
シンタックスハイライトしているコードの周辺に妙な隙間ができています。


見るからにcssの問題なので、このタグに対して適用されているスタイルをfirebugで確認します。



どうやら、今使用しているテーマが、tableタグに対してmarginを指定しているのが原因のようです。



使用しているテーマに依存して表示が崩れるのはいただけないので、wp-syntaxのプラグインにあるwp-syntax.cssの以下のスタイルシート定義を以下のように変更します。

.wp_syntax table {
  border-collapse: collapse;
}


 ↓

.wp_syntax table {
  border-collapse: collapse;
  width:100%;
  margin:0px;
}




変更後、再度確認すると…




いい感じに直りました。


※ちなみに、プラグイン内のファイル編集は、以下の記事で説明しています。
 → WordPressのbrBrbrプラグインの振る舞いを確認する

jQueryを使用してtableへ行の追加削除を行う

HTMLをjavascriptから動的に操作する場合、jQueryを使用すると便利です。
本記事では、HTMLの中でも特にtableタグに対して、行の追加・削除を行うためのサンプルを説明します。

単純な追加・削除に加えて、アニメーション処理をつけた場合のサンプルも有ります。


また、本記事の最後に、各処理の動作を確認できるボタンを用意しています。


行の追加


最終行にデータを追加する



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script>
getRowData = function() {
    var sysDate = new Date();
    return '<tr><td>メッセージです</td><td>' + sysDate + '</td></tr>';
}
 
$(document).ready(function(){
    $( "#btnTest11" ).click(function () { 
        // 最後の行に追加
        $('#target').append( getRowData() );
    });
});
</script>
 
<input type="button" id="btnTest11" value="最終行に追加" />
<table id="target">
    <tr>
        <th style="width:200px;">メッセージ</th>
        <th style="width:250px;">登録時刻</th>
    </tr>
</table>



最初の例は、tableタグに行を追加する方法です。

はじめなので各行の内容を詳細に確認していきます。

○1行目
jqueryのライブラリをロードしています。

○4~7行目
追加ボタンの処理でtableタグに追加する行情報を返しています。

○22行目
追加ボタンです。
この例では、ボタンにid”btnTest11″を指定しています。

○23~29行目
追加される対象のテーブルです。
こちらもボタン同様id”target”を指定しています


○14~19行目
追加ボタンがクリックされたときのイベントハンドラです。

大枠は以下の構成になっています。
$( “#btnTest11” ).click( function(){…} );
この記述で、idが”btnTest11″のタグがクリックされたらfunction()の処理が実行されます。

次にfunctionを見ると、以下の処理が記載されています。
$(‘#target’).append( getRowData() );

これは、最初の$(‘#target’)で、行を追加するtableタグを決定しています。
次に、決定したtableに対してappend()で行を追加します。

登録する行データは、先ほど説明したgetRowData()メソッドより受けとっています。





行番号を指定して追加する



1
2
3
4
$( "#btnTest12" ).click(function () { 
    var rowNo = 0;  // 1行目の後に追加
    $( '#target tr' ).eq( rowNo ).after( getRowData() );
});




これ以降は、ボタンクリックの処理だけを記載します。
(クリックのイベントハンドラ以外は、1つ目のサンプルと全て同じです。)

$( ‘#target tr’ ).eq( rowNo )で、指定した行のtrタグを取得できます。
取得したtrタグの後ろに、afterメソッドで行データを追加しています。

rowNoはヘッダ行も含むことと、rowNoの行だけデータが存在しない場合はデータが追加されない事に注意が必要です。




フェードインのアニメーション付き追加する



1
2
3
4
5
6
7
8
9
10
11
$( "#btnTest13" ).click(function () { 
    // 最後の行に追加(アニメーション有)
    $('#target').append( getRowData() );
    $( '#target tr:last' ).hide().fadeIn( 500 );
});
 
$( "#btnTest14" ).click(function () { 
    var rowNo = 0;  // 1行目の後に追加(アニメーション有)
    $( '#target tr' ).eq( rowNo ).after( getRowData() );
    $( '#target tr' ).eq( rowNo+1 ).hide().fadeIn( 500 );
});




最初の2つの例では、行の追加時にどこに行が追加されたかが分かり辛いというデメリットがあります。
この例では、追加された行をフェードインのアニメーション表示させるため、どの行が追加されたが分かりやすいです。

前者の例は最終行、後者の例は指定した行にデータを追加しています。

行っていることは、行を一旦追加した後、対象行を一旦hide()で非表示にした後fadeIn()でフェードインさせています。fadeIn()には引数の指定が可能で、例の場合は500mSecかけてフェードインさせています。また、引数を省略した時は400が指定されたとみなされます。



スライドダウンのアニメーション付き追加する



1
2
3
4
5
6
$( "#btnTest15" ).click(function () { 
    // 最後の行に追加(slideアニメーション有)
    $('#target').append( getRowData() );
    $( '#target tr:last' ).find('td').wrapInner('<div style="display: none;" />');
    $( '#target tr:last' ).find('td > div').slideDown( 500 );
});




今度は新しい行追加時に、スライドさせるアニメーションを行う例です。

サンプルコードを見ると、気持ちとしては$( ‘#target tr:last’ ).hide().slideDown( 500 );と書きたいところでが、残念ながらtdタグはblock要素ではないので直接slideDown()を適用することができません。この為tdの中にダミーのdivを一旦追加し、divをアニメーションさせる形をとります。




行の削除



行を指定して削除する



1
2
3
4
$( "#btnTest21" ).click(function () { 
    var rowNo = 2;  // 3行目を削除
    $( '#target tr' ).eq( rowNo ).remove();
});



行番号を指定して、行を削除します。
最初、最後の行を削除する場合は、$( ‘#target tr’ ).eq( rowNo )の替わりに以下の記述が可能です。

最初の行:
   $( '#target tr:first' ).fadeOut(...
 
最初の行:
   $( '#target tr:last' ).fadeOut(...




フェードアウトのアニメーション付き削除する



1
2
3
4
$( "#btnTest22" ).click(function () { 
    var rowNo = 2;  // 3行目を削除(アニメーション付)
    $( '#target tr' ).eq( rowNo ).fadeOut( 500, function(){$(this).remove();} );
});




フェードアウトのアニメーションつきで行を削除します。
fadeOutは2つ引数をとることができ、第一引数はアニメーション時間(msec)、第二引数がアニメーション終了後の処理内容です。
行の削除はアニメーションが終わった後で実施したいので、第二引数でremove()をコールしています。



全ての行を全削除する



1
2
3
4
$( "#btnTest23" ).click(function () { 
    // ヘッダ以外の全行を削除
    $( '#target' ).find("tr:gt(0)").remove();
});




1行目はヘッダ行なので、.find(“tr:gt(0)”)で2行め以降の全行を抽出し、remove()を行います。
テーブル内の行ではなく、テーブル自体を削除したい場合は、$( ‘#target’ ).remove();で消すことができます。


サンプル

本記事で説明した各処理のサンプルです。
各ボタンを押して、それぞれの処理がどのように動作するかを確認することができます。



メッセージ 登録時刻

WordPressで連載記事を作る

色々な記事をWordPressで書いていると、話題によっては1記事で完結ではなく、複数の記事で連載のような形になることが出てきます。この際、せっかくなので、一連の記事の集まりを1つの連載記事として表現できるようにしたいと思ったりします。

WordPressの機能として、カテゴリやタグで書く記事を紐付けることができたり、静的ページを作成できるのは知っているのですが、これをうまく利用して連載記事っぽく纏められそうな気がします。また、プラグインで同じな事が簡単にできるのであればそれでもOKなので、WordPressの機能だけで構成・プラグインを利用の両面で検討します。


今回は、@ITやcodezineが連載記事を持つサイト構成をしているので、WordPressの機能を調査する前に、まず、@ITのサイト構造やページ構成をチェックしてみます。



目次一覧



まず、各連載の一覧ページがあります。(例:http://www.atmarkit.co.jp/fdotnet/chushin/)ここでは、サイト内の連載一覧が列挙されています。


ここに記載する情報は、以下の5つでした

- 連載名
- 連載のバナー画像
- 最新の記事へのリンク
- 1行での説明(全角で120文字ぐらい??) 
- 各連載へのリンク




幾つかバナーを確認してみましたが、どれも抽象的なイメージを背景に、タイトル(タイトルが長いときは一部だけ)を記載する構成で統一されています。バナーの画像があるだけでかなりイメージが変わるし、特集一覧ページではこの単位でカタマリがあるという印象を与えられるので、ここは結構大事なポイントです。


※@ITのような大きなサイトだと、連載が.Net,Java等のようなくくりでカテゴリ分けされていますが、今回はそこまでは踏み込まないことにしておきます。



連載の目次

次に、特定の連載に対するリンク一覧があります。


各回のタイトルと小見出しの一覧がリンクされていて、本でいうとここが章と節のレベルを列挙した目次的な位置づけになっています。



各記事(ヘッダ)

個別の各記事は共通のヘッダを持っています。


ヘッダには以下の情報が表示されています。

- ソーシャルブックマークへのリンク
- 連載のバナー画像
- 連載のタイトル
- この回のタイトル
- 筆者、作成日
- ページ遷移のリンク




目次と同じバナー画像を使用することで、今自分が見ている場所がさっきと同じことが分かりやすくなっています。
また、この手のサイトの場合、1回の記事が複数ページに分かれるようになっています。
WordPressの場合は1記事で1ページが原則なので、ページ分割はプラグインが必要そうな感じです。


各記事(フッタ)

記事のフッタには、自記事のページネーションと、前述した連載内の記事一覧へのリンクが有ります。




各記事(ヘッダ,2ページ目以降)

2ページ目以降のヘッダはバナー画像が小さくなっています。
小さな違いですが、これで今自分が最初のページに居るかが分かりやすくなっています。






バナー画像を、試しに作ってみた。

@ITにある各連載のバナーを見てみたけど、それほど凝った画像では無さそうな感じです。

なので、Paint.Netを使用して、試しに自サイト用のバナーを作ってみました。

下記の連載のためのバナーです。

C#でmarkdown記法を使用する

  1. C#のmarkdownライブラリ,MarkdownSharpを使用する
  2. markdown.dllを使用したプログラムを作成する
  3. MarkdownSharp.dllの変換結果をブラウザ表示結果としてプレビューする
  4. BackgroundWorkerで、markdownのプレビュー処理を改善


WordPressのver3.2は、各記事に対してアイキャッチ画像が指定できるので、ここから登録できるようにできるとbestな感じがします。

Paint.Netのpdnファイルも置いときます。
Download: csharp_with_markdown.zip








VisualStudioの出力ウィンドウを色分け表示させる方法




Visual Studioのプラグイン、VSColorOutputを使用すると、IDEでアウトプットウィンドに出力されるビルド時の出力やデバッグ出力を色分けして表示してくれます。これをインストールすると、デバッグ実行時に自分がチェックしたいトレースメッセージをすばやくチェックすることができます。

VSColorOutputは、codeplex.comで配布してされており、VisualStudioの2010と2011をサポートしています。


インストール


下記のURLより、VSColorOutput.vsixをダウンロードします。
http://vscoloroutput.codeplex.com/releases/view/79354


ダウンロードしたファイルをダブルクリックします。



ダイアログが表示されるので、インストールボタンをクリックします。





動作


System.Diagnostics.Debug.PrintやSystem.Console.WriteLineで、error,warning,information等を含む文字列を出力させます。
すると、出力ウィンドウ上で、以下のように色分けして出力してくれます。

System.Console.WriteLine( "information : 情報です" );
System.Console.WriteLine( "warning     : 警告です" );
System.Console.WriteLine( "error       : エラーが発生しました" );







また、コンパイル結果も自動で色分けしてくれます。




カスタマイズ


ツール→オプションのウィンドウから色分け表示させるパターンを正規表現で指定可能です。




プラグインのソース

Apache Licenseによるオープンソースプロジェクトですので、ソースも入手可能です。
http://vscoloroutput.codeplex.com/SourceControl/list/changesets



ダウンロード

VSColorOutputは、以下のサイトよりダウンロードできます。
Download: VSColorOutput



WP_SyntaxとbrBrbrを併用時、余計なスペースが入るのを抑制

前回、brBrbrのプラグインをチェックしたのですが、問題無さそうなうでした。
ですので、今回はWP_Syntax側のソースをチェックします。


まず、brBrbrの時と同様にソースを確認します。WP_Syntaxは、全7ファイルで構成されています。
それぞれのファイルをざっとチェックしてみましたが、メインはwp-syntax.phpのようです。



で、wp-syntax.phpですが、brBrbrと違ってこっちは200行ぐらいソースが有ります。




200行ぐらいなら頭から読んでも良いのですが、面倒なのであたりをつけます。
preタグの前後に改行が2づつ付くという状況は既に把握済みなので、”\n\n”で検索するとそれっぽいのが出てきました!!

function wp_syntax_substitute(&$match)
{
    global $wp_syntax_token, $wp_syntax_matches;
 
    $i = count($wp_syntax_matches);
    $wp_syntax_matches[$i] = $match;
 
    return "\n\n<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>\n\n";
}



まさに、前後に改行を2つづつ付与しています。



これを、を試しに以下のように変更して試してみます。

    return "\n\n<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>\n\n";return "st<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>ed";


出力結果を比べると、以下のように期待した感じになりました。
(画像中の start /waitの箇所がシンタックスハイライトの処理対象になっています。)


      ↓
    



結局、修正箇所は…

というわけで…
WP_SyntaxとbrBrbr併用時に、余計なスペースが入るのを防ぐ為のパッチです。


wp_syntaxプラグイン内の、wp_syntax_substitute()メソッドを以下のように修正します。
(最後の1行のreturnを書き換えるだけです)

function wp_syntax_substitute(&$match)
{
    global $wp_syntax_token, $wp_syntax_matches;
 
    $i = count($wp_syntax_matches);
    $wp_syntax_matches[$i] = $match;
 
    /* 2012/01: brBrbrプラグイン併用時の余計な空行を取り除く */
    /* return "\n\n<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>\n\n"; */
    return "<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>";
}



WordPressのbrBrbrプラグインの振る舞いを確認する

本blogはWordPressを使用して構築しているのですが、その中でWP-SyntaxとbrBrbrのプラグインを使用しています。

しばらく使っていて気づいたのですが、どうやら上記2つのプラグインを同時に使用すると、シンタックスハイライトさせたコードの下に無駄なスペース(brタグ)2行ほど出てしまうらしく、出力結果の見た目がかっこ悪くなってしまいます。

で、この問題を解消したいので、プラグインの勉強を兼ねてbrBrbrの処理内容をチェックしてみました。


プラグインのソースを表示させる

プラグイン内のソースチェックは、ファイルを直接開く必要があるのかと思っていたのですが、調べてみるとWordPressの管理画面から直接確認や編集を行うことができました。

管理者ページの左メニューから、プラグイン→プラグイン編集を選択します。


その後、画面右上のコンボボックスから、確認したいプラグイン(今回はbrBrbr)を選択すると、ソースが確認できます。




brBrbrプラグインのソースを読む


ソースは以下のとおり、30行程度です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
Plugin Name:brBrbr
Plugin URI:http://camcam.info/wordpress/101/
Description:Line feed is converted to &lt;br /&gt;.
Version:2.0
Author:CamCam
Author URI:http://camcam.info/
*/
 
remove_filter('the_content','wpautop');
add_filter('the_content','brBrbr');
 
 
remove_filter('comment_text', 'wpautop', 30);
add_filter('comment_text','brBrbr',30);
 
function brBrbr($brbr) {
	$brbr = str_replace(array("\r\n", "\r"), "\n", $brbr); // cross-platform newlines 
	$brbr = str_replace("\n", "<br />\n", $brbr); // cross-platform newlines 
	$brbr = preg_replace('!(</?(?:table|img|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|textarea|input|blockquote|address|p|math|script|h[1-6])[^>]*>)\s*<br />!', "$1", $brbr);
	$brbr = preg_replace('|<blockquote([^>]*)>|i', "</p>\n<blockquote$1><p>", $brbr);
	$brbr = str_replace('</blockquote>', "</p></blockquote>\n<p>", $brbr);
	$brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/ise', "clr_br('$0')", $brbr);
	$brbr="<p>\n".$brbr."</p>\n";
	return $brbr; 
}
 
 
function clr_br($str){
	$str  = str_replace("<br />","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
}



ぱっと見で分かるように、brBrbr()関数だけ押さえればOKなので、この関数内の各処理で何を行っているかチェックしました。以下にコメントの形で処理内容を記述します。

function brBrbr($brbr) {
    //--------------------------------------------------------------------------
    // \r\nや、\rを\nに置換します。
    // これはクライアント環境によって改行文字が"CRLF,LFのみCRのみ"と
    // 混在しているのを、全て\nへ正規化するのが目的です。
    //--------------------------------------------------------------------------
    $brbr = str_replace(array("\r\n", "\r"), "\n", $brbr); // cross-platform newlines 
 
    //--------------------------------------------------------------------------
    // 正規化された改行文字を、一旦全部brタグに変換します。
    //--------------------------------------------------------------------------
    $brbr = str_replace("\n", "<br />\n", $brbr); // cross-platform newlines 
 
    //--------------------------------------------------------------------------
    // ここに列挙されたタグの後にあるbrタグは除去します。
    // (これらのタグの後にある改行は改行文字のままにしておきたいので)
    //--------------------------------------------------------------------------
    $brbr = preg_replace('!(</?(?:table|img|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|textarea|input|blockquote|address|p|math|script|h[1-6])[^>]*>)\s*<br />!', "$1", $brbr);
 
 
    //--------------------------------------------------------------------------
    // blockquoteタグが出てきたときは、blockquoteの中全体をpタグで括ります。
    //--------------------------------------------------------------------------
    $brbr = preg_replace('|<blockquote([^>]*)>|i', "</p>\n<blockquote$1><p>", $brbr);
    $brbr = str_replace('</blockquote>', "</p></blockquote>\n<p>", $brbr);
 
    //--------------------------------------------------------------------------
    // pre,script,formタグの中にある改行はそのまま保持したいので、br->改行に戻します。
    //--------------------------------------------------------------------------
    $brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/ise', "clr_br('$0')", $brbr);
    $brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/ise', "clr_br('$0')", $brbr);
    $brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/ise', "clr_br('$0')", $brbr);
 
    //--------------------------------------------------------------------------
    //置換後の文字列全体を,pタグで括ります。
    //--------------------------------------------------------------------------
    $brbr="<p>\n".$brbr."</p>\n";
    return $brbr; 
}





brBrbrプラグインは無罪っぽい…

元々の問題だったWP-SyntaxとbrBrbr混在時の不具合ですが、brBrbrのソースを見る限りこちらの問題ではなさそうです…

おそらく、WP-Syntaxがpreタグを置換する際、置換後文字列に空行を無駄に入れているような雰囲気です。



msiパッケージをmsiexec.exeで展開する

インストーラでよく拡張子がmsiのファイルが使用されています。
これは、”MicroSoft windows Installer”の略でWindows標準のインストーラパッケージです。

通常ソフトをインストールする際は、このファイルをダブルクリックして実行すれば問題ないのですが、インストールは行いたくないけどパッケージに入っているファイルだけ入手したいと言う場合があります。

このような場合は、Windowsに標準インストールされているmsiexec.exeコマンドを使用することでファイルの抽出のみを行うことが可能です。



msiパッケージから,ファイルの抽出だけを行うコマンド


以下のコマンドで、ファイルの抽出だけを行うことが可能です。

start /wait msiexec.exe /a xxx.msi targetdir="c:\dest\dir" /qn  /li "c:\work\install.log"


次に、コマンド内の各オプションを説明します。




start /wait


“start /wait”は、後続のコマンド”msiexec.exe …”が終了するまで,次のコマンドを待たせる処理です。
このコマンドを書かずにいきなりmsiexec.exeから初めてもファイルの抽出は行えるのですが、msiexecコマンドは子プロセスにファイルの展開が行わせ、自分はすぐに処理を終了してしまうため、プロンプトが戻ってきた時点では全ファイルの展開が完了していない場合があります。
ファイルの展開漏れをなくすために、本コマンドを最初に書きます。

※start /waitに関しては,Heath Stewartが書いた以下の記事が詳しいです。
http://blogs.msdn.com/b/heaths/archive/2005/11/15/493236.aspx




msiexec.exe


msiexecはWindowsに標準で入っているインストーラコマンドです。




/a xxx.msi


/aオプションで、msiexecが展開を行うmsiファイルを指定します。




targetdir="c:\dest\dir"


targetdirで、展開したファイルの保存先を指定します。
msiファイルが存在するフォルダを指定すると、正常に展開できないので注意してください。




/qn


/qnは、画面にインストーラのダイアログを出さずに、非対話で処理を行うことを意味します。
このオプションを指定することで、コマンドラインのみでファイルの抽出が行えます。




/li "c:\work\install.log"


このオプションは必須ではないのですが…、/lはファイルの展開結果をログファイルに落とします。
/lの後にあるiはログ出力の粒度を表していて、iは情報(info)ログを出力します。
通常はこのレベルで十分ですが、より詳細なログを確認したい場合は、/lvにすると詳細なログ(verbose)の出力が行われます。




msiexec.exeのオプション一覧


コマンドラインより、以下のコマンドを実行するとオプション一覧が表示されます。

msiexec /?




windows7上で実行したオプション一覧のヘルプです

Windows R インストーラー. V 5.0.7601.17514 
 
msiexec /Option <必須パラメーター> [省略可能なパラメーター]
 
インストール オプション
	</package | /i> <Product.msi>
		製品をインストールまたは構成します。
	/a <Product.msi>
		管理用ツール - ネットワーク上の製品をインストールします。
	/j<u|m> <Product.msi> [/t <変換一覧>] [/g <言語 ID>]
		製品をアドバタイズします - すべてのユーザーには m、現在の
		ユーザーには u を指定します。
	</uninstall | /x> <Product.msi | 製品コード>
		製品をアンインストールします。
表示オプション
	/quiet
		Quiet モード - ユーザーの操作なし
	/passive
		無人モード - 進行状況バーのみ
	/q[n|b|r|f]
		ユーザー インターフェイスのレベルを設定します。
		n - なし
		b - 基本
		r - 簡易
		f - 完全 (既定)
	/help
		ヘルプ情報
再起動オプション
	/norestart
		インストール完了後に再起動しません。
	/promptrestart
		再起動が必要な場合は、ユーザーに再起動を要求します。
	/forcerestart
		常に、インストール後コンピューターを再起動します。
ログ オプション
	/l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>
		i - 状態メッセージ
		w - 致命的ではない警告
		e - すべてのエラー メッセージ
		a - 操作のスタートアップ 
		r - 特定の操作の記録
		u - ユーザーの要求
		c - UI パラメーターの初期値
		m - メモリ不足または致命的な終了に関する情報
		o - ディスク領域不足メッセージ
		p - ターミナルのプロパティ
		v - 詳細出力
		x - 詳細デバッグ情報
		+ - 既存のログ ファイルに追加
		! - 各行をログにフラッシュ
		* - v オプションと x オプションを除くすべての情報をログに記録します。
	/log <ログ ファイル>
		/l* <ログ ファイル> と指定したときと同じ情報がログに記録されます。
 
更新オプション
	/update <Update1.msp>[;Update2.msp]
		更新を適用します。
	/uninstall <修正プログラム コード GUID>[;Update2.msp] 
	/package <Product.msi | 製品コード>
		製品の更新を削除します。
修復オプション
	/f[p|e|c|m|s|o|d|a|u|v] <Product.msi | 製品コード>
		製品を修復します。
		p - ファイルが見つからない場合のみ
		o - ファイルが見つからない、または古いバージョンが
		    インストールされている場合 (既定)
		e - ファイルが見つからない、同じバージョンまたは古い
		    バージョンがインストールされている場合
		d - ファイルが見つからない、または違うバージョンが
		    インストールされている場合
		c - ファイルが見つからない、またはチェックサムと計算
		    された値が一致しない場合
		a - すべてのファイルをインストールする
		u - すべてのユーザー固有の必須レジストリ エントリ (既定)
		m - すべてコンピューター固有の必須レジストリ エントリ (既定)
		s - すべての既存のショートカット (既定)
		v - ソースから実行して、パッケージをローカルに再キャッシュする
パブリック プロパティの設定
	[PROPERTY=プロパティ値]
 
コマンド ラインの構文の詳細については、Windows (R) インストーラー SDK を参照してください。
 
Copyright (C) Microsoft Corporation. All rights reserved.
Portions of this software are based in part on the work of the Independent JPEG Group.



参考資料


Microsoft Windows インストーラ ツール Msiexec.exe のコマンドライン オプション
http://support.microsoft.com/kb/314881/ja


msiexec.exe コマンド実行時、ファイルの展開が終了するまで待たせる
http://blogs.msdn.com/b/heaths/archive/2005/11/15/493236.aspx

Windows Installer 4.5の再配布URL
http://www.microsoft.com/downloads/ja-jp/details.aspx?displaylang=ja&FamilyID=5a58b56f-60b6-4412-95b9-54d056d6f9f4

MarkdownSharpのクラス仕様

doxygenを使用してドキュメントの作成を行ったので、コレをもとにMarkdownSharpの機能を確認します。


ドキュメントは、以下のリンクより参照できます。
MarkdownSharpクラス仕様


クラス構成


前回確認したとおり、実質的にMarkdownSharpは、MarkdownクラスとMarkdownOptionsクラスの2つで構成されています。


Markdownクラス


メソッド


まずメソッド一覧を確認します。


  • Markdown ()
  • Markdown (bool loadOptionsFromConfigFile)
  • Markdown (MarkdownOptions options)
  • string Transform (string text)

コンストラクタが3つと、実際の変換関数が1つの計4つしかありません。
非常にシンプルな構成ですね。
各メソッドの内容は、以下のとおりです。


Markdown()


デフォルトコンストラクタです
Markdownクラスのインスタンスをデフォルトのオプション構成で生成します。


Markdown (bool loadOptionsFromConfigFile)


Markdownクラスのインスタンスを、設定ファイルを元に生成することができます。
設定ファイルからの読み込みは、引数をtrueにしたときのみ有効になるので、new Markdown(false)は、new Markdown()と等価です。


設定はappSettings(app.config)に、以下のキーで登録しておきます。
各パラメータの意味は、後述のプロパティを参照してください。


Markdown.StrictBoldItalic           (true/false) 
Markdown.EmptyElementSuffix         (">" or " />" を、ダブルクォーテーション無しで記載) 
Markdown.LinkEmails                 (true/false) 
Markdown.AutoNewLines               (true/false) 
Markdown.AutoHyperlink              (true/false) 
Markdown.EncodeProblemUrlCharacters (true/false)



Markdown (MarkdownOptions options)


MarkdownOptionsオブジェクトで定義したオプションで、Markdownクラスのインスタンスを生成します。


string Transform (string text)


実際にMarkdown形式のテキストをhtmlに変換する処理です。
Markdown形式の構文は、wikipediaに記載されています。


呼び元側で行われるエスケープ処理など、他のサブルーチンが呼び順は重要です。
aタグとimgタグに含まれる、任意の”*”や”_”はエンコードされるので、リンクと画像の置換はEscapeSpecialChars()の前に発生する必要があります。


プロパティ


プロパティは、7つあります。
その内、最初の6つはコンストラクタで指定可能な情報です。


string EmptyElementSuffix         [get, set]
bool   LinkEmails                 [get, set]
bool   StrictBoldItalic           [get, set]
bool   AutoNewLines               [get, set]
bool   AutoHyperlink              [get, set]
bool   EncodeProblemUrlCharacters [get, set]
string Version                    [get]



string EmptyElementSuffix

空タグの終了文字を指定します。
一般的に、HTMLを出力する場合は、”>”で、XHTMLの場合は ” />”を指定します。


空タグと言うのは、brやhrのように、開きと閉じがペアになってなっておらず、単独で意味をなすタグのことです。xhtmlの場合はxml文法に準拠する必要があるので”<br>”ではなく”<br />”と書く必要があるのですが、ここでどちらの出力を行うかを指定できます。

デフォルト値は” />”です。


bool LinkEmails

falseにすると、テキスト中にemailの文字列があるときでも、自動でmailtoのリンクを生成しません。

注意:falseにするとは通常のmarkdown仕様とは異なる振る舞いとなり、デフォルトはtrueです。


bool StrictBoldItalic

trueにすると、ボールドとイタリックの変換に対して、どちらかの側の非単語の文字を必要とします。


例えばboldの場合、本プロパティをfalseにすると…


  マッチングルール: (\*\*|__) (?=\S) (.+?[*_]*) (?<=\S) \1
  置換のかけ方    : <strong>$2</strong>


となり、trueだと以下のようになります。

  マッチングルール: ([\W_]|^) (\*\*|__) (?=\S) ([^\r]*?\S[\*_]*) \2 ([\W_]|$)
  置換のかけ方    : $1<strong>$3</strong>$4


(markdownでは、2つの”*”か”_”で囲まれた中の文字列をboldにします)

注意:trueにするとは通常のmarkdown仕様とは異なる振る舞いとなり、デフォルトはfalseです。



bool AutoNewLines

trueにすると、テキスト上に改行文字がある場合、出力されたhtmlでも改行を行います。

注意:trueにするとは通常のmarkdown仕様とは異なる振る舞いとなり、デフォルトはfalseです。



bool AutoHyperlink

trueにすると、テキスト上に記載されたURLに対して、aタグによるリンクを自動生成します。

注意:trueにするとは通常のmarkdown仕様とは異なる振る舞いとなり、デフォルトはfalseです。


bool EncodeProblemUrlCharacters

trueにすると、URL中に「 ” ‘ * ( ) [ ] $ : 」の文字列があった場合、%xxの形式にエンコードします。

注意:trueにするとは通常のmarkdown仕様とは異なる振る舞いとなり、デフォルトはfalseです。


string Version

使用しているMarkdownのバージョンを返します。
例えばver1.13の場合、”1.13″という文字列が返ってきます。

また、http://code.google.com/p/markdownsharp/ で最新版のソースが入手できます。


MarkdownOptionクラス

Markdownのコンストラクタに渡すためのコンテナです。
本クラスの状態は変更不可(immutable)なので、newした後にプロパティ値を変更したい場合は、別途新しいインスタンスをnewする必要があります。





MarkdownOptionメソッド

こちらは、3つのコンストラクタが有ります。

  • MarkdownOptions ()
  • MarkdownOptions (bool loadFromConfigFile)
  • MarkdownOptions (bool autoHyperlink, bool autoNewlines, string emptyElementsSuffix, bool encodeProblemUrlCharacters, bool linkEmails, int nestDepth, bool strictBoldItalic, int tabWidth)


MarkdownOptions ()

デフォルトコンストラクタです。
システムのデフォルトパラメータを元にオプション定義を生成します。
デフォルト値は、標準のmarkdown仕様と互換性があるものとなっています。


MarkdownOptions (bool loadFromConfigFile)


loadFromConfigFileパラメータをtrueにすると、app.configの定義内容を元にオプション情報をセットします。
app.configに記載するKey,valueの値は、前述したMarkdownクラスのコンストラクタを参照してください。


loadFromConfigFileパラメータfalseの場合は、new MarkdownOptions()と同じ処理を行います。


MarkdownOptions (bool autoHyperlink, bool autoNewlines, string emptyElementsSuffix, bool encodeProblemUrlCharacters, bool linkEmails, int nestDepth, bool strictBoldItalic, int tabWidth)


全てのパラメータを明示的に引数で指定して、オブジェクトを生成します。
NestDepthとTabWidthのパラメータはMarkdownクラス側で見ていないので、何を指定しても意味が無いようです。


MarkdownOptionプロパティ


以下のプロパティを参照可能です。(セットすることはできません)
各パラメータの意味は、前述のMarkdownクラスの各パラメータを参照してください。


bool    AutoHyperlink
bool    AutoNewlines 
string  EmptyElementSuffix
bool    EncodeProblemUrlCharacters
bool    LinkEmails
bool    StrictBoldItalic
int     NestDepth
int     TabWidth


doxygenを使用してC#のドキュメントを自動生成する(その3)

今回は、前回までで説明できなかった細かな体裁の変更を行います。


latex用データの出力を抑制する


GENERATE_LATEX         = NO


windows環境だと、通常latex形式での出力を行っても使用しないため、出力を行いません。

本パラメータをNOにすると、ドキュメント生成の時間が若干速くなります。
※ドキュメントをpdfで出力したい場合は、latex形式で出力後latex→pdfに変換を行うことができます。



説明文を日本語にする


OUTPUT_LANGUAGE        = Japanese


doxygenが出力するドキュメントはデフォルトで英語です。
文章自体は簡単なものばかりなので、英語でも問題ないのですが、気になる場合は日本語化することもできます。

変更前

    ↓
変更後



プロジェクト名を指定する


PROJECT_NAME           = "MarkdownSharp"



画面右上に表示されているプロジェクト名を変更できます

変更前

    ↓
変更後



また、PROJECT_NUMBERを変更することで、プロジェクトのバージョンも併記可能です。

PROJECT_NUMBER         = 1.0






クラスの情報サマリー表示


BRIEF_MEMBER_DESC      = NO


各クラスの先頭には、メソッドやプロパティの一覧が表示されますが、ここに出ている1行コメントの出力を抑制できます


変更前

    ↓
変更後




タブストップ


TAB_SIZE               = 4



ソースコード中にTAB文字があった場合のインデント幅です。





背景色


HTML_COLORSTYLE_HUE    = 220
HTML_COLORSTYLE_SAT    = 100
HTML_COLORSTYLE_GAMMA  = 80



どうでもいい機能ですが…。色も変更可能です。
例えばHUE(色相)を320に変更すると、以下のように紫っぽくなります。




呼び出しグラフ等の付加情報を折りたたむ


HTML_DYNAMIC_SECTIONS  = YES



呼び出しグラフはあまり見ないから邪魔だけど、時々見たいこともある。と言った場合に、折りたたんでおくことができます。


クリックするとグラフが表示されます。




グラフ中の、呼び出し階層の最大数を抑制


MAX_DOT_GRAPH_DEPTH    = 3


デフォルトでは最大50階層ですが、詳しすぎてもかえって見づらいので、3階層くらいにしておきます。

変更前

     ↓
変更後




htmlのヘッダ、フッタ領域をカスタマイズする


HTML_FOOTER            = footer.html
※HTML_HEADER,HTML_STYLESHEETも同様



必要があれば、全てのページに対して共通の情報を差し込むことができます。
例えば、以下のように定義した上で、doxygen.exeのあるフォルダにfooter.htmlにファイルを置きます。


footer.htmlを作っておくと…


ページ下部に表示される。



一通り設定完了後のドキュメント

ここまでの設定を行ったドキュメントです。
markdown1.12 document

ヤマト伝票番号の最終桁を求める計算式(CheckDigit)

ヤマト運輸の伝票は12桁ですが、最後の1桁がチェックデジットになっています。

チェックデジットの算出ルールは単純で、残りの桁を7で割った剰余(mod-7)です。
この計算式は、7DRチェック形式とも呼ばれています。

例えば”1234-5678-901?”の場合は、12345678901 ÷ 7 = 商:1763668414、 余り:3
ですので、この場合のCheckDigitは3です。

せっかく調べたので、チェックデジット(C/D)の算出ツールを作成してみました。
※テストボタンをクリックすると、上記例の伝票番号で計算します→

1伝票のみ

伝票番号11桁

C/D付き伝票No


複数伝票(1行に1つの伝票番号を入力してください

伝票番号11桁


C/D付き伝票No



伝票範囲指定

伝票番号11桁


C/D付き伝票No

doxygenを使用してC#のドキュメントを自動生成する(その2)

前回の記事で、C#のソースコードからドキュメントの自動生成が出来るようになりました。
今回は、ソース内のクラス階層や、関数の呼び出し関係を可視化する為にグラフ(画像)を表示できるようにします。


こんな感じで、どの関数が、どの関数をコールしているかを一目で分かるようにするのが目的です。




doxygenがグラフを生成する仕組み


doxygenは、自力でグラフ画像の生成することは出来ず、graphvizというソフトを利用しています。
graphvizは、AT&Tが開発したオープンソース(Common Public License ライセンス)のソフトウェアで、テキスト形式の設定ファイルより、以下のような画像を生成することが出来ます。




graphvizのセットアップを行う


まずは、準備としてgraphvizのセットアップを行い、単体で動作することを確認します。


下記のサイトへアクセスします。
http://www.graphviz.org/


画面左のdownloadをクリックします。



Executable Packageの下にある、リンクよりダウンロードを行います。





ダウンロードが出来たらセットアップを行います。
公式サイトからは、msiイメージのみがダウンロードできるので、通常だとインストールが必要です。


今回は、exeだけ入手できれば良いので、以下のコマンドでmsiパッケージからファイルの抽出を行います。
※下記の例では、c:\workにあるmsiファイルを、c:\work\extractに展開しています(途中で折り返していますが、実際は1行で記入します)


start /wait msiexec /a c:\work\graphviz-2.28.0.msi targetdir="c:\work\extract" /qn 
/li "c:\work\install.log"




インストーラからセットアップしたい場合は、ダウンロードしたgraphviz-x.xx.msiを実行します。
以下のようにインストール先を聞かれるだけなので、セットアップ自体は簡単です。


  ↓

  ↓



フォルダ構成は、こんな感じです。



ファイルを展開したら、上記のファイル達を、doxygen.exeのあるフォルダにコピーしてしまいます。
(この作業は必須では有りませんが、1つのフォルダに纏めておくとUSBメモリなどで持ち運ぶ際に便利です)




無事graphvizがセットアップできたら、動作確認を行います。
エディタでテスト用のファイルを作成して…


graph graphname {
    a -- b -- c;
    b -- d;
}


コマンドプロンプトよりグラフを作成します。

  <p>bin\dot.exe -Tjpg test.txt -o test.jpg</p>





test.jpgが生成されていればOKです。





doxygenでgraphvizを使用する


次に、doxygenでgraphvizを使用できるようにします。graphviz用の設定は、Doxyfileを編集します。


以下の設定内容を…

HAVE_DOT               = NO
DOT_PATH               =
SOURCE_BROWSER         = NO
CALL_GRAPH             = NO
CALLER_GRAPH           = NO


このように変更します。

HAVE_DOT               = YES
DOT_PATH               = .\graphviz\bin\
SOURCE_BROWSER         = YES
CALL_GRAPH             = YES
CALLER_GRAPH           = YES



各パラメータの意味は以下のとおりです。


HAVE_DOT       : dot(graphvizに入っているコマンドdot.exe)を使用するか
DOT_PATH       : dot.exeのある場所
SOURCE_BROWSER : ドキュメントからソースへのリンクを付与するか
CALL_GRAPH     : 呼び出しグラフ(自分が誰をcallしているか)を表示するか
CALLER_GRAPH   : 呼び出されグラフ(誰から自分がcallしているか)を表示するか



上記の内、SOURCE_BROWSERはグラフ表示と直接関係ないのですが、SOURCE_BROWSERをYESにしておかないと画像が出力されないようなのでYESにしてます。


ここまで設定したら、再度doxygen.exeを実行します。



実行後、ドキュメントを確認すると…、なぜか画像が出来ていません



htmlフォルダの中を確認してみると、graph_legend.htmlというファイルが追加で作成されています。
graph_legendのファイルは、文字通りグラフの凡例なので、どうやらHAVE_DOTの定義自体は認識されているようです。


htmlの中身。



ここで、なぜ画像が生成されないのか、小一時間悩んだのですが… どうやら今回対象としたMarkdownSharpは、クラス数・コードの構造がシンプルすぎで表示すべきグラフがまったく無かったという凡ミスでした。


ですので、今回は確認のために以下のパラメータを追加で変更しました。


EXTRACT_PRIVATE        = NO
 ↓
EXTRACT_PRIVATE        = YES



EXTRACT_PRIVATEは、プライベートなメソッドの情報をドキュメント生成するかのフラグです。他から利用するライブラリ等のドキュメントを生成する場合は、privateなメソッド情報は不要なのでNOのままの方が分かりやすいのですが、ライブラリ自体の解析をしたい場合はYESしておくと便利なパラメータです。


改めて、doxygen.exeを実行します。なにやらグラフが生成されてそうなログが出力されました。




クラスのドキュメントを確認すると…、無事呼び出しグラフが出力されました!!
(画像が横長すぎて画面からはみ出てますが…この辺は次回調整します)



今回は以上です。
次回は、細かな見た目の改善を行います。

PT2+tvtestで録画時、解像度が320×180になってしまう場合の対処法

PT2で録画した番組を再生したら、解像度が低い番組がありました。
Media Player Classicで実行すると、以下のように320×180で、fpsも15しかありません。

Media Type 0:
--------------------------
Video: MPEG4 Video (H264) 320x180 14.99fps



これは、チューナがフルセグとワンセグの両方を放送波として受信しているのですが、ワンセグ側を録画してしまっているのが原因です。

tvtest.exeの設定を変更すれば、フルセグ側を録画してくれるようになります。


まずは、tvtest.exeを起動し、適当な場所で右クリックし、設定を選択します。


設定画面より、録画→現在のサービスのみを保存するにチェックを入れます。


これで、フルセグ側の高解像度な動画が、録画されるようになります。


Oracleサーバ上に、SQLの実行履歴を落とす方法

下記の手順で、発行されたSQLとバインド変数のログが出力可能です。
各手順の背景を細かく説明すると長いので、要点だけのメモです。

1.SQLのトレースログを落とす(コのコマンドを実行したセッションに限り有効
    ALTER SESSION SET EVENTS '10046 trace name context forever, level 4';
 
2.適当に何かSQLを実行する
    SELECT * FROM TAB;
 
3.トレースファイルの落ちるディレクトリを調べる。
  (環境によって、user_dump_destかbackground_dump_destのどちらかに落ちる
    select * from v$parameter where name in ( 'user_dump_dest', 'background_dump_dest' );
 
 
4.上記フォルダにトレースログがあることを確認する。
  (複数ある場合はタイムスタンプで判断)
    ORA99999.TRCみたいな感じのファイルになるはず。
 
5.SQLの確認が終わったら、上記1.のSQLを"level 0"で実行しておき、トレースの出力をやめる。

doxygenを使用してC#のドキュメントを自動生成する(その1)

C#では、通常の”/* */”や “//”によるコメントに加えて、”///”で始まるコメントで、XML形式のドキュメントコメントを記述することが出来ます。

具体的な例としては、下記ソースのsummary,paramや、returns等が相当します。

//***************************************************************************
/// <summary> 指定されたファイルを読み込む
/// </summary>
/// <param name="fileName">ファイル名</param>
/// <returns>ファイルの内容</returns>
//***************************************************************************
private String GetText( String fileName ) {
    try {
        using ( StreamReader reader = new StreamReader( fileName, Encoding.GetEncoding( 932 ) ) ) {
            return reader.ReadToEnd();
        }
    } catch ( Exception ex ) {
        Console.WriteLine( ex.Message );
        return "";
    }
}


今回は、doxygenというオープンソースソフトウェアを使用することで、上記コメントを元にしたプログラムのドキュメントを自動生成させます。


一旦実行してみる


以下のサイトより、doxygen本体をダウンロードします
2012/01時点での最新はver1.7.6でした。
http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc




ダウンロードしたzipを展開すると、doxygen.exeが入っています。
コマンドラインのプログラムなので、一旦実行してみるとエラーが出てしまいました。
(1行目の、”Doxyfile not found and no input file specified!”)
これは設定ファイルが無いためです。




設定ファイルが必要となるのですが、親切なことに雛形をdoxygen.exe自身で作成することが可能です。
先ほどのエラーメッセージを見るとdoxygen.exe -gで作成できるらしいのでその通りに実行します。
コマンド実行後、Doxyconfというファイルがある事を確認してください。




生成後、再度doxygen.exeを実行すると、なにやら処理が走りドキュメントの生成処理が行われます。




処理完了後、exeがあるフォルダを確認するとhtml/latexフォルダが出来ています。
latexというのは、unix系のOSで使用されれるドキュメント形式です。
今回はwindows環境で、html形式が参照できれば十分なので、htmlフォルダだけ確認します。




htmlフォルダの中には幾つかのファイルが出来ています。その中のindex.htmlを開くと、ドキュメントのトップページが表示されます。
今は、まだドキュメント生成を行う対象ファイルを指定していないため、当然ながら中身は空っぽです。




C#ソースのドキュメントを生成させてみる。


次にC#のソースコードよりドキュメントを自動生成させてみます。
自動生成させるプログラムは、前回触ってみたMarkdownSharpにします。


今回は説明のため、ソースをdoxygen.exeがあるフォルダにsrc\を作成し、その下に配置します。
(実際はどこに置いてあっても構いません)



srcフォルダの直下に*.csファイルが置いてあります。




ファイルを置いたら、ソースのありかをdoxygen.exeに伝える必要が有ります。
その方法ですが、先ほど生成した設定ファイル(Doxyfile)にフォルダを記載します。


ファイル内を見ると、以下のような記述があるので…


#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
 
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
 
INPUT                  =



以下のように、src以下を見るように指示します。


INPUT                  = .\src




上記の変更を行ったら、再度doxygen.exeを実行します。
コマンドの出力内容を見ると、先ほど設置したソースを認識している事が分かります。




再度html\index.htmlファイルを開いています。
今度は、MainPageの横にNamespaces, Classesのリンクが出来ています。




Classesをクリックすると、クラス一覧が表示されます。
ここからドキュメントを確認したいクラスを選択します。




クラスをクリックすると、クラスが持っているメソッド(メンバ関数)や、プロパティなどが確認できます。
(今回はMarkdownSharp.Markdownを選択しました)




メソッドをクリックすると、各メソッドの詳細な説明が表示されます。




たったこれだけで、C#のソースからhtmlドキュメントを自動生成することが出来ました。


まとめ


C#のドキュメントは、以下の4ステップで自動生成させることが出来ます。


  1. http://www.stack.nl/~dimitri/doxygen/download.htmlからdoxygen.exeを入手
  2. “doxygen.exe -g”で、設定ファイル(Doxyfile)の雛形を作る
  3. Doxyfileをエディタで開き、”INPUT =”の行に、ソースがある場所を指定する。
  4. doxygen.exeを実行し、ドキュメントを自動生成させる

BackgroundWorkerで、markdownのプレビュー処理を改善

前回までの作業で、画面で入力したMarkdown形式テキストをその場でプレビュー可能となりました。
ただ、この方法だとテキストのサイズが小さいときは問題ないのですが、サイズが大きくなってくるとプレビューに時間が掛かるため、キー入力に対するレスポンス低下が起きてしまいます。


今回は、テキストが大量になっても入力のレスポンスが低下しないように改造してみます。


リアルタイムプレビュー時の負荷を下げる


レスポンス低下の問題ですが、原因は2つ存在します。


  • 1文字でも変更があっると都度htmlへの変換を行う為、変換頻度が高すぎる。
  • htmlへの変換処理をイベントハンドラ内で行っている為、変換中にキー入力が出来ない

ここでは、それぞれの問題に対して対応を考えます。


変換頻度が高すぎる件の改善


まず、前者の変換頻度が高すぎる件ですが、TextChangedのイベントハンドラ内で直接Markdown形式からhtmlへの変換を行うのを止めます。
以下の処理に変更することで、変換の頻度を落とします。


  • テキストが変更されたタイミングでは、変更があった事を記録する(flgを立てる)だけにする
  • 一定周期のタイマーで、flgが立っているかチェックする。
  • flgが立っていれば変換を行う

それでは、実際に上記の改造を行ってみます。


前回までは、textBox1_TextChanged()で変換処理を直接行っていました。


private void textBox1_TextChanged( object sender, EventArgs e ) {
    // 変換ボタンが押されたことにする
    button1_Click( sender, e );
}


これを、flgを立てるよう変更します。


private bool changeFlg = false;
 
private void textBox1_TextChanged( object sender, EventArgs e ) {
    // 変換処理が必要なことを覚える
    changeFlg = true;
}



次に、タイマーコントロールをフォームに追加し、一定周期でイベントが走るようにします。(とりあえず1秒周期にしてみます)



コントロールを置いたら、イベントハンドラを追加します

private void timer1_Tick( object sender, EventArgs e ) {
    // 変換が不要な場合は何もしない。
    if ( !changeFlg ) {
        return;
    }
 
    // 変換処理を行う(変換ボタンを押したことにする)
    button1_Click( sender, e );
 
    changeFlg = false;
}




上記の改造後、再度プログラムを実行してみます。
改造の前に比べるとかなりレスポンスは向上しました(静止画では分かりませんが…)。


ただし、この状態でも、タイマーが走る1秒周期のタイミングで入力が引っかかる感じは残っています(テキストのサイズが大きい状態で編集を行うと顕著です)。


変換処理をイベント内で行っている件の改善


次は、Markdown形式の変換中にキー入力が出来ない為、引っかかりが残る件の対処です。


これは、タイマー処理のイベントハンドラがUIの入力イベントループの中で処理されていることが原因です(試しにタイマー処理内で、1秒程度スリープしてみると分かりやすいです)。


この問題に対してはC#(というか.Net Framework)の場合、BackgroundWorkerクラスを使用すると簡単に非同期処理を行うことが出来ます。


まずは、BackgroundWorkerコントロールを追加し、DoWork, RunWorkerCompletedイベントを追加します。
DoWorkイベントは、非同期で行うべき処理を記述します。イベント内では、GUIのコントロールに対して値をセットすることが出来ない点に注意が必要です。これは、スレッド間の競合が発生する恐れがある為です。実際に値をセットしようとすると、”実行時”に例外が発生します。

また、RunWorkerCompletedイベントの方は、DoWorkイベントが終了した際にコールされます。こちらは、GUI側のイベントループ内で走る処理ですので、画面コントロールに情報をセットすることが可能です。


ですので、BackgroundWorkerコントロールの基本的な流れは、DoWorkで時間の掛かる処理を行い、その後RunWorkerCompletedで処理結果を画面に反映するという流れになります。


で、具体的なプログラムの改造ですが、まずは、タイマーのイベントハンドラ処理を変更します。


private void timer1_Tick( object sender, EventArgs e ) {
    // 変換が不要な場合は何もしない。
    if ( !changeFlg ) {
        return;
    }
 
    // 変換処理を行う(変換ボタンを押したことにする)
    button1_Click( sender, e );
}




private void timer1_Tick( object sender, EventArgs e ) {
    // 変換が不要な場合は何もしない。
    if ( !changeFlg ) {
        return;
    }
 
    // すでに非同期処理中の場合は何もしない
    if ( backgroundWorker1.IsBusy ) {
        return;
    }
 
    // 変換処理を非同期で実施する
    backgroundWorker1.RunWorkerAsync( textBox1.Text );
}



backgroundWorker1のRunWorkerAsync()で、処理を非同期実行することが出来ます。
このメソッドを呼ぶと、別スレッドでbackgroundWorker1_DoWork()メソッドが実行されます。

また、RunWorkerAsyncメソッドに引数を渡すことで、DoWork()に対するパラメータを渡すことが可能です。引数は1つだけですがobject型なので、Dictionary<>やList<>をセットすれば、結果的に複数の情報を渡すことが可能です。今回必要な情報は1つだけなので、単純にstringの文字列を渡しています。


次に、実際に非同期処理を行うロジックをDoWork()に記述します。


private void backgroundWorker1_DoWork( object sender, DoWorkEventArgs e ) {
    //-------------------------
    // 入力パラメータを取得する
    //-------------------------
    string srcStr = e.Argument as string;
    if ( srcStr == null ) {
        srcStr = "";
    }
 
    //-------------------------
    // 変換処理を行う
    //-------------------------
    Markdown m = new Markdown();
    String destStr = m.Transform( srcStr ); 
 
    //-------------------------
    // 変換結果を返す
    //-------------------------
    e.Result = destStr;
}


先ほどRunWorkerAsync()で渡した情報は、DoWork()イベントの第二引数経由(e.Argument)で取得できます。e.Argumentは、当然ながらobject型なので、呼び元が渡したデータ型にキャストする必要があります。

キャストは、string srcStr =(string)e.Argument; といった形でも行うことが可能ですが、呼び元側で異なる型のオブジェクトを渡した場合、ここで例外が発生してしまいます。この為、”as”を使用したキャストを行います。asを使用した場合、元となるオブジェクトがキャストできない場合はnullが返る仕様なので、nullチェックを行ったうえで適切な処理を行います。


入力パラメータを取得したら、本来やりたかったMarkdownの変換を行った後、結果を返す必要があります。ここで、textBox2.Text = destStr;と書きたくなるところですが、前述したようにスレッド間の競合が発生する可能性があるので、この処理は認められません。

替わりに結果を、第二引数のResultプロパティ経由で渡します。こちらもArgumentと同様object型ですので、同様の配慮を行う必要があります。


最後は、変換結果を画面に反映させる処理です。
こちらは、BackgroundWorkerのRunWorkerCompleted()メソッドで行います。


private void backgroundWorker1_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
    //--------------------------------------
    // textBoxに出力するために改行文字を変換
    //--------------------------------------
    String destStr = e.Result as String;
    if ( destStr == null ) {
        destStr = "";
    }
 
    String htmlText = GetHeader() + destStr.Replace( "\n", Environment.NewLine ) + GetFooter();
 
    //--------------------------------------
    // 変換結果をテキストで画面に表示
    //--------------------------------------
    textBox2.Text = htmlText;
 
    //--------------------------------------
    // 変換結果をブラウザにプレビュー
    //--------------------------------------
    webBrowser1.DocumentText =  htmlText;
}


DoWork()の時と同様、非同期処理の結果がe.Resultで取得できます。RunWorkerCompleted()はGUIのイベントループと同じスレッドで実行されるため、GUIコントロールにアクセスすることが可能です。

一方で、本メソッドで時間の掛かる処理を行うことは出来ません。ここで時間が掛かると、画面の応答速度が低下するため、操作性が悪くなってしまいます。


上記の改造を行ったうえで、再度プログラムを実行させると、無事、今まであった引っかかりがなくなりました。


以上で、前回作成したMarkdown変換処理のリアルタイムプレビューに対する処理改善は完了です。

MarkdownSharp.dllの変換結果をブラウザ表示結果としてプレビューする

前回までの記事で、C#からMarkdown形式のテキストをhtmlテキストに変換することが出来ました。


今回は、このhtmlをブラウザで表示した時、どのように見えるかをプレビュー可能にします。
プログラムは、前回作成したものを改造する事とします。


ブラウザでの表示形式でプレビュー可能にする

まず、フォームにWebBrowserコントロールを貼り付けます。
WebBrowserコントロールは、コモンコントロールの一番下に有ります。



名前は、今回はwebBrowser1のままにしておきます。



次に、変換ボタンをクリックしたときのハンドラを書き換えます。

private void button1_Click( object sender, EventArgs e ) {
    //--------------------------------------
    // markdown形式の文字列をhtmlに変換する
    //--------------------------------------
    Markdown m = new Markdown();
    String tmpBuff  = m.Transform( textBox1.Text ); 
 
    //--------------------------------------
    // textBoxに出力するために改行文字を変換
    //--------------------------------------
    String htmlText = tmpBuff.Replace( "\n", Environment.NewLine );
 
    //--------------------------------------
    // 変換結果をテキストで画面に表示
    //--------------------------------------
    textBox2.Text = htmlText;
 
    //--------------------------------------
    // 変換結果をブラウザにプレビュー
    //--------------------------------------
    webBrowser1.DocumentText =  htmlText;
}



前回と変わったのは最後の1行だけです。
WebBrowserコントロールは、DocumentTextプロパティでHTMLソースを直接指定できます。
※ちなみに… webBrowser1.Document.Write()を使用する技もあります。詳細は@ITの記事を参照。

この状態で、プログラムを実行します。
以下の様にhtmlをブラウザでプレビューしたときのイメージが表示されるようになりました。



htmlのheadタグを付与する

上記の方法で一応htmlのプレビューが可能になりましたが、markdown形式の変換結果に>html<や>head<タグが含まれていません。
このため厳密に考えると、DocumentTextメソッドに変換結果をそのまま渡すのは、NGです(正しいHTMLテキストではないので)。

また、プレビューを行う際に自分で定義しているcssを適用したい場合も有ります。



次は、上記の問題点を解消するため、変換した結果に対して事前定義したヘッダ・フッタを付与できるようにします。


事前準備として、exeのあるフォルダにheader.txtとfooter.txtを追加します。
(VisualStudioでデバッグ中は、”bin\Debug”フォルダに配置してください)


各ファイルの中身は、以下のようになっています。

header.txt


footer.txt



ファイルを作ったら、取り込み処理を作ります。
ファイル読み込みの例外処理は、サンプルなので適当です。実際はダイアログを出すとかログを落とすなどしてください。

//***************************************************************************
/// <summary> ヘッダ情報を読み込む
/// </summary>
/// <returns>ヘッダテキスト</returns>
//***************************************************************************
private String GetHeader() {
    return GetText( "header.txt" );
}
 
//***************************************************************************
/// <summary> フッタ情報を読み込む
/// </summary>
/// <returns>フッタテキスト</returns>
//***************************************************************************
private String GetFooter() {
    return GetText( "footer.txt" );
}
 
//***************************************************************************
/// <summary> 指定されたファイルを読み込む
/// </summary>
/// <param name="fileName">ファイル名</param>
/// <returns>ファイルの内容</returns>
//***************************************************************************
private String GetText( String fileName ) {
    try {
        using ( StreamReader reader = new StreamReader( fileName, Encoding.GetEncoding( 932 ) ) ) {
            return reader.ReadToEnd();
        }
    } catch ( Exception ex ) {
        Console.WriteLine( ex.Message );
        return "";
    }
}



markdown形式のテキストを変換した際に、これらのファイル内容を付け足すため、ボタンのクリック処理に対して、以下の変更を行います。

//--------------------------------------
// textBoxに出力するために改行文字を変換
//--------------------------------------
String htmlText = tmpBuff.Replace( "\n", Environment.NewLine );String htmlText = GetHeader() + tmpBuff.Replace( "\n", Environment.NewLine ) + GetFooter();



実行すると、ファイルに記述したheader.txt,footer.txtの内容が適用されます。
header.txtにcssの定義を記述しているので、デザインが変わっているのが確認できます。



リアルタイムプレビューを可能にする

ここまでの方法で、ボタンを押す事でhtmlのプレビューが可能になりましたが、プレビューをしたいときに毎回ボタンを押す必要がある点がちょっと面倒です。
次は、Markdown形式でテキストを入力したらその場でリアルタイムプレビューが出来るようにします。

プレビュー結果を書き換えたいタイミングは、Markdown形式のテキストが書き換えられた時なので、左上の入力欄(textBox1)にTextChangedイベントを追加し、以下の処理を記述しいます。

private void textBox1_TextChanged( object sender, EventArgs e ) {
    // 変換ボタンが押されたことにする
    button1_Click( sender, e );
}



この変更を加えた上で、もういちど実行すると、期待通りにリアルタイムプレビューが出来ています。
(キャプチャ画面だと分からないですが、左上の入力欄に1文字入力するたびにプレビュー結果が変更されます)



リアルタイムプレビュー時の負荷を下げる

ここまでで、画面で入力したMarkdown形式テキストを、その場でプレビュー可能となりました。
ただ、この方法だとテキストのサイズが小さいときは問題ないのですが、サイズが大きくなってくるとプレビューに時間が掛かるため、キー入力に対するレスポンス低下が起きてしまいます。


次回は、テキストが大量になっても入力のレスポンスが低下しないように改造してみます。

markdown.dllを使用したプログラムを作成する

MarkdownSharp.dllを使用したサンプルPGを作成

前回の記事でdllを作成しましたので、今回はdllを使用してサンプルのプログラムを作成します。
(VisualStudio2010 + .Net Framework3.0で確認しています)


VisualStudioを起動し、ファイル→新規作成→プロジェクトを選択します。
テスト用のプロジェクトを作成します。


作成したプロジェクトファイル内にlibフォルダを作成し、前回作成したMarkdownSharp.dllを置きます。



ソリューションエクスプローラ→参照設定を右クリックし、参照の追加を選択し…

先ほど置いたdllを選択します。



参照設定にMarkdownSharpが追加されていることを確認します。


次にFormにtextBox1,button1,textBox2の3つの部品を配置します。



ボタンののイベントハンドラを以下のとおり記述します。
※tmpBuff.Replace()の行は、textBox出力したhtmlを見やすくするために改行文字を変換しているだけなので、変換処理の本質ではありません。実質的な変換処理は、Markdown#Transform()の1行だけです。

private void button1_Click( object sender, EventArgs e ) {
    //--------------------------------------
    // markdown形式の文字列をhtmlに変換する
    //--------------------------------------
    Markdown m = new Markdown();
    String tmpBuff  = m.Transform( textBox1.Text ); 
 
    //--------------------------------------
    // textBoxに出力するために改行文字を変換
    //--------------------------------------
    String htmlText = tmpBuff.Replace( "\n", Environment.NewLine );
 
    //--------------------------------------
    // 変換結果を画面に表示
    //--------------------------------------
    textBox2.Text = htmlText;
}




コンパイル・実行を行うと、以下のようにMarkdown記法がHTMLに変換されます。



C#のmarkdownライブラリ,MarkdownSharpを使用する

markdown記法とは?


wikiなどでよく使用されている構文です。

http://ja.wikipedia.org/ によると..

Markdown は軽量マークアップ言語のひとつである。
「読みやすく書きやすいプレーンテキストで書け、そして構造的に妥当なXHTML(もしくはHTML)
に変換することのできるフォーマット」として、John GruberとAaron Swartzによって考案された。
Markdownの記法の多くは、電子メールでプレーンテキストを装飾する際の慣習から着想を得ている。


だそうです。




markdown記法の変換ライブラリ


C#でのmarkdown記法パーサは、markdownsharpというライブラリが有名です。

markdownsharpは、stackoverflow.comなどで使用されています。
MITライセンスですので、自作のアプリに組み込みやすい所も良いです。

markdownsharpは、基本的にはPerl 1.0.1のMarkdown実装を元にしてされています。
また、幾つかStackOverflow.com向けのカスタマイズが施されていますが、それらの機能はデフォルトでoffになっているので気にする必要はありません。


VisualStudio2010で、markdownsharpを使用する


http://code.google.com/p/markdownsharp/ のdownloadsリンクより最新版をダウンロードします。
本エントリー作成時の最新は、20100703-v113でした。

※ファイルは7zip形式(*.7z)です。展開ソフトがない場合は7-zip portableが便利です。
(7-zip portableは文字通りポータブル版なのでインストール不要です)


ファイルを展開すると、以下の3フォルダ/ファイルが入っています。




メインとなる、ソースが入っているフォルダ(MarkdownSharp)を確認すると、6ファイルはいっています。


AssemblyInfo.cs・MarkdownSharp.csprojは、実際のロジックは入ってないので関係なし。

MarkdownOld.csは、ソースの頭を見ると以下の記述があります。
過去バージョンの確認用らしいので、コレも関係ないですね。

This old version is included only for historical comparison purposes; 
use at your own risk!



ですので、実質的には3ファイルで構成されているようです。

Escapes.cs
Markdown.cs
MarkdownOptions.cs




動作確認

とりあえず、トップフォルダにある.slnファイルを開いてコンパイルをかけます。

MarkdownSharp\bin\Debugの下にMarkdownSharp.dllが出来ていることを確認します。



次に、MarkdownSharpTest側のプロジェクトを実行させます。
(ソリューションエクスプローラで右クリック->デバッグ実行)

コマンドプロンプトがが開いて、テスト結果が表示されます。




結果を全部表示させると、以下のような感じになります。

MarkdownSharp v1.13 test run on \mdtest-1.1
 
001 Amps_and_angle_encoding                                OK
002 Auto_links                                             OK
003 Backslash_escapes                                      OK^
004 Blockquotes_with_code_blocks                           OK
005 Code_Blocks                                            OK
006 Code_Spans                                             OK
007 Hard_wrapped_paragraphs_with_list_like_lines           OK
008 Horizontal_rules                                       OK
009 Images                                                 OK
010 Inline_HTML_Advanced                                   OK
011 Inline_HTML_comments                                   OK
012 Inline_HTML_Simple                                     OK
013 Links_inline_style                                     OK
014 Links_reference_style                                  OK
015 Links_shortcut_references                              OK
016 Literal_quotes_in_titles                               OK
017 Markdown_Documentation_Basics                          OK
018 Markdown_Documentation_Syntax                          OK
019 Nested_blockquotes                                     OK
020 Ordered_and_unordered_lists                            OK^
021 Strong_and_em_together                                 OK
022 Tabs                                                   OK
023 Tidyness                                               OK^
 
Tests        : 23
OK           : 23 (^ 3 whitespace differences)
Mismatch     : 0
 
MarkdownSharp v1.13 test run on \mstest-0.1
 
001 code-inside-list                                       Mismatch
002 line-endings-cr                                        OK
003 line-endings-crlf                                      OK
004 line-endings-lf                                        OK
005 markdown-readme                                        OK
 
Tests        : 5
OK           : 4
Mismatch     : 1
 
 
MarkdownSharp v1.13 benchmark, takes 10 ~ 30 seconds...
input string length: 475
4000 iterations in 2850 ms (0.7125 ms per iteration)
input string length: 2356
1000 iterations in 2843 ms (2.843 ms per iteration)
input string length: 27737
100 iterations in 3017 ms (30.17 ms per iteration)
input string length: 11075
1 iteration in 15 ms
input string length: 88607
1 iteration in 119 ms
input string length: 354431
1 iteration in 462 ms



以上で、動作確認は完了です。



おまけ。
dllだけ欲しい人のために、コンパイルしたものを置いときます。

ダウンロード: MarkdownSharp_20100703-v113.zip

Amazonの個別商品ページから一瞬でASINをコピーする技

ブラウザに下記のブックマークレットを登録しておくことで、ワンクリックでASINの値をクリップボードにコピーできます。ブックマークレットというのはavaScriptの小さなプログラムで、ブラウザのブックマークに登録して利用します。


以下のリンクを右クリックして、「お気に入りに追加」を選択してください。
リンクをブックマークバーにドラッグしてもOKです。
(“追加しようとしているお気に入りは、安全でない可能性があります”というダイアログが出る場合がありますが、”はい”を選択してください。)

ASINをクリップボードにコピー

クリップボードに直接コピーされるのが嫌な場合は、下記のリンクを使用してください。

ASINをダイアログで表示
ASINをダイアログで表示(コピペが簡単なように入力欄として表示)




仕組み

amazonの個別商品ページにはhiddenでASIN情報が入っています。
この為、以下のスクリプトでASIN情報が取得できます。
document.getElementById(‘ASIN’).value

上記の関数で取得した値を、clipboardData.setData()でクリップボードにコピーしています。


ソースは以下のようになっています。

ASINをクリップボードにコピー
javascript:var a=clipboardData.setData("Text", document.getElementById('ASIN').value ); alert( "ASINをクリップボードにコピーしました\n\n" + document.getElementById('ASIN').value );
 
ASINをダイアログで表示(コピペが簡単なように、入力欄として表示)
javascript:prompt('ASIN',document.getElementById('ASIN').value);
 
ASINをダイアログで表示
javascript:alert( document.getElementById('ASIN').value );

WindowsXPでリモートデスクトップ使用時に格子模様のゴミが表示される

問題


リモートデスクトップ使用時に、以下の様な格子模様のゴミが表示される。


原因


パッチKB958470の不具合が原因です。


対処法


以下のサイトで、リモート デスクトップ接続の新しいクライアントをインストールする。


Windows XP 用リモート デスクトップ接続 (Terminal Services クライアント 6.1)