別オブジェクトからフォームインスタンスの参照を得るには?

.NET Framework 2.0 以降のみですが、System.Windows.Forms.Application クラスの静的プロパティ、 OpenForms により、開いているフォームインスタンスを参照することができます。
 

Form form = Application.OpenForms[0]; // 開いているフォームのうち一番古いものを得る

 

Form form = Application.OpenForms[“form1”]; // form1 という名前のフォームインスタンスを得る

 
参考:
Windowsフォームでフォームのコレクションを使用するには?
Application.OpenForms プロパティ(MSDN)
FormCollection クラス

別スレッドからフォームコントロールを操作するには?

VB.NET にも該当することですが、C#.NET では、

using System;
using System.Windows.Forms;
using System.Threading;
 
namespace Foo{
public class Form1 : Form{
    public Form1(){
        InitializeComponent();
    }
 
    private void button1_Click(object sender, EventArgs e){
        new Thread(new ThreadStart(delegate{
textBox1.Text = “Hello, world”;
})).Start();
    }

    // その他については略
}
}

としても InvalidOperationException が発生し、

有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール ‘textBox1’ がアクセスされました。

のように表示されてしまい、クロススレッドなフォームコントロールの操作ができません。
 
これを回避するには、System.Windows.Forms.Control の Invoke() メソッドを使い、コントロールの操作時のみ、そのコントロールが属するウィンドウハンドルを持つスレッドで実行するようにします。

            // Invoke() 用デリゲート
            private delegate void Del();
 
            private void button1_Click(object sender, EventArgs e){
 
                new Thread(new ThreadStart( delegate {
Invoke( (Del) delegate { // 匿名メソッドを Del 型にキャストし, それを呼び出す。
textBox1.Text = “Hello, world”; // コントロールの操作
});
                    })).Start();
            }

あるいは、MSDN の「Windows フォーム コントロールのスレッド セーフな呼び出しを行う」にあるように、

            private void button1_Click(object sender, EventArgs e){

new Thread(new ThreadStart( delegate {
SetText(“Hello, world”);
})).Start();
}

private delegate void SetTextCallback(string msg);

private void SetText(string msg){
if(textBox1.InvokeRequired){ // 指定したコントロールの操作に Invoke()が必要かどうか(この場合、this.InvokeRequired としてもよい)。

Invoke(new SetTextCallback(SetText), new object[] {msg}); // 必要であれば自身を Invoke する。
return;

}

// 以下本来の処理

textBox1.Text = msg;
}

のように、Control クラスの InvokeRequred プロパティで Invoke が必要かどうかを判別し、必要なら Invoke によりメソッドを呼び直すという方法もあります。
 
どちらを利用する場合も、Invoke() 中はメインスレッドでの実行になるため、マルチスレッド処理の恩恵を受けられません。このため、Invoke() 中のコードでは、コントロールの操作をするために最低限の実装であることが望ましいでしょう。
 
なお、本記事のコードで使用している匿名メソッド( delegate (){ /* */ } というコード)は、.NET Framework 2.0 以降でしか利用できないため、2.0 未満で利用する場合は該当箇所をメソッド定義に置き換えてください。
 

追記: C# 3.0(Visual Studio 2008)以降はラムダ式が使えるようになってさらに書きやすくなりました。

Invoke( (MethodInvoker)(()=> // ラムダ式をUIスレッドで実行する。
    textBox1.Text = "Hello, world";        // コントロールの操作
});
}

参考:
System.Windows.Forms.Control.Invoke()
Windows フォーム コントロールのスレッド セーフな呼び出しを行う(MSDN)
  MSDN ライブラリ -> 開発ツールと言語 -> Visual Studio ドキュメント -> Windows ベースのアプリケーション、コンポーネント、サービス -> Windows ベースのアプリケーションの作成 -> Windows フォーム -> Windows フォームについて -> Windows フォームコントロール -> .NET Framework を使用したカスタム Windows フォームコントロールの開発 -> Windows フォームコントロールのマルチスレッド処理

servname not supported for ai_socktype エラー

chroot 環境で作業をしていたら whois でこんなエラーが。

$ whois google.co.jp
whois: jp.whois-servers.net: servname not supported for ai_socktype

調べてみると、原因は /etc/service の不備でした。
whois の場合、/etc/service に

nicname 43/tcp whois
nicname 43/udp whois

がないのが原因です。
 
参考:
Error: Servname not supported for ai_socktype

Postfix での Port 25 Blocking 対策

Outbound Port 25 Blocking により、外部にSMTP が通せない環境でメールサーバを運用する場合、次のいずれかの対応方法をとる必要があります。
1.プロバイダのメールサーバに転送する
2. サブミッションポート(Submission Port)が使える外部のメールサーバに転送する
 
1 の場合で認証が不要な場合は、main.cf に以下を加えることで簡単に対応することができます。
main.cf:

relayhost = smtp.nifty.com

smtp.nifty.com は自分のプロバイダの SMTP サーバに置き換えてください。
 
1 で認証が必要な場合、あるいは、2 の場合は普通認証を必要としますが、この場合は Cyrus SASL 対応の Postfix を使うことで、認証付きのリレーが可能になります。
main.cf:

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/saslpass
relayhost = [smtp.nifty.com]:587
smtp_use_tls = yes # optional

relayhost は自分が使う SMTP サーバ、ポート番号に置き換えてください(587 はサブミッションポートを使う場合)
 
次に、smtp_sasl_password_maps で指定したファイルを作成します。
saslpass:

# 書式:”relayhostに指定した値”<space>”認証ユーザ名”:”認証パスワード”
[smtp.nifty.com]:587 user:pass

作成後、postmap で saslpass.db を生成します。

$ cd /etc/postfix/
$ postmap saslpass

 
このままでも動作しますが、ここでセキュリティを考慮するのであれば、元としたプレインテキストのパスワードファイル saslpass は削除しておくべきでしょう。

$ rm saslpass

 
あとは Postfix を再起動し、好きなメーラを使って動作確認を行えば完了です。ここでは CUI の mail コマンドの例を示します。

$ mail -s test [email protected]
hello, world
.

([email protected] は自分が確認できる任意のメールアドレス)
 
参考:
Re: プロパイダのsmtpホストが smtp authを要求してる場合(Postfix-jp ML:1685)
  ぷらら環境での Postfix 設定。
25番ポートブロック対策について(Fedoraで自宅サーバー構築BBS)
  @nifty 環境での Postfix 設定。
Postfix で、Gmail にメールをリレーする(私の二次記憶)
  Postfix + Gmail
postconf(5)(Postfix 日本語マニュアル)

特定のサイト上の変数を動的に操作する

[2005-06-22-1],[2005-01-14-3]でも書きましたが、

javascript:…

というURI スキームについてですが、当然これはそのままブラウザの URL として指定できます。
 
javascript: 以下には、任意の JavaScript コードを指定できるので、ブラウザ(IE, Firefox, Opera でもなんでも)を有用な簡易 JavaScript デバッグ環境として利用することができます。
 
例えば、任意のサイトで変数 foo の現在の値を閲覧したい場合は、そのサイトを表示した状態で

javascript: alert(foo);

とすればよく、逆に foo の値を変更したい場合は
 

javascript: foo=”new value”; focus();

などとすればいいわけです( 最後の focus() は画面遷移を防ぐ目的)。
 
実例を挙げると, こちらで紹介されている、モグラたたきゲームのサンプルは、ソースによるとten が点数なので、ゲーム動作中に

javascript:ten=50000;focus()

とする事で得点が50000 点になります。
動作検証をする場合に、ソースに変更を加えることなくテストができるので、開発後のメンテナンス時に役立つのではないでしょうか。
 

実行中の画面
実行後の画面

UIEngine

UJML という XML ベースの言語により、さまざまな環境(PC,Mobile)で動作するアプリケーションが作成可能になる、というものです。
UIEngine という、環境の差異を吸収するエンジンにより実現しているようです。
開発環境の非営利目的での利用は無償ですが、UEIジャパン社に営利目的の場合は要連絡とのことです。
 
Life is beautiful
 UIEジャパンCEO中島氏のブログ。
 
-UIEngine WiKi
 
-株式会社UIEジャパン
 開発、配布元。
 
UIEngineだ
UIEngine について色々書かれてます。

chalow 1.0rc4 から1.0rc6 に

思い立ってバージョンしました。
セキュリティ面で問題があるというわけではなかったのと、自分で好き勝手にカスタマイズしているので、手間を惜しんで更新していなかったのです。
 
こういった作業の時に diff は便利ですね。
 
ところで chalow 1.0 rc6 が出たのが 2005-08-21 ということなので、2年近く前の更新を今更やったわけですが、一番最初のエントリ(当時は非公開)が [2004-08-27] だという事実に驚きです..
 
光陰矢の如し。
これからもマイペースに続けるつもりなので、末永くよろしくお願いします。