Archive

Posts Tagged ‘未解決問題’

Apache 2.2 で WebDAV

サーバーのディスクが余っていたのでファイルサーバーにしようかと思い,いくつか方法を考えていましたが, Apache を使っていたので WebDAV サーバーを構築してみました。

環境

  • Ubuntu 10.4 Server 版 (64-bit)
  • Apache 2.2
  • mod_dav

Read more...

Tip, サーバー , ,

配列をジェネリックリストにキャストするとおかしいことになる

Array クラスArray クラスは IList インターフェイスを実装していますが, IList<T> インターフェイスは実装しません。したがって次のコードは実行できないように思われます。

string[] array = new string[1];
IList list = (IList)array;
IList<string> genericList = (IList<string>)array;

ところが実際に動かしてみると何のエラーも起こらずに普通に動きました。リフレクションでインターフェイスを調べてみると,ジェネリックリストのインターフェイスが実装されていたので,コンパイル時にそういうことが行われているんだろうと納得しました。というかちゃんと MSDN に書いてありました。しかも重要って書いてありました。

.NET Framework Version 2.0 では、 Array クラスは System.Collections.Generic.IList(T)、 System.Collections.Generic.ICollection(T)、および System.Collections.Generic.IEnumerable(T) の各ジェネリック インターフェイスを実装します。

反省しつつも,もう少し調べてみると不思議なことが起こりました。

Console.WriteLine(array.IsReadOnly);  // False
Console.WriteLine(list.IsReadOnly);  // False
Console.WriteLine(genericList.IsReadOnly);  // True

上の 2 つは期待通りの動作をするのですが,最後の挙動は不思議です。じゃあ IList<string> にキャストしたら本当に読み込み専用になるのかというとそうでもないようです。

genericList[0] = "hoge";
Console.WriteLine(array[0]);  // hoge
Console.WriteLine(list[0]);  // hoge
Console.WriteLine(genericList[0]);  // hoge

でもやはりジェネリックか否かで IsReadOnly の結果は違うのです。コレクションで実装されるかリストで実装されるかの違いが原因なのでしょうか。

// ICollection.IsReadOnly は存在しない。
// Console.WriteLine(genericList.IsReadOnly == ((ICollection)genericList).IsReadOnly);
Console.WriteLine(genericList.IsReadOnly == ((IList)genericList).IsReadOnly);  // False
Console.WriteLine(genericList.IsReadOnly == ((ICollection<string>)genericList).IsReadOnly);  // True

同じ EXE ファイル (Visual Studio でコンパイル) を mono で実行すると, genericList.IsReadOnlyFalse を返しました。これ妥当な結果を返していると思います。逆に mono でコンパイルした EXE ファイルを .NET Framework で動かすと,上で述べてきたような変な結果になります。つまりは .NET Framework ランタイムのバグということでしょうか。

問題になるのは IsReadOnly で条件判定している場合ですね。

public void InitializeList<T>(IList<T> list)
{
	if (list == null)
	{
		throw new ArgumentNullException();
	}
	if (list.IsReadOnly)
	{
		throw new ArgumentException();
	}

	for (int index = 0; index < list.Count; index++)
	{
		list[index] = default(T);
	}
}

あまりあるケースだとは思いませんが,一応ジェネリックリストを引数にとるメソッドは引数が配列であるかどうかをチェックした方が良いかもしれません。

プログラミング ,

Mercurial に移行

分散型バージョン管理システムに移行するなら日本語ファイル名も上手に扱ってくれる Bazaar だとずっと考えていたのですが,プラグインの日本語扱いがファイル名に限らず微妙なのと,そもそも日本語ファイル名をそんなに扱うこともないという考えから Mercurial に移行してみました。以前試したときは TortoiseHg は 64-bit Explorer からコンテキストメニューで操作できなかったのですが,最新バージョンでは対応しているようです[a]

手順としては以下のような感じになりました。

  1. Mercurial のインストール
  2. リポジトリの変換
  3. Apache の公開設定
  4. SSH サーバーの設定
  5. クライアントの設定

以下に詳細を記します。

Read more...

脚注

  1. explorer.exe /separate とすれば使えましたが (64ビット版 Windows Vista で右クリックメニューを動かすにはどうすればいいですか?)。 []

サーバー , , , ,

Firefox に自己認証局証明書が追加できない

いろいろアドインの対応問題から Firefox 3.5 の使用をやめて Firefox 3.0 を使用していましたが, Firefox 3.5 に再アップグレードしました。ほとんど問題なく動いているのですが, 1 点だけ気になることが。表題の通りオレオレ証明書がインストールできません。

認証局証明書にオレオレ証明書を追加しようとすると,すでにインポートされている旨のメッセージが出ます。しかしインポートされていないので,自分のサーバーにアクセスすると不正な証明書との警告が出ます。自己証明書はインストールできたので,自分のサーバー証明書を例外扱いにすれば問題なくクライアント認証ができるので,一応問題なく動作はするのですけどね。

サーバー , , ,

スクリーン上でのウィンドウクライアント領域の取得

Win32 API を用いると他のアプリケーションのウィンドウやクライアント領域を取得することができます。

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
	public int Left;
	public int Top;
	public int Right;
	public int Bottom;
}

GetClientRect 関数では左上端の座標は常に (0, 0) です。ウィンドウの枠やキャプションバーを除いたクライアント領域のスクリーン上での座標を得るにはウィンドウの四角形から枠を除いて取得することができる気がします。

普通のウィンドウでは枠は左右と下に同じ太さでついていて上にキャプションバーが付いているというスタイルなので,これを仮定すれば簡単にクライアント領域を取得できます。しかしこのようなインターフェイスを本当に仮定してよいのかはよくわかりません。もしかして別の方法でクライアント領域を取得する方法があるのでしょうか。

プログラミング , ,