2007/09/03

[Eclipse] java.lang.NoClassDefFoundError

Exception in thread "main" java.lang.NoClassDefFoundError: XXX

XXX.class を作成し、
java XXX
で java の class ファイルを実行することができる

その際に、表題のようなエラーに出くわすかもしれない。

HelloWorld を表示するだけのような
なにも import せず、パッケージも使わないクラス
(例えば HelloWorld.classとする)においては
その class が見えるところにカレントを移動して、
java HelloWorld をすればまず実行できるだろう。

それで失敗するようならタイプミスかもしれない。
(クラスが見つからないってエラーなのでタイプミスでも同じのが出る)

次に、Eclipse から外部 jar を使っている場合は、
それらの jar に classpath を通さないといけない。
注意として、フォルダで止めずに、.jar までを指定すること。

Eclipse は内々でパスの設定なんかをしてくれるので、
Eclipse で作ったものを、コマンドプロンプトに持っていったら
このエラーで動かない。という話を何度か聞いている。

全ての外部 jar を、実行したい class のカレントに集めてしまえば
classpath については考えずに

java -classpath .;YYY.jar\ZZZ.jar XXX
(カレントを入れるのを忘れないように)
と、できるので、原因の切り出しが多少はラクになる。

最後に、パッケージを設定していた場合。

例えば、
foo.bar パッケージに HelloWorld を作った場合は
foo\bar\HelloWorld.class が生成されるわけだが、
foo フォルダが見える場所から
java foo.bar.HelloWorld とやらないと、
やはり表題のエラーになるので注意。

(ドキュメントから抽出した情報ではなくて
 トライ&エラーなので、あくまでも同じ状況になった人の参考程度に)


2007/09/04

[Eclipse] UnsatisfiedLinkError

こんなエラーが出た。

Monolithic library init failed with UnsatisfiedLinkError:
java.lang.UnsatisfiedLinkError: no XXX in java.library.path

とりあえず表示させてみる。

import java.util.Properties;
// プロパティのリスト取得
Properties props = System.getProperties();
// リストを表示
props.list(System.out);

たしかに、java.library.path にはライブラリのパスが無い。
DOS 窓から、環境変数 PATH に追加したんだけど
それじゃ駄目だったのかな。

実行の構成から環境タブに
新規で
名前:path
値 :ライブラリのパス
の変数を追加したら動いたので、これでいいや。

[murmur] LAMP XAMPP

LAMP(ランプ)は、言わずと知れた
Linux, Apache, MySQL, Perl or PHP or Python
の略なわけだけど
(この呼称が初めて使われたのは1998からだとWikipediaにあった)

そっか、XAMPP もそういうネーミングルールだったんだ。
でも X ってなんだろう笑。
GNU is NOT UNIX みたいに
XAMPP is including Apache, MySQL, PHP and Perl とかかな。

[murmur] innoDB

innoDB イノディービーと読む。
データベースで扱うテーブルのフォーマット。

当たり前の話だけど、
データベースのテーブルって
色んなフォーマットがあるんだ。

トランザクションセーフと
非トランザクションセーフって概念は
絶対に覚えておこ。

MySQL 4.1 リファレンスマニュアル :: 第7章 MySQL のテーブル型
でちょっとだけ触れられている

[murmur] phpMyAdmin

phpMyAdmin

ブラウザから簡単に
MySQL のテーブル操作、メンテナンスが行える。

XAMPP を入れたら入っている
http://localhost/phpmyadmin/

[murmur] Apache のバーチャルホスト機能

ホスト名やポート番号を使って
ドキュメントルートを振り分ける機能。

例えば、http://lolalhost:8080/
で指定したフォルダ、にアクセスさせるならば

httpd.conf を編集し、
Listen 8080

<VirtualHost *:8080>

DocumentRoot フォルダのフルパス

<Directory "フォルダのフルパス">
Options Indexes FollowSymLinks MultiViews Includes ExecCGI
AddType text/html .shtml
AddHandler server-parsed .shtml
AddHandler cgi-script .cgi .pl
AllowOverride All
Order allow,deny
Allow from all
</Directory>

</VirtualHost>

とすることで、可能となる。

[inside] 一時的に PATH を追加する方法

PATH というのは、要するに
ファイル名がフルパスじゃないときに
チェックするディレクトリ群のこと。
(ファイルも指定できるので、正確にはパス群)

DOS プロンプトから path と打てば、参照できる
これは path だけの優遇措置なので、
他の環境変数は
echo %環境変数名%
で参照できる。

環境変数の一覧は、DOS プロンプトから env と打てば、参照できる
(追記:これはパスの通った Cygwin の機能でした…)

PATH にディレクトリを加えることを
パスを通す、と言う。

バッチなんかで、
パスを一時的に通すには、次のようにする

@echo off
rem path をバッファリングする
set path_tmp=%path%
rem path に\foo\barを追加
set path=%path%;\foo\bar;
(ここで追加した path を参照するような処理を実行)
rem path を元に戻す
set path=%path_tmp%

(rem 行は DOS のコメントなので削除しても問題ない)

linux なら export でできるらしい。

[Eclipse] プラグイン(plugins)が読み込まれない

readme_eclipse.html には次のように書かれている。

Installing plug-ins by unzipping them into the plugins directory
If you have installed new plug-ins and they aren't showing up when you run,
then perhaps you unzipped them into your "plugins" directory
and your configuration might need to be refreshed.
This can be accomplished by starting Eclipse
with the -clean command line argument.

プラグイン(大抵は zip で配布されている)は解凍し、
plugins ディレクトリに配置することで、インストールすることができる。

プラグインをインストールしても
起動時にそれが出てこない場合、
plugins ディレクトリに配置して、
さらに設定を更新する必要があるかもしれない。

更新は、Eclipse をコマンドラインから
-clean オプションをつけて起動すれば行われる。

eclipse -clean

確かにこれで表示された


2007/09/05

[inside] クイック起動について

Windows のタスクバーには、
アプリケーションのアイコンが並んだ
クイック起動ツールバーが表示されている。

これは左端のサイズ調整領域をドラッグしたまま
デスクトップにドロップすることで、
フローティング表示になる。

そのウィンドウ上で右クリックすると、
フォルダを開くがメニューから選べるので、
それでクイック起動のフォルダが
どこなのかがわかる。

[inside] デスクトップアイコンを非表示に

Windows XP では
マイドキュメント
マイコンピュータ
マイネットワーク
Internet Explorer
のデスクトップアイコンに関しては
特殊なソフトを使用せずに表示/非表示が
切り替えられるようになった。

デスクトップで右クリックし
プロパティ > デスクトップ > デスクトップのカスタマイズ
ここに
デスクトップアイコンという項目があり
チェックボックスで表示非/表示が切り替えられる。

[Eclipse] JAVAメモ tools.jar と rt.jar

Eclipse から tomcat が起動できない。
未だ解決できないけど、
とりあえずメモ。

tools.jar と rt.jar を指定するって?
c:\j2sdk1.4.XX\lib に tools.jar が
c:\j2sdk1.4.XX\jre\lib に rt.jar が、それぞれあった。

rt.jar ってなんだろう。

JAR は、Java ARchive の略。
中身は ZIP ファイル。
.zip にリネームすれば、解凍可能。
JAR には中間コードが含まれている。

JAVA では、ソースコードから中間コードを作成し、
それを VM が解釈して処理が行われる。

コアパッケージ(基本ファイル)の中間コードは
rt.jar に格納されている。

なるほど。

じゃあ tools.jar は?
JDK から使われるツールとか
コア以外のファイルなのだそう。

ここらへんは
「JDK および JRE のファイル構造」
で検索かければ Sun のドキュメントが出てくるから
参考に

( URL が永続的じゃなさそうなので、リンクなし)


2007/09/06

[inside] pstore.h

pstore.h という禁断のヘッダファイルがある。

それがどういうものかはひとまず無視して、
VC6 で #include すると、
wingdi.h objidl.h objbase.h でエラーが起きる。

これを解決してみる。

pstore.h が
wtypes.h をインクルードする。
その中に、wingdi.h と競合する struct が定義されている。

wtypes.h ってグーグルで調べてみたけど、
あまり聞かない名前みたい。
pstore.h が 1997年 のファイルだし、
もしかしたらもう使わなくてもいいのかも。

と思ってはずしてみる。
コンパイルとおった。

[inside] Visual C++ 6.0 を便利に

少しずつ書き溜めようかと
キーワード強調
予約語 ( for とか char とか int とか )
以外を強調表示(色つき表示)させたいなら、
msdev.exe と同じ場所に
usertype.dat を作成し、
そこにキーワードを列挙する。
1行に1キーワード。
色は、 ツール > オプション > 書式
から変更できる

デバッグ中に、ウォッチを使って変数の値を確認できる。
static 変数はシンボルを解決できない
(表示できない)ことがある。
原因不明。
static 変数を前後に追加したら見れるようになったとか
情報が錯綜している。
UNICODE 文字列 LPWSTR とか WCHAR なんかは、
変数名,su で参照できる。

[inside] メッセージループ基礎

Windows のアプリケーションは
各アプリケーションが、Windows からメッセージを受け取って
そのメッセージに応じた動作をする。

一般的にウィンドウに関するメッセージが多いので、
ウィンドウが無いアプリケーション
( RegisterClass も CreateWindow もしない)
だとメッセージループを意識しないが、
きちんとメッセージを受け取っている。
(恐らく GUI に関係ないメッセージを)

メッセージはキューイングされ
::GetMessage() にて受け取れる
第1引数 LPMSG lpMsg // メッセージ情報
第2引数 HWND hWnd // ウィンドウのハンドル
第3引数 UINT wMsgFilterMin // 最初のメッセージ
第4引数 UINT wMsgFilterMax // 最後のメッセージ

第1引数にメッセージ情報が格納されていて、
メッセージの種類、メッセージごとのパラメータ
(クリックメッセージなら座標値など)
などに応じた処理を行える。
この処理は、ウィンドウプロシージャに任せることがほとんど。

第2引数はウィンドウハンドルだが、
これは NULL にすることで、このスレッドに関わる
メッセージ全てを拾うことができるので、大抵はそうなっていると思う。

例外的に、例えばダイアログなんかを作成して、
拾うメッセージはそのダイアログに対するものだけでいい
なんてときはそのダイアログのハンドルを指定してやる。

第3引数、第4引数は
メッセージの種類が整数表現なので、
その最小、最大を指定するが
あまり意味があるとは思えない。

取捨選択したいメッセージがたまたま
すごく小さかったりすごく大きい範囲に限定されていることは
まれだからだ。

ある種類のメッセージのみを受け取りたいなら
if 文を書けばそれで済む。

[inside] モードレス(モーダレス)な MessageBox

ずっと、モーダルとモーダレスだと思っていたのだけど
検索結果数を見た限りでは、
モーダルとモードレスという表記が一般的らしい。

あと、同期と非同期って言うこともあるね。
これも、言葉が違うから厳密には違いがあるかもしれないけど。

Windows 標準の API の MessageBox はモードレスにはなりません。笑
これはまあ、そういうものだから。

ただ、システムモーダル(OSごと待ち)と
アプリケーションモーダル(アプリが待ち)は
一番最後の引数で設定できるようだけど。

システムモーダルつかったことが無いから
ハッキリしたことは言えないなあ。

で、モードレスにするには、
別なプロセスで開くか、別なスレッドで開くか、
まあこのやり方を覚えれば
他の、同期とは言わずとも時間がかかる処理とかも
メインスレッドを停止させずに動かせるので、
やり方がわからない人もこれを気に覚えるといいと思う。

// スレッド用のルーチンを定義
DWORD WINAPI MessageThread( LPVOID pData );

呼び出しはこんな感じ
HANDLE hThread = CreateThread( NULL, 0, MessageThread, (LPVOID)NULL, 0, NULL );

// スレッドルーチン本体
DWORD WINAPI MessageThread( LPVOID pData )
{
    MessageBox(NULL, _TEXT("I am modeless."), _TEXT("message"), MB_OK );
    return 0;
}

特に難しいことは無いです。
ダイアログをサブクラスかするよりは遥かに簡単。
(まあ自由度はあっちのほうが高いというか
 そもそもニーズが違う技術だけど)

[murmur] 台風の日にはコロッケ

人づてに聞いたのだが、
ネット界隈では台風の日にコロッケを食べる習慣があるんだって。
いや、聞いたこと無いから。笑

食べたくなってきたよ。


2007/09/07

[セキュリティ] ディレクトリトラバーサル

例えば、ファイル名を受け取るような CGI に
../ のように、1つ上のディレクトリを意味する文字列を与え
本来想定されているディレクトリ以外にアクセスを試みる攻撃
ディレクトリをトラバース(横断)してしまう

[セキュリティ] バナーチェック

これから攻撃を行う対象のサーバの、
使用ソフトと、そのバージョンを調べること。

telnet などで特定のポートにリクエストを送信すると、
サービスからのレスポンスが返る。
そのレスポンスを調べたり、
さらにバージョン問い合わせコマンドを発行することで、
ソフトウェアとバージョンに関する情報を得る

感覚的にはポートスキャンにも近い
ポートスキャンは誰でも知っているが、
こちらはそれほど名前が挙がらないと思う


2007/09/10

[Ruby] かな漢字文(自然文)をローマ字へ

まず始めに、形態素解析などの専用ソフトを使ったほうが
よさそうだな、と思った。

形態素解析に使えるソフトは色々あるが
(その中でも kakasi はそのものずばりローマ字出力が可能)
性能がいいと言われる MeCab を使うことにした。

まずはMeCab の Binary package for MS-Windowsを
ダウンロードしてインストール、bin フォルダへ PATH を通した。

これで
system( "mecab target.txt -Oyomi > output.txt" )
してやれば、文章を読みガナにすることが可能だ。

Ruby 用のライブラリもあるらしいが、
tar.gz だったので Windows での使用を諦めた。

この -Oyomi は、オプションで、
あらかじめ別ファイルに定義されている。
これを定義しなおして、ローマ字出力が出来ないかと考えた。
しかし、読みガナに相当するのは、表層文字列だと思うのだが、
ざっくり調べた感じでは、
フォーマット(ひらがな、カタカナ、ローマ字)を
指定できるようにはなってないようだ。

そこで、出てきたカタカナの読みをさらに
kakasi に渡して 笑、ローマ字に変換することにした。

kakasi はドキュメントが見つからず、
いったいどんなオプションを渡せばいいのかわからずに苦労したが、
最終的に -Ka や -Kj で
カタカナからアスキー または カタカナからローマ字
の意味だろうと推測し、このようなコマンドを送ることにした。

system( "kakasi -Kj < yomi.txt" )
ファイルの与え方は、
やはりドキュメントは見つからなかったが
いくつかのサイトを見るとこういう渡し方をしているので、
恐らくこうなのだろう。

最初に言ったとおり、
kakasi のみで文章→ローマ字 は行えるが、
特に大量にデータを処理するわけではないので、
(むしろ少しでも正確性が上がるほうが良い)
Ruby から MeCab と kakasi を呼び出すという方法を採用。

[数学]ゼロの階乗(0の階乗)

ゼロの階乗 0! は 1 になることが知られいてるが、
これは定義であるので、証明は存在せず。

探してたらこんなの見つけたけど。

階乗の定義から
n! = n * (n-1) * …

両辺を n で割ると
n! ÷ n = (n-1) * (n-2) * … = (n-1)!

上の式は n = 1 のとき
1! ÷ 1 = (1-1)! = 0!

整理し
1! = 0! //

まあ、納得いかないわ。
定義って言われたほうがスッキリ。

[Eclipse] Tomcat プラグインが起動できない

正確には、プラグインをインストールしても
ボタンから Tomcat が起動、終了できない。

そういう場合、Eclipse では
workspace\.metadata\.log
にエラーログが表示されている。

が、まあ大抵は謎のエラーが表示されている。
java.lang.ClassNotFoundException
とか、文字列処理、タイマー処理
関係なさそうなクラスのエラーの場合、
大抵はJDKのバージョン違いの可能性が高い。

解説によっては
Tomcat プラグインの導入を、J2SDK で行っているものがある。
J2SDK は Ver 1.4.x までに相当し
J2SDK の最新版で導入している限り、
最新のTomcat で対応しているような
1.5.x の Java は一生インストールされないので注意しよう。

Java は 1.5.x から名前が変わって
JDK と呼ばれるようになった。
またバージョンも、1.5.x が 5.0 1.6.x が 6.0 と
表記方法が変わったが、しばらくは併記されるだろう。

現時点のこちらの環境で Tomcat プラグインが動くのは
JDK 1.5.0_12 である。

JDK 1.5.0_12をインストールした後、
ウィンドウ > 設定 > Java > インストール済のJRE から
追加を選択し、
インストール時にデフォルトパスで行ったなら
C:\Program Files\Java\jdk1.5.0_12
を指定する。

同じく設定ウィンドウの Tomcat > JVM 設定
に JRE のバージョンを選択する項があるので、
先ほどの jdk1.5.0_12 を指定する。

これで無事に Tomcat が起動できるようになった。
それでも起動しない場合は、
先ほどの .log をチェックして、
環境と一緒に Eclipse Wiki などで助けを求めると
親切な人が助けてくれるかもしれない笑。

[murmur] kakasi と MeCab を比較

と言っても、セキュリティアドミニストレータ用の
単語学習辞書をとくに工夫もせずにそれぞれに読ませただけ。

MeCab の方が優秀なのは全くその通りで
kakasi は 一人の→イチニンノなのに
複数人の→フクスウヒトノ とかカオスな感じで、
(これはまあいいけど)
者は全部モノになる(翻訳者=ホンヤクモノ)
文書はモンショで、
明らかな訓読みが音読みになるケースがある
の中に→ノジュウニ
委託する側→イタクスルソク

でも MeCab も 脅かす→キョウカス なんて
たまにポカしてた(kakasiはオビヤカスだった)

どちらも絶対ってことは無い(そらそーだ)
程度でいうと MeCab のほうがミスは少ないという結論

[murmur] JSP 関連のメモ

JSPで登場する特殊なタグの名前
<%@ %> ディレクティブ
<% %> スクリプトレット
<%= %> 式
<%! %> 宣言

JSPとASPの違い
ASP=マイクロソフト
本当か?笑

サーブレットコンテナ=サーブレットの実行環境
代表的なサーブレットコンテナ Tomcat

[セキュリティ] セキュリティ関連のメモ

ISMS=情報セキュリティマネジメントシステム

PDCA(PDCAサイクル)=
プランドゥーチェックアクト
Plan Do Check Act
計画 実施 検証 改善

ISMSの規格
管理策の明示=ISO/IEC 27001:2005
実際の指針=ISO/IEC 17799:2005

ISO=国際標準化機構
IEC=国際電気標準会議

VPN=Virtual Private Network
VPN の実現方法
PPTP
SOCKS
IPSec
事実上の標準(デファクトスタンダード)→IPSec

IPSec サービスのプロトコル
AH 認証ヘッダ
ESP 暗号ペイロード
AH→パケットを認証、改ざんされていないことを保証
ESP→パケットを暗号化
それぞれは独立しており、組み合わせても使える

でもパケットが暗号化されているから
ファイアウォールの不正パケット監視機能はスルーされる。

[murmur] DTD に関するメモ

サーブレット作ってると web.xml を書くわけだけど
書いててなんだこれは、と思ったので

DTD (Document Type Definition)
ドキュメント型定義

DOCTYPE 宣言 → 自らが基づく DTD を指定するもの

例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">

解説:
<!DOCTYPE …> → このタグが DOCTYPE 宣言であること示す
HTML → この文書のタイプが HTML であることを表す
PUBLIC → DTD が、特定の機関などにより、公知されたものであることを表す
"-//W3C//DTD HTML 4.01//EN" → 文書のフォーマット識別子を記述
(FPI=フォーマル公開識別子、という書き方に従う)

FPI のフォーマットの解説:
「//」 は区切り文字
W3C → 所有者識別子
DTD → 公開文種別
HTML 4.01 → 公開文記述
EN → 公開文言語

(先頭は、ある規格に基づく機関は +// それ以外は -// ではじまる)

[Silverlight] Silverlight をはじめる

Silverlight さわってみる

SDK のインストール完了
スタート > プログラム > Microsoft Silverlight 1.0 SDK > QuickStart

Silverlight のプロジェクトには4つのファイルが必要となる。

Silverlight プラグインを読み込む HTML ファイル
silverlight.js
XAML ファイル
JavaScript ファイル( HTML ファイルの補助に使う)

まずは、HTML ファイルとSilverlight.js を同じフォルダに入れる。

Silverlight.js は、デフォルトパスでインストールした場合、
C:\Program Files\Microsoft Silverlight 1.0 SDK\Tools\Silverlight.js フォルダにある

同じフォルダに、こんな内容で、createSilverlight.js を作成する。
function createMySilverlightPlugin()
{
  Silverlight.createObject(
    "myxaml.xaml",          // ソースプロパティの名前
    parentElement,          // DOM reference to hosting DIV tag.
    "mySilverlightPlugin",     // プラグインのユニークID
    // 各インスタンスの記述
    {
      width:'300',        // プラグインエリアの幅
      height:'300',         // プラグインエリアの高さ
      inplaceInstallPrompt:false, // バージョン違いの場合にプロンプトを出すか
      background:'#D6D6D6',     // プラグインエリアの背景色
      isWindowless:'false',     // ウィンドウレスモード←?でプラグインエリアを表示するか
      framerate:'24',       // フレームレート
      version:'1.0'         // 使用する Silverlight のバージョン
    },
    {
      onError:null,         // OnError を処理する関数
      onLoad:null         // OnLoad を処理する関数
    },
    null);              // イベントハンドラの関数名
}

次に、HTML ファイルの <head> と </head> タグの間に、
Silverlight.js と、craeteSilverlight.js を読み込むための
<script> タグを埋め込む

<head>

<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="createSilverlight.js"></script>

</head>

Silverlight を表示させるため、
<body> と </body> タグの間に次の記述を埋め込む

<body>

<!-- Where the Silverlight plug-in will go-->
<div id="mySilverlightPluginHost">
</div>

<script type="text/javascript">

var parentElement = document.getElementById("mySilverlightPluginHost");
createMySilverlightPlugin();

</script>


</body>

<div>タグの id= の値は好きに変えてかまわない(.jsと統一すること)

表示された。次々ー。


2007/09/11

[Silverlight] Silverlight とは

Silverlight とは
クロスブラウザ(複数のブラウザ上で動く)
クロスプラットフォームのブラウザ用プラグイン。
http://www.microsoft.com/japan/silverlight/

Flash の対抗技術として紹介されているように
ユーザに、ブラウザ上でのグラフィカルなインタフェースを提供する。
Flash はコンテンツを swf ファイルで提供するために、
バイナリへのコンパイルが必要だが、
Silverlight は XAML と呼ばれる 拡張 XML の記述のみで
作成可能であるため、テキストエディタさえあれば作成できる。

SDK は 1.0 Beta、1.1 Alpha が提供されており、
ランタイムは 1.0、1.1 Alpha が提供されている。

対応ブラウザは
InternetExplore 6 or 7
Firefox 1.x or 2.x
Safari

対応 OS は
Windows
Macintosh
(Linuxは現在対応中)

Google で検索したら、
Silverligth という誤表記もちらほら出始めてるなー。
Silverligth で Google 検索

[Silverlight] Silverlight 入門

【ハウツー】ゼロからはじめるSilverlight
http://journal.mycom.co.jp/articles/2007/08/16/silverlight/menu.html

すごく分かりやすい!

大抵の解説ページが、SDK の QuickStart をなぞって、
おかげでいきなり .js 書いたり オブジェクト定義したり
HelloWorld ってレベルじゃねーぞ!
となっているけど、これはシンプルな HTML + XAML から解説してる。

■まずは XAML を書いてみる
「hello.xaml」
<TextBlock xmlns="http://schemas.microsoft.com/client/2007" FontSize="20">
Hello World!!
</TextBlock>

■次に、HTML からそれを読み込む
「hello.html」
<object type="application/x-silverlight" width="200" height="100">
<param name="source" value="hello.xaml">
</object>

これで Hello World!! が表示された

■XAML で使える要素について
MSDN にあります

Silverlight Reference
http://msdn2.microsoft.com/en-us/library/bb188567.aspx

■object タグについて
HTML 中から、動画や音声、Flash などのプラグインを
参照するためのタグ。

詳しく知りたい人は
W3C が公布する HTML の標準仕様、 HTML 4.01 の邦訳を
公開してくれている方がいるのでそちらを参照のこと
http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/struct/objects.html#h-13.3

■<HTML> や <BODY> がないことについて
ブラウザ依存ですが、大抵のブラウザは拡張子さえ .html にしておけば
これらのタグが無くても解釈してくれるので、
こういう <object> タグだけの HTML ならいちいち書かなくてもいいんじゃないか

[murmur] ERROR_NOACCESS

RegSetValueEx した結果、どうしても 998 が返ってくる。
#define ERROR_NOACCESS 998L

KEY_ALL_ACCESS 設定しても駄目。
RegOpenKeyEx は ERROR_SUCCESS なのに。

と思ったら、書き込み用データのアドレスに
(UCHAR*)data を渡していた。
本来は (UCHAR*)&data と、アドレスにしてやらないといけない。

ERROR_NOACCESS って、
レジストリにアクセスできないんじゃなくて
データの方にアクセスできてなかったのか…。


2007/09/12

[inside] undefined reference to `WinMain@16'

MinGW に含まれている g++ を使って、
ちょっとしたソースをコンパイルしようとしたら、
こんなエラーが出てきた。

<built-in>:89:1: warning:
this is the location of the previous definition
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x104):
undefined reference to `WinMain@16'

なぜ `WinMain@16' が未定義といわれるのですか?
http://www.sixnine.net/cygwin/translation/faq/faq_3.html#SEC91

このソース、もともと DLL 用に書いたもので、
今回、なんとなく exe として作り直そうとしていたので、
main 関数を書いてなかったのだ。

int main (int argc, const char **argv){ return 0; }
を付け足したところ、確かにコンパイルが通った。

他には、まとめて .exe にリンクするので main() なくていい
.o だけ欲しいってやつをコンパイルするのは
-c オプションでよかったんじゃないかなー。


2007/09/13

[Eclipse] Eclipse+CDT+MinGW+MSYS で JNI

JNI とは
Java Native Interface

JNI は C や C++ で作った DLL 内のルーチンを
Java から呼ぶことを可能とする技術。

まずは Java で Class を作成し、その中に
native なメソッドを宣言する。

そのまま .class を作成し、
javah で .class から .h を抜き出してやる。

この .h を使って作った DLL は、
Java のコードから使えるようになる。

まずは、Eclipse で開発環境を整える。

JNI 自体は、c を解釈できて、
DLL が作れるコンパイラがあれば、
それで使える技術だが、
なぜか Eclipse のプラグインにある
CDT(C/C++ Development Tooling)

で説明しているページが多いので、そこから説明する。

でも Visual Studio 使ったほうがいいよ。
というわけで、VC 使う人ここから大分飛ばしてください。

Eclipse の CDT に関するページ
http://www.eclipse.org/cdt/
わざわざここから落とさなくても
ヘルプ > ソフトウェア更新 > 検索とインストール
に CDT があるので、そこから落とすと良い。

CDT が入ると、パースペクティブに、
C/C++ Development 用の物が増えるので、それを開く。
これで、C のプロジェクトが作れるようになる。

しかし…コンパイラは付属してません。笑

これって、ひどくないですか。

標準で作られる makefile
(C の コードをコンパイルするために実行されるコマンド群)
では、gcc と make が呼ばれているので、
DOS プロンプトで gcc と make が実行できる状態にしないといけない。

MinGW と MSYS のダウンロード
http://sourceforge.net/project/showfiles.php?group_id=2435

MinGW とは
Minimalistic GNU for Windows
GNU のコマンドである gcc や g++ を
Windows 環境から利用するためのツールである。

勿論、gcc で Windows アプリケーションを作ることもできる。

MSYS とは
Minimal SYStem
MinGW をサポートし、configure など
コンパイル必要な最低限の UNIX 環境を構築するツールである。

Cygwin と違って UNIX 環境すべてを Windows 上に構築するわけではない。
ソースのコンパイルだけなら MSYS と MinGW で行える。

で、MinGW と MSYS が入って
DOS プロンプトから
gcc
make
がそれぞれ動くようになったら、
Eclipse の方で作った C プロジェクトも
無事にコンパイルできるようになっています。

長かった。

ここから、VC の人もよく聞いてください。

javah により取り出した .h を見てみると、
JNIEXPORT 戻り値 JNICALL
という関数があるので、これを実装します。

そのままビルドして DLL を作成します。
ただし、ビルドする際に
Java の SDK フォルダ\include
以下にある全てのヘッダが必要になるので、
(win32 の 中身も)
gcc なら コンパイル時にオプションで渡すか、
MinGW なんかのルートにある include に入れておく、
VC はインクルードパスの追加(オプションあたりからできるから)
で、これらのヘッダを参照可能にしておくこと。

あとはこの DLL を、Java のクラス内で
static {
    System.loadLibrary("name");
    // name は dll の名前、 .dll を抜かしたものを指定すること
    // test.dll を作ったのなら loadLibrary("test")
}
などで最初に読み込んでおき
native で宣言してあったメソッドを呼ぶと
DLL 内のルーチンが実行される。

注意として、
DLL はそのクラスから参照できるパスにおいておくこと
java.library.path みたいなのがあったと思うけど
クラスのルートに置けばチェックはできる
(loadLibrary の成否を見ること)

それから、
gcc 系のコンパイラは
main が無いとエラー吐いたり、
DLL 内で使う API によっては gcc へのオプションが必要だったり
なにか引っかかった場合はちゃんとエラーメッセージを読み、
分からない場合はエラーメッセージで検索すること。

新潟大学信号処理教室の方々が
少なくとも僕の環境
Eclipse 3.2
JDK 1.5.0_12
CDT 3.1.2
Visual C++ 6.0
MinGW 5.1.3
MSYS 1.0.10
で VC gcc ともに JNI に成功した
良質なサンプルを提供してくださっているので、それを参考にすること。
http://telecom0.eng.niigata-u.ac.jp/index.php?Java/JNI


2007/09/14

[murmur] お仕事募集中

ヨルノデンキクラゲでは、お仕事を募集中です。
プログラムに関することであれば、なんでも構いません。

スキルとしては、
プログラマとしての活動が十数年。
ソフトウェア開発技術者
TOEIC700点
Java(サーバ、クライアント)
C C++ VC MFC
Ruby Perl PHP
の開発実績があります。

まずはこちらにご連絡ください。
yoruno.dだみーgmail.com

だみーはアットマークに置き換えてください。

[inside] DOS プロンプトでファイル名の補完

DOS プロンプトでファイル名の補完を行う。
といっても Windows XP では標準搭載の機能。

しかし、これにまつわるレジストリキーが
HKEY_CURRENT_USER の Software\Microsoft にあったらしく、
そこを誤って削除してしまったので、
再設定しなければいけなくなった。

まずは
HKEY_CURRENT_USER\Software\Microsoft を見ると
Command Processor がなかったので、
右クリック→キーの追加→Command Processor とする。

次に
HKEY_CURRENT_USER\Software\Microsoft\Command Processor
に移動し、DWORD 値の作成で、
変数名を CompletionChar 、値を9に設定し、
cmd.exe を起動しなおしたところ、無事に補完が復活した。

[murmur] explorer.exe の再起動 バッチの wait

自作アプリを作ってる最中に、
explorer.exe を再起動する必要が出てきた。

あまり explorer.exe を再起動したいという
需要は無いだろうけど、再起動は次のやり方で可能。

taskkill /IM explorer.exe /F
start explorer.exe

しかし、このやり方で再起動したところ、
どうも Windows キーが効かなくなってしまう。

もう一度同じバッチを起動すると、
今度は Windows キーが有効になる。

どうやら、2回に1回、Windows キーの有効と無効が
切り替わってしまうようだ。

これは恐らく、
taskkill によって explorer.exe を終了しても
すぐに explorer.exe が終了するわけではなくて、
その後処理が行われているのだと思う。

新しい explorer.exe が立ち上がった後に、
Windows キーの有効無効にまつわる処理が行われれば、
こういう現象になる。予想。あくまで。

実際に、
taskkill /IM explorer.exe /F

start explorer.exe
を時間を置いて実行した場合は、
Windows キーは無事に復帰した。

では、この2つの行の間に、
ウェイト処理を入れたらどうだろうか。
bat で ウェイトを行う方法を僕は知らないが、
調べたら次のようなテクニックが出てきた。

ping localhost
(絶対に成功する)

ping -n %x
(指定回数のping送信)

ping > nul
(結果を破棄)

これらに、ping の送信間隔が1秒であることを利用して
@echo off
ping localhost -n %x > nul
%x に ウェイトさせたい秒数 + 1 を設定する

これで無事に、
explorer.exe を再起動し、
Windows キーも復帰させることができた。

[murmur] …シェルエクステンションって?

Explorer.exe の再起動をすると
Windows + M (全ウィンドウを隠す)が効かなくなってしまう。
なぜなのかは不明。

Windows + D は厳密には動作が違うので、困った。
意外と多用してたみたいで、押してからアレッと思う。

そもそも Windows + M って何をやってるんだ、と思って
調べたら

クイック起動バーに [デスクトップの表示] アイコンを再登録する方法
http://support.microsoft.com/kb/190355/ja

そうそう、全ウィンドウを隠すっていうか、
デスクトップの表示っていうショートカットだった。

で、こいつに対するショートカットをさらに作って、
ショートカットにはショートカットキーが設定できるので、
好きなキーでいつでもデスクトップが表示できる。

それで、連打したらタスクバーが死んだ笑。なぜだ。

scf ってなに?
Windows エクスプローラ コマンド

内容はテキストで、iniファイルと同じ形式。
内容はシェルエクステンションと同じで、
[shell]セクションに Command , IcomFileの値、
[Taskbar]セクションにCommandの値がある。

シェルエクステンションってなんだろ。後で調べよう。

そういえばスタートアップメニューに
Power Witch the Royal
ていうリンク切れのメニューがあって、
なんだこれと思って調べたら、バイナリエディタだった。

使ったことあったかな?

[murmur] Brew のプロジェクトを作成する

久しぶりなので、すっかり手順を忘れていた。

ファイル→新規作成→プロジェクト→BREW Application Wizard

BREW Application Wizard - ステップ 1 / 2 と表示されるので、
使用する機能を選んで『次へ (N)>』

『MIF Editor』をボタンから起動。 (ウチの環境だとなぜか2回押す必要がある)

『新規アプレット』を選択、
『名前』に適当な名前を入れて、(今回はtest)
ラジオボタンの『ローカル』をチェックし、
『ClassID』に適当な数値(今回は1010)を入れて
『生成』をクリック。

---------------------------
BREW(tm) MIFエディタ
---------------------------
ローカルにClassIDを生成してよろしいですか?
---------------------------
はい(Y) いいえ(N)
---------------------------

『はい(Y)』を選択。
*.bid ファイルをプロジェクトフォルダに保存。
(名前はアプレットの名前と統一する)

『アプレット』の種類にツールを選択。
ファイル→保存 から *.mif ファイルを、
プロジェクトフォルダに保存。
(名前はアプレットの名前と統一する)

ファイル→終了 で MIF Editor を終了する。

BREW Application Wizard - ステップ 2 / 2 で『終了』を押して、
生成されたファイルを確認して、プロジェクトの作成終了。

プロジェクトに次のファイルが生成されている。
アプレット名.c
AEEAppGen.c
AEEModGen.c
下の二つは、BREW 用の API が記述されている。
本体は SDK のフォルダに格納されているので、編集してはいけない。

[murmur] Brew で Disabled This app was disabled to save space

とりあえず実行してみる。

Disabled
This app was disabled to
save space. Would you like
to restore it now?

Restore Cancel

こんなメッセージが表示された。
そうだそうだ。

BREW の ディレクトリ構成

test という名前のアプリがあったら
MIFフォルダに
test.mif
test\test.dll

という構成でファイルを置かないといけないのだ。
で、MIF フォルダはエミュレータへの引数で変えることができる。
それと、Visual Studio は標準で、debug フォルダ以下に dll を出力するが、
これもプロジェクトの設定から変えられる。

プロジェクトのフォルダに MIF を置いて
プロジェクト→設定→一般→出力ファイル に test と入力し、
プロジェクト→設定→デバッグ→プログラムの引数 に
-m "MIFフォルダがある場所" としておくと、
プロジェクトが増えたときにファイル容量を気にする必要も無い


2007/09/18

[murmur] フタエノ キワミノ

フタエ!フタエノキワキワミ!
キワミ!キワミノフタフタエ!
アアン、アアン ← ここで腹筋が壊れる笑

[murmur] Visual Studio 6 でプログラムの引数にマクロを指定する

やり方がわからない。

例えば、
プロジェクト→設定 の
カスタムビルドやビルド後の処理であれば、
echo "$(OutDir)" のようにして、
出力ディレクトリを echo させることができる。

これのやり方で、
デバッグの実行ファイルにエミュレータを
引数に出力パスを指定したい場合は、
プロジェクト→設定→デバッグ→プログラムの引数
に $(OutDir) を渡せばいいと思ったのだけど

デバッグセッションの実行可能ファイルに
notepad.exe
引数に $(OutDir) で試してみたら
$(OutDir).txt は存在しないか開けません
と出てしまったので、展開されないみたい。

うーむ。

[murmur] 日本の平均労働時間

日本人の平均労働時間は、年間1800時間を下回り
http://www2.ttcn.ne.jp/~honkawa/3100.html
http://www.nikkei.co.jp/news/main/20070903AT2M0300903092007.html

さらに減り続けてるんだそうだ

うん、サービス残業を続ける輩が居る限り、正しいデータは出てこない。

声を出す勇気を持とう。それとも、文句が言えないような仕事ぶりなのかな

[murmur] クジノカワ 鬮野川

読めなかった。愛媛県らしい

[murmur] BREW メモ

ISHELL_CreateInstance() したものは
ISHELL_Release() ではなくて XXX_Release により解放する

コールバック関数は、CALLBACK_Init マクロ関数によって設定する。

BREW SDK における、
デバッグ時、リリース時のコンパイルオプションは
AEE_SIMULATOR を使う

BREW では C の標準関数
SPRINTF MEMCMP MEMSET などは
AEEStdLib.h にマクロとして定義されている

BREW のコードは、C 言語を用いて書かれているので
(標準の話。工夫すれば C++ にも対応できるらしい)
変数宣言を冒頭に書かないと

error C2143: 構文エラー : ';' が 'type' の前に必要です。
error C2065: 'XXX' : 定義されていない識別子です。

のようなエラーが出る。
これは C++ では通常、
存在しない型名で変数を定義したときに現れるエラー。

BREW のエラーコードは
AEEError.h に格納されている

BREW では、HTTP のレスポンスで
サーバに到達する前にエラーが発生したときは
マイナスの値が返って来る。
これは、サーバー側のレスポンスコードが 400 200 など、
正の値で規定されているからで、それと被らない工夫。

各コードは
WEB_ERROR_BASE 0x500
をオフセットとしたマイナスの値になる
例えば、 WEB_ERROR_ADDRUNKNOWN (WEB_ERROR_BASE+8)
は 10 進数で 1288 だが、 -1288 として返って来る。

WEB_ERROR_ADDRUNKNOWN が返ってくる → URL を IP で指定してみる
WEB_ERROR_CONNECT → URL を static な領域に保存していない可能性がある
WEB_ERROR_UNSUPSCHEME → URL に http:// がついていない
WEB_ERROR_CONNECT → お手上げ ネットワーク制限かも
(追記)

と思ったら、いつの間にか出力ディレクトリがリセットされてて
(なんでだろう?)プロキシの設定とか有効になってない dll を
延々実行していたようだ。

↓このメッセージが出てたら要注意、笑。
プリロードされたシンボルは 'XXX.dll' とマッチしないかもしれません。

IWEB_GetResponse( web,
    (web, &resp, &callback, url,
    WEBOPT_HANDLERDATA, data,
    WEBOPT_METHOD, "GET",
    WEBOPT_STATUSHANDLER, handler,
    WEBOPT_PROXYSPEC, "*:///http://proxy:8080",
    WEBOPT_END));

WEBOPT_PROXYSPEC について書いてるページがなかなかないので
いちおうプロキシはこうやって設定しますってことでのせとく


2007/09/19

[murmur] BREW の出力ディレクトリが大文字だと

エミュレータで実行時に、次のような警告が出る
*launcherview.c:521 - ______________________________________________________
*launcherview.c:524 - 大文字と小文字の混在するか大文字のファイル/ディレクトリ名が見つかりました
*launcherview.c:527 - - 以下のアプリケーションはシミュレータで正しく動作しない可能性があります -
*launcherview.c:529 -
*launcherview.c:582 - アプリケーション:Debug、原因:"Debug" ディレクトリ
*launcherview.c:534 - ______________________________________________________
*launcherview.c:534 - ______________________________________________________

もちろん、大文字のディレクトリをやめればよい
プロジェクト→設定→一般→出力ディレクトリ
から
中間ファイルと出力ファイルのディレクトリ名を変更する

(追記)

と思ったら、ここに小文字の名前を入れても、
デバッグファイルは大文字ではじまるDebugとして作成される

幸い?Windows は大文字と小文字を区別しないし、
ディレクトリを逐一生成するわけでもないので
一度 Debug ディレクトリができたら小文字にリネームしてしまおう

[murmur] プリロードされたシンボルは…

VisualStudio がまれに出す警告
プリロードされたシンボルは 'XXX' とマッチしないかもしれません。

コンパイルに使ったコードと、デバッグに使っているファイルが
一致しないときにこれが出ます

他には、VisualStudio のバージョンが古いとか
ようするに、VisualStudio はファイル 'XXX' に対して、
大まかにファイルの中身を予想しているけど
その予想と違うかもしれないときに出る警告。

デバッグでロードされているファイルが本当に
自分が想定していたファイルであるかをデバッグウィンドウで確認。
それから、ちゃんと更新されているかタイムスタンプも確認しましょう。

[inside] スタートアップルーチン crt0.c

CRT0.C は「スタートアップルーチン」と呼ばれるものだ。

F10 や F11 はデバッグにおける、
ステップオーバやステップインのショートカットキーだが、
デバッグ中でなくても実行できる。
その場合、スタートアップルーチンからデバッグが開始する。

スタートアップルーチンは、
スタックの初期化などプログラム実行に必要な処理を行い、
最後に main 関数を呼び出す。

[murmur] mshtml.h の IHTMLStyle らへんでエラー

#include <mshtml.h>
をインクルードしたプロジェクトをコンパイルしたら

コンパイル中...
XXX.cpp
c:\program files\microsoft visual studio\vc98\include\mshtml.h(26) :
error C2146: 構文エラー : ';' が、識別子 'IHTMLStyle' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\mshtml.h(26) :
fatal error C1004: 予期せぬ EOF が検出されました。
cl.exe の実行エラー
ブラウザ データベースを作成中...

と表示されて、IHTMLStyle が未定義なのか? と思って
IHTMLStyle で検索したけど、どのヘッダに含まれてるとかの
情報は引っかからなかった。

そこで mshtml.h で検索したら
その前で #include <shlobj.h> してるソースを見かけたので、
その通りにしたら動いた。納得いかないー。

[murmur] LPFNOBJECTFROMLRESULT が定義されてるヘッダ

oleacc.h でした。

例によって
コンパイル中...
XXX.cpp
XXX.cpp : error C2065: 'LPFNOBJECTFROMLRESULT' : 定義されていない識別子です。
cl.exe の実行エラー
ブラウザ データベースを作成中...

が出たので LPFNOBJECTFROMLRESULT で検索すると

#include <oleacc.h>

しているコードを見つけた

コードスニペットをもってくるときって、
その人が、プロジェクトのウィザードでオプションを選択して
StdAfx.h やらなにやらでヘッダが追加されてる可能性があるので、
とりあえず 定義されていない識別子です→検索。

[VC] プロセスを列挙する

なんというか、[VC]というカテゴリを
作ろうか作るまいかで悩んでいたのだけど、
厳密には Windows API とか MFC とか .NET とか
違うものだからそれをさらに分けるのが面倒で、
結局[inside]にしてきた。

でも僕自身、見つけたコードが
Delphi だったり VB だったり WSH だったりで
面倒だったことが何度もあるので、
ひとまず[VC]で運用してみる。

プロセスの列挙だけど
EnumWindows() がウィンドウの列挙なので、
それを使っても実現できる。

でも EnumWindows() は非同期だから、
コールバックが必要でなんだか使いづらい。

というわけでプロセスのスナップショットを取得する。

#include <tlhelp32.h>

HANDLE hSnap;
PROCESSENTRY32 pe;
ZeroMemory( &pe, sizeof(pe) );
pe.dwSize = sizeof(pe);

hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( hSnap == INVALID_HANDLE_VALUE ) {
    return; // error
}
BOOL bNext = Process32First( hSnap, &pe );
while ( bNext ) {
    bNext = Process32Next( hSnap, &pe );
}
CloseHandle( hSnap );

pe から プロセスID とかプロセスにまつわる情報が取れる。


2007/09/20

[murmur] interface = インタフェース? インターフェイス

コンピュータに関わっていると、
インタフェースという単語をよく目にする
Java なんかには機能として用意されているので当たり前だが

これの読みが、ドキュメントによって違う
こういう表記ゆれは、Google で多数派を探してみると面白い
ここに現時点で検索した結果をのせておく

まずは極端にー(長音符と読む)を排して
インタフェイス
これは 484,000 件 と結果が少ないうえに
もしかして: インターフェイス と、
ありがたいアドバイスまでいただいてしまう。笑

次にインタフェース
Google の親切な表記ゆれ補正をオフにするため
"インタフェース" で試す
6,070,000 件

"インターフェイス"
8,610,000 件

どうもインターフェイスが多数派のようだ


2007/09/22

[VC] CreateProcess したプロセスの HWND を取得

ようするに、プロセス ID からウィンドウハンドルを取得しよう
ということ。

STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
ZeroMemory( &pi, sizeof(pi) );
CreateProcess( exe, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
(各引数は自分で調べてみて)

ヒントとして、引数 exe でファイルを指定するならフルパスでないといけない。
cmd の方は本来は exe への引数を記述するけど、
パスが通っているファイルならば、cmd に記述して実行できる。

すると、pi に
dwProcessId
dwThreadId
があるのだけど、このうち dwThreadId を使って、
今しがた生成したプロセスのウィンドウハンドル HWND を取得する

考え方としては
HWND と プロセス ID は紐づいている
たった今作ったプロセスのプロセス ID はわかる
HWND の一覧を取得する方法がある

から、HWND の一覧から各 HWND のプロセス ID を調べ、
生成したプロセスのプロセス ID と一致したら、
その HWND が生成したプロセスの HWND である。

(しかし、HWND から一発でプロセス ID が取れるのに、逆が無いとは…)

HWND を列挙するには、
EnumWindows を使用する。

こいつは、引数にコールバック関数を渡すと、
「各 HWND」 に対して、そのコールバック関数を実行してくれる。
だから、プロセス ID の比較を行うようなコールバック関数を渡せばいい。

ん、コールバック関数?
一応説明すると、コールバック関数というのは、

コールバックの説明開始…

いつ終わるか分からない処理などに設定しておくことで、
その処理が終わったときに自動で呼ばれる関数のこと。

例えば通信処理が終わったときに、その結果をみて処理を行いたいとする。
しかし、通信処理はすぐにリターンし、通信はバックグラウンドで行われ、
通信速度など、状況によって終了までの時間も変わる場合を考える。
通信処理のあとにすぐにリソースの開放などを行うと、
通信はバックグラウンドで進行中(リソースも使用中)なので、誤動作を引き起こす。
かといって、適当に Sleep(60*1000)では、
通信がすぐに終わっても1分は待たなくてはいけないし、
1分を超える通信が発生した場合は、やはり誤動作を引き起こす。

そこで、通信が終わったときに呼ばれる関数を設定できれば、
上手い具合に後処理が行えるんじゃないだろうかと考えたらすごい。
そういう呼ばれ方をする関数がコールバック関数。
関数は関数ポインタとして何かに代入しておくことが出来るので
それを使って実現されてる。

…コールバックの説明終了

で、どうしてEnumWindows にコールバック関数が必要かというと、
この関数が非同期で処理を行うから。

非同期ってのは、関数の呼び出し自体はすぐにリターンして、
バックグラウンドで処理が行われている間に
メインの処理は再開されてしまう。とかそんなイメージ。

どうも、確実に存在しているウィンドウだけを返すには
どうしても時間がかかるようで、非同期になってるみたい。
だから、各 HWND に対してコールバック関数を呼ぶカタチで処理を行う。

EnumWindows の書式は、
BOOL EnumWindows(WNDENUMPROC lpEnumFunc , LPARAM lParam)
第1引数がコールバック関数
第2引数がコールバック関数へ渡す引数である。
コールバック関数は各 HWND に対して処理を行うが、
その結果は、この第2引数にデータのポインタを渡し、
コールバック関数内でその値を変化させて受け取る。

コールバック関数の書式は
BOOL CALLBACK EnumWindowsProc(HWND hwnd , LPARAM lp)
となっている(名前は自由に変えてかまわない)
第1引数に各ウィンドウの HWND が入り、
第2引数には、先ほど EnumWindows で第2引数に指定したものが入る。

実際にこれらを使って、
CreateProcess で notepad を起動して、
その HWND を取得、
タイトルバーの文字列を変化させるところまでやってみよう。

ファイル→新規作成→プロジェクト→Win32 Application→空のプロジェクト
で以下のコードを挿入

#include <windows.h>

typedef struct {
    DWORD    id;
    HWND    hw;
} MYDATA, *LPMYDATA;

BOOL CALLBACK EnumWindowsProc( HWND hw , LPMYDATA pMy )
{
    int id = GetWindowThreadProcessId( hw, NULL );
    if( GetWindowThreadProcessId( hw, NULL ) == pMy->id ) {
        pMy->hw = hw;
        return FALSE;
    }
    return TRUE;
}

INT APIENTRY WinMain(
    HINSTANCE    hInst,
    HINSTANCE    hInstPre,
    LPSTR        lpCmdLine,
    INT            nCmdShow )
{
    MYDATA my;
    PROCESS_INFORMATION pi;
    STARTUPINFO si;

    ZeroMemory( &my, sizeof( my ) );
    ZeroMemory( &si, sizeof( si ) );
    si.cb = sizeof( si );

    // メモ帳を起動
    CreateProcess( NULL,"notepad",NULL,NULL,0,0,NULL,NULL, &si, &pi );
    // 作成したプロセスの初期化が完了するまで待機
    WaitForInputIdle( pi.hProcess, 1000 );
    my.id = pi.dwThreadId;

    EnumWindows( (WNDENUMPROC)EnumWindowsProc, (LPARAM)&my );

    // メモ帳の HWND が取得できればループを脱出
    while( my.hw == 0 ) {
        Sleep( 100 );
    }

    // 起動したメモ帳のタイトルバーの文字列を変更
    SetWindowText( my.hw, "メーモー帳" );
    return 0;
}

キーワード
API,プロセスを作成,プロセスID,プロセスのHWND,プロセスからHWND
全てのウィンドウハンドル,全ウィンドウハンドル,タイトルバー
プロセスを待機,外部からexeを起動,起動したexeに引数


2007/09/23

[murmur] piがπとして表示されてしまう

コードを HTML として表示するときに
(恐らくそのまま出してくれるプラグインがあるとは思うが)
PROCESS_INFORMATION pi;
&pi = …
が、
PROCESS_INFORMATION pi;
π = …
と表示されてしまっていた。

これは、HTML の実体参照と呼ばれる
> や < を &gt; や &lt; と記述するやりかたに
πも&pi; として含まれていて、
多分後ろのセミコロンが無くても変換されるケースがあるからだ。
(スペースとか入っている場合かな)

これを意図どおり表示するには
実体参照の先頭の & そのものを実体参照で
を &amp; と書けばいい。

キーワード
πを表示,パイを表示,実体参照,piをパイとして
HTMLで不等号を表示,HTMLで記号を表示


2007/09/24

[Ruby] Ruby でビット反転

Packer and Loader なアプリを作ろうと思って、
C でビット反転のソースを書いていたのだけど、
そういえば Ruby でビット反転って
どうやるんだろうと思って、思いついたのがこれ。

修行が足りない感じ。どなたかスマートなやり方を教えてください。

src = nil
filename = "ファイル名"

open( filename, "rb") { |f|
    src = f.read
}

# ビット反転前
p src.unpack("b*")
dst = [ src.unpack("b*")[0].gsub('0','o').gsub('1','0').gsub('o','1') ].pack("b*")

# ビット反転後
p dst.unpack("b*")

open( filename + ".bin", "wb") { |f|
    f.write dst
}

解説
バイナリでファイルを読み込んで
(その場合 String に入るので)
2進文字列に unpack し、0と1を
(気持ちの悪い方法で)入れ替えた後にまた pack


2007/09/25

[murmur] printf のフォーマット指定子と引数の数

フォーマット指定子よりも多い引数を渡したら、
一体どういう動作をするんだろうと思って調べたら、
どうも多めに渡した引数は無視されるらしい。
フォーマット指定子よりも少ない引数はエラー。

[murmur] 最近使ったファイルについて

最近使ったファイルを追加させない
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
値の追加 DWORD 値で、名前を NoRecentDocsHistory 値を 1 に設定
再ログイン後に有効になる。
(追加されなくなるだけでなく、これまでの履歴も表示されなくなる)

最近使ったファイルメニューを非表示にする
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
値の追加 DWORD 値で、名前を NoRecentDocsMenu 値を 1 に設定

最近使ったファイルメニューの表示数を増やす
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
値の追加 DWORD 値をで、名前をMaxRecentDocs 値を表示したい件数に設定

最近使ったファイルの場所
C:\Documents and Settings\ログインユーザ名\Recent

[murmur] nvlog.txt って

C: 直下を整理していたら、
nvlog.txt ってファイルが出てきたけど、
検索しても日本語のページは引っかからない。

海外のフォーラムで、NVIDIA のドライバのログなんじゃないのかと意見が。
んー。たしかに NVIDIA のビデオカードだなあ。
中身も空。とりあえず消去したメモ。
(追記)
pod2html.dir、pod2html.itm も削除
ActivePerl 関連のファイルなのではとのこと
APInstall.log も削除(中見たらActivePerlのインストールログ)

TcpCheckResult.txt も削除(用途不明)
PPM.log も削除(多分 Perl の PPM が置いたファイル)


2007/09/26

[murmur] アサヒる

捏造とか売国とか、いろんな意味があるらしい笑
購読者数も年々減少しているし、
いい加減に自分達がどんな目で見られているか気づけばいいのに


2007/09/27

[murmur] Java サーブレットでわざとタイムアウト

Java のサーブレットで強制的にタイムアウトを起こさせるには
サーブレットの doPost や doGet 内で
Thread.sleep( 60000 );
のようにして、処理を停滞させる。

[inside] Brew で IWeb を使って POST を行う

■まず HTTP 通信ってどうやるの?
→IWeb のインターフェイスを使う

■IWeb のインスタンスの作成

IWeb* pWeb として
pWeb = NULL;
ISHELL_CreateInstance( shell, AEECLSID_WEB, (void**)(&pWeb) );

■IWeb のインスタンスの解放
if ( pWeb ) {
IWEB_Release( pWeb );
pWeb = NULL;
}

■IWeb のリクエストの生成
IWEB_GetResponse( … );

POST するときは引数に

WEBOPT_METHOD, "POST",
WEBOPT_BODY, ポストするデータ,
WEBOPT_CONTENTLENGTH, ポストするデータの長さ,

とすること

ドキュメントによると、ポストするデータには (ISource *) を指定する
ISource?
実際には IPeek へのポインタを指定すればよい

■IPeek を作成する手順

ISourceUtil* util = NULL;
ISHELL_CreateInstance( shell, AEECLSID_SOURCEUTIL, (void**)(&util) );

ISOURCEUTIL_SourceFromMemory(
    util,
    data, // void* でデータへのポインタを渡す
    size, // int32 でデータ長を渡す
    NULL,
    NULL,
    (ISource**)&m_pIPeek
);

ISOURCEUTIL_Release( util );
util = NULL;

ポスト用のデータ用を作成するための自作クラス CPostData
のサンプルで示す

■ヘッダファイル
#include "AEEShell.h" // Shell interface definitions
#include "AEESource.h" // WebOpt interface definitions

#ifndef __POSTDATA_H__
#define __POSTDATA_H__

class CPostData{
public:
    CPostData( IShell *pIShell );
    ~CPostData();

    IPeek* GetPeek();

    void Reset();
    void Push( const char* name, const char* data, int len, bool b64 = false );
    void PushBase64( const char* name, const char* data, int len );
    void CreatePeek();
    int GetSize();

private:
    IShell* m_pIShell;
    IPeek* m_pIPeek;
    char* data;
    int size;
};

#endif

■ソースファイル
#include "AEEStdLib.h"
#include "AEEWeb.h"
#include "postdata.h"

CPostData::CPostData( IShell *pIShell )
{
    m_pIShell = pIShell;
    m_pIPeek = NULL;
    data = NULL;
}

CPostData::~CPostData()
{
}

IPeek* CPostData::GetPeek()
{
    return m_pIPeek;
}

int CPostData::GetSize()
{
    return size;
}

void CPostData::Reset()
{
    FREEIF( data );
    data = NULL;
    size = 0;

    if ( m_pIPeek != NULL ) {
        IPEEK_Release( m_pIPeek );
        m_pIPeek = NULL;
    }
}

void CPostData::PushBase64( const char* name, const char* value, int len )
{
    Push( name, value, len, true );
}

void CPostData::Push( const char* name, const char* value, int len, bool b64 )
{
    IShell * shell = m_pIShell;
    IWebUtil *util = NULL;
    ISHELL_CreateInstance( shell, AEECLSID_WEBUTIL, (void**)(&util) );

    int nameLen = STRLEN( name );
    int equalLen = STRLEN( "=" );
    int andLen = STRLEN( "&" );
    int dataLen = 0;

    char *base64 = NULL;
    if ( b64 ) {
        int lenBase64 = BASE64LEN( len );
        base64 = ( char* )MALLOC( lenBase64 );
        IWEBUTIL_EncodeBase64( util, value, len, base64 );
        value = base64;
        len = lenBase64;
    }

    IWEBUTIL_UrlEncode( util, value, &len, NULL, &dataLen );
    char* buf = NULL;
    buf = (char*)MALLOC( dataLen );
    IWEBUTIL_UrlEncode( util, value, &len, buf, &dataLen );

    // 既にデータがあれば&でつなぐ
    if ( size > 0 ) {
        data = (char*)REALLOC( data, size + andLen );
        MEMCPY( data + size, "&", andLen );
        size += andLen;
    }

    data = (char*)REALLOC( data, size + nameLen );
    MEMCPY( data + size, name, nameLen ) ;
    size += nameLen;

    data = (char*)REALLOC( data, size + equalLen );
    MEMCPY( data + size, "=", equalLen ) ;
    size += equalLen;

    data = (char*)REALLOC( data, size + dataLen );
    MEMCPY( data + size, buf, dataLen ) ;
    size += dataLen;

    // 末端データをつけておくが、size は増やさない
    //(次の Push() 時に size からデータを追加をさせるため)
    data = (char*)REALLOC( data, size + 1 );
    MEMCPY( data + size, "\0", 1 ) ;

    FREEIF( buf );

    if ( util ) {
        IWEBUTIL_Release( util );
        util = NULL;
    }
}

void CPostData::CreatePeek() {
    IShell * shell = m_pIShell;
    ISourceUtil* util = NULL;

    if( SUCCESS != ISHELL_CreateInstance( shell, AEECLSID_SOURCEUTIL, (void**)(&util) ) ) {
        return;
    }

    if ( m_pIPeek != NULL ) {
        IPEEK_Release( m_pIPeek );
        m_pIPeek = NULL;
    }

    ISOURCEUTIL_SourceFromMemory(
        util,
        data,
        size,
        NULL,
        NULL,
        (ISource**)&m_pIPeek
    );

    if ( util != NULL ) {
        ISOURCEUTIL_Release( util );
        util = NULL;
    }
}

■使用方法

CPostData* pPostData = new CPostData();
pPostData->Reset();
pPostData->Push( "query1", "testtest", STRLEN("testtest") );
// BASE64 エンコードも可能
pPostData->PushBase64( "query2", base64_data, base64_size );
pPostData->CreatePeek();

IWEB_GetResponse(

WEBOPT_METHOD, "POST",
WEBOPT_BODY, pPostData->GetPeek(),
WEBOPT_CONTENTLENGTH, pPostData->GetSize(),

);

[murmur] フェッチ fetch と フォーク fork

たまに聞くけど、意味をはっきりと説明できない用語

フェッチ fetch =取り出し

メインメモリにある命令が実行されるまでの流れ

命令のフェッチ
命令のデコード
命令の実行

演算対象をオペランドというが、
オペランドのフェッチは命令のフェッチの後、
命令の実行の前(当たり前)に行われる

フォーク fork = UNIX 系 OS のシステムコール
フォークを呼んだプロセスを複製したプロセスが生成される

関連語:fork 爆弾
ひたすら自分のプロセスを複製する

関連語:wabbit
自己増殖でネットワークを介さないもの。初めて聞いた。

自分でも、ソースを Wikipedia に頼るのはどうかと思う。


2007/09/28

[news] 【格差社会】 “格差拡大” 年収200万以下の人、大幅増の1000万人超え…平均年収は435万円

ソース

仕事してて、やる気も実力もない人が増えてるなーとは感じる。