「ほっ」と。キャンペーン
<   2008年 12月 ( 42 )   > この月の画像一覧
(.Net)RichTextBoxコントロールは勝手に改行コードをLF(ラインフィード)にしてしまう!?
またMicrosoftの陰謀の話です。
(VB.Net)DataObject.GetText()の引数にCSV(TextDataFormat.CommaSeparatedValu)指定時のバグ!? で上げたコードを使ってCSV出力時にセル値の改行コードを取り除く処理をやろうと思ったのですが、なぜか改行が出力されてしまうという現象に出くわしました。
ちなみに、セル値の改行コードを取り除く処理は下記のようにしています。
cell.Value = (cell.Value.ToString()).Replace(vbNewLine, "")
で、どうやらこの原因がデータ入力時に用いているRichTextBoxだということまで至るのに大変時間がかかりました。

RichTextBoxコントロールのMultilineプロパティがTrueなら複数行入力できるのですが、その改行コードが勝手にLF(ラインフィード)にされてしまうのです。
下記のようにコード上から CRLF の文字列を入れても RichTextBox.Text プロパティで取得すると LF だけになってるのです。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'意図的に RichTextBox1 と TextBox1 の双方に CRLF を含んだ文字列を代入
RichTextBox1.Text = "ABC" & vbNewLine & "あ" & vbNewLine
TextBox1.Text = "ABC" & vbNewLine & "あ" & vbNewLine
 
Console.Write("RichTextBox:")
' RichTextBox1.Text文字列をダンプ
DumpString(RichTextBox1.Text)
 
Console.Write("TextBox :")
' TextBox1.Text文字列をバイト配列に変換
DumpString(TextBox1.Text)
End Sub
 
Private Sub DumpString(ByVal str As String)
' エンコーディングはUnicode
Dim sourceEncoding As System.Text.Encoding = System.Text.Encoding.Unicode
'文字列をバイト型配列に変換
Dim bytAry As Byte() = sourceEncoding.GetBytes(str)
For Each value As Byte In bytAry
'16進数2桁でコンソールに出力
Console.Write("{0:X2} ", value)
Next
Console.WriteLine()
End Sub

この結果は下記のようになります。(結果はリトルエンディアンで表示されている)

RichTextBox:41 00 42 00 43 00 0A 00 42 30 0A 00
TextBox :41 00 42 00 43 00 0D 00 0A 00 42 30 0D 00 0A 00

TextBoxのほうは 0x000D 0x000A(CRLF) となっているのに、RichTextBoxは 0x000A(LF) しかありません。
MSDNライブラリには特に明記されていないのでやはりバグでしょうか。それともMS得意の仕様?

ということで、RichTextBoxからTextプロパティで値を取得した後に、LF だけの改行コードを CRLF に直すメソッドを作ってみました。

Private Function Lf_To_CrLf(ByVal src As String) As String
'文字列がnullか空文字の場合
If String.IsNullOrEmpty(src) Then
Return String.Empty
End If
Dim sr As New IO.StringReader(src)
Dim line As String
Dim out As New System.Text.StringBuilder
Do
'StringReader.ReadLine()を使うと3種類の改行コードいずれであっても1行ずつ読み出すことができる。
line = sr.ReadLine()
If line is Nothing Then Exit Do
out.Append(line)
out.Append(vbNewLine)
Loop
'元の文字列に改行がない場合は、上のループでつけた最後の改行コードを削除
If src.Length > 2 AndAlso Not src(src.Length - 1) = vbLf Then
out = out.Remove(out.Length - 2, 2)
End If Return out.ToString()
End Function

このメソッドを最初のコードにつけくわてみます。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RichTextBox1.Text = "ABC" & vbNewLine & "あ" & vbNewLine
TextBox1.Text = "ABC" & vbNewLine & "あ" & vbNewLine
 
Console.Write("RichTextBox:")
' RichTextBox1.Text文字列をダンプ
DumpString(RichTextBox1.Text)
 
Console.Write("TextBox :")
' TextBox1.Text文字列をバイト配列に変換
DumpString(TextBox1.Text)
 
Console.Write("Lf_To_CrLf :")
'LFをCRLFに変換
DumpString(Lf_To_CrLf(RichTextBox1.Text))
End Sub

結果はこうなります。

RichTextBox:41 00 42 00 43 00 0A 00 42 30 0A 00
TextBox :41 00 42 00 43 00 0D 00 0A 00 42 30 0D 00 0A 00
Lf_To_CrLf :41 00 42 00 43 00 0D 00 0A 00 42 30 0D 00 0A 00

ちゃんと L Fが CRLF になってますね。

ちなみに、StringReader.ReadLineメソッドを使うとどの改行コードでも関係なく1行ずつ読み取ることができます。改行コードが混在する際に便利です。
参考:
複数の行を含む文字列から1行ずつ読み出すには?
[PR]
by jehoshaphat | 2008-12-30 00:35 | .Net開発 | Trackback | Comments(0)
(VB.Net)String型変数の値(文字列)を16進数でダンプする
デバッグ中に文字列を16進数でダンプする方法です。

エンコーディングを指定し、そのエンコーディングで文字列をByte型配列にします。
(WindowsはAPI等内部的に文字列はUTF-16で処理しているので、エンコーディングはUnicode(UTF-16)にしておきます。)
その後、数値書式指定でX2で2桁16進数に出力します。
下記は引数に渡された文字列をコンソールに出力する例です。

Private Sub DumpString(ByVal str As String)
' エンコーディングはUnicode
Dim sourceEncoding As System.Text.Encoding = System.Text.Encoding.Unicode

'文字列をバイト型配列に変換
Dim bytAry As Byte() = sourceEncoding.GetBytes(str)
For Each value As Byte In bytAry
'16進数2桁でコンソールに出力

Console.Write("{0:X2} ", value)
Next
Console.WriteLine()
End Sub

たとえば "ABCあいうえお" という文字列を上のメソッドでダンプすると下記のようになります。

41 00 42 00 43 00 42 30 44 30 46 30 48 30 4A 30

さて、ここで注意しないといけないのはこの出力結果がリトル・エンディアンになっていることです。
リトルエンディアンとはUTF-16の文字コードでコードの上位バイトと下位バイトが入れ替わったバイト列のことです。
つまり、上記の結果だと通常の符号単位列としてみるにはダンプ結果を1バイトずつ交互に入れ替えます。

A B C あ い う え お
00 41 00 42 00 43 30 42 30 44 30 46 30 48 30 4A

あと、注意しないといけないのはUTF-16は基本的には2バイトで1文字あらわすのですが、2バイトに割り当てられなかった漢字は4バイトで表すということです。

参考:
Wikipedia UTF-16
Unicodeの概略を理解する
ITpro 文字コードの基本
バイト列と数値を変換するには?
[PR]
by jehoshaphat | 2008-12-29 23:41 | .Net開発 | Trackback | Comments(0)
(Web)PDFを配布するため、AdobeReaderのロゴとダンロードページのリンクを張りたい
よくPDFを置いてるサイトにはAdobeReaderのバナーやダウンロードページへのリンクが張っているとおもます。
あれは正式にはどこで手に入れるのでしょう。

ということで、Adobe社のサイトを探してみました。

Adobe Readerダウンロードサイトへのリンクは下記に載せられていました。
http://www.adobe.com/jp/products/acrobat/acrrlogos.html
どうやら http://www.adobe.co.jp/products/acrobat/readstep2.html がAdobe Readerのダウンロードリンクみたいです。
上記のページには下記のAdobeReaderのロゴも載せられていますが、これは古いロゴだそうです。
e0091163_16133624.gif


新しいロゴはこちらによると、Adobeの英語サイトにあるようです。
http://www.adobe.com/misc/linking.html#readerlogoの「Guidelines for use of Get Adobe Reader web logos」にAdobeReader9用のロゴがあります。
こんな感じです。
e0091163_16135016.gif

[PR]
by jehoshaphat | 2008-12-28 16:14 | Webがらみ | Trackback | Comments(0)
Chromeが速い理由
@ITにChromeはなぜ速いのかという記事で載ってました。

たしかに、Chromeは他のブラウザに比べ、ページ表示が速いように感じます。

そのからくりが上記の記事に載せられているんですが、まあさすがGoogleだなという印象を受けました。

Chromeは下記の点で高速化を実現しているみたいです。
応答性の高速化→体感速度UP
たとえば起動シーケンスを工夫して見かけ上起動したように見せるにしてるっぽいです。
確かにこれはユーザからみると体感速度はUPしますね。

I/Oアクセスを減らす
特にブラウザ本体プロセスはディスクI/O禁止してるようです。
そして、ブラウザ本体プロセスで応答性を悪くさせるような要素を除くため、レンダラーには子ウィンドウを生成させず、またレンダリング結果をいったんバッファ領域にビットマップとして描画してから、それをタブのウィンドウに転送するようにしてるっぽいです。

アンチフィッシングのURLリスト転送工夫
GoogleがフィッシングとみなしたURLのリストをChromeが定期的に取得してるようなのですが、このリストもハッシュ化して、さらに、SHA-256の256ビットのうち先頭32ビットだけを取得してるようです。
アクセスしようとしているURLがブラックURLリストの先頭32ビットで引っ掛かったときだけ、再度256ビットをグーグルのサーバに送って検査するにしてみたいです。

DNSプリフェッチ
これはDNSの名前解決を事前に行うという機能みたいです。
表示したページに含まれるURLのDNSは、もうその段階で名前解決してるっぽいですね。
驚いたのは、名前解決に100~250ミリ秒かかり、場合によって1-2秒かかるサーバもあるようです。
確かに、これはコロンブスの卵的発想です。

Chromeに刺激されて他のブラウザでも応答性の面で改善されることを願いますね。
[PR]
by jehoshaphat | 2008-12-28 15:29 | 豆知識 | Trackback | Comments(0)
(バグ管理)Mantisをインストールしてみた
Excelベースのバグ管理していたのを、ちゃんとしたバグトラッキングを使うようにするためにMantisを導入してみました。
(前の会社ではredmine導入を提案しそれで進捗管理もしてましたが、今回はバグ管理だけなのでMantisにしました。)

まず、Mantisを動かすための環境を整えるため、下記をインストールします。
(OSはWindowsServer2008 Std x64。 DBはMySQLを使用。)
・Apache2.2.10
・PHP5.2.8 (PHPは
・MySQL5.0.67(x64) (MySQLはデフォルトの文字コードをUTF-8を使うように設定します。)

Mantisの公式サイトより最新版をダンロードします。
(今回はバージョンは 1.1.6 です。)

ダウンロードした mantisbt-1.1.6.zip を解凍し、ディレクトリ名を mantis に変更して、Apacheのドキュメントルートに配置します。

ここからはMantis Manual(日本語版) インストールを参考にしてます。
データベースのテーブルを作成し、基本的な設定ファイルを作成するため、ブラウザ下記のURLにアクセスします。
http://xxxx/mantis/admin/install.php
e0091163_14425541.jpg


Username,Admin UsernameはどちらもDBのユーザ名となります。(おそらく、Admin Usernameはテーブル作成がらみのINDEX、CREATE、DELETEおよびDROPの権限が必要なのでしょう。)
上記の場合、Usernameは root を使用していますが、セキュリティ的に考えるとALTER、SELECT、INSERTおよびUPDATの権限をもった一般ユーザのほうが好ましいです。
これで、"Install/Upgrade Database"ボタンを押下すると、データベースと設定ファイルを作成してくれます。

下記のように設定の結果が"GOOD"になっていることを確認します。
e0091163_14432739.jpg


次に config_inc.php (mantisのルートディレクトリに存在)を設定します。
上記の admin/install.php で設定できていれば、$g_hostname,$g_db_type などDBに関する最低限の設定はここに記されていると思います。
設定マニュアルには日本語で使用する際に必要(設定しないと文字化けする)だということで、下記の設定を付け加えます。(DBもUTF-8で運用するようにMySQL側で設定済みです。

$g_default_language = 'japanese_utf8';


これで下記のURLで設定できているかどうかチェックします。
http://xxxx/mantis/admin/check.php
e0091163_1443498.jpg


メールの送信のテストもこのページで行えるのですが、これが曲者で今回ハマりました。

今回レンタルサーバーで借りているメールサーバを使う予定だったのですが、契約プロバイダが最近はやりのOP25B(Outbound Port25 Blocking)を導入してます。
レンタルサーバのメールサーバはOP25Bでも使えるように設定されておりSMTPポートは528でSMTP認証をかけています。

Mantisの設定マニュアルを読む限りではSMPT認証時に使うユーザ名とパスワードを指定できるのでできると思ったのですが。。。
その際に設定した内容は下記の通りです。

$g_phpMailer_method = '2';
$g_smtp_host = "レンタルサーバのSMTPホスト:587";
$g_smtp_username = "SMTP認証時のユーザID";
$g_smtp_password = "SMTP認証時のパスワード";
$g_administrator_email = 'メールアドレス';
$g_from_email = 'メールアドレス';


これで、"Send Mail"ボタンでメール送信テストをしてみましたが、「Testing Mail - PROBLEMS SENDING MAIL TO: メールアドレス. Please check your php/mail server settings.」となり、できませんでした。

$g_phpMailer_methodの値を 0:mail() , 1:sendmail(インストースしてないので使えないのはわかってますが) , 2:SMPT でいろいろ変えても無駄でした。

結局、かなりの時間かけてもわからなかったのでメール通知はあきらめました。
まあプロジェクトメンバも少数だし、RSSもついてるからそれでカバーできるかと。

メール通知を使用しない設定は下記の通りです。

$g_enable_email_notification = 'OFF';



とりあえずメール機能は妥協し、ログインページからログインします。
http://xxxx/mantis/
初期設定のままだと
Username:Administrator
Password:root
でログインできます。

ログイン後は英語のままなので、My Account メニューより、Language の値を Japanese にします。
e0091163_14441716.jpg


設定マニュアルによると、「そして、管理画面ですくなくとも1つ以上の管理者権限のアカウントを作成して、すぐにデフォルトの管理者アカウントを削除してください。アカウントを再生成できますが、まず、そのアカウントを削除して、Cookieがパッケージにいたずらしないようにすべきです。そのアカウントの名前を変えてしまうか、永久に削除してしまうほうがよりいいでしょう。パッケージを設定した後に、デフォルトの管理者アカウントを削除することを忘れないでください。」とあるので、「システム管理」→[ ユーザー管理 ] より管理者権限を持った新規ユーザを作成します。

新規ユーザ作成の際に、言語が自動的に「auto」になってしまっています。これを「japanese」に変更しておかないとえらいことになるので注意しましょう。

後はプロジェクトを作成して、ユーザを作成、プロジェクトへの追加をし、プロジェクトのカテゴリを設定するとOKです。
(プロジェクトのカテゴリで担当者を決定できますが、これを行うとそのカテゴリでバグを登録すると、自動的に担当が決定し、ステータスも「担当者決定」になるので注意しましょう。新規追加時にステータスを通常通り「新規」にするには「システム管理」→「設定管理」→「ワークフロー閾値」で、「割当てられたチケットに設定するステータス」の値を「新規」にするとOKです。でも、担当は勝手にカテゴリに登録された担当者になってしまいますが。。)

参考:
Mantis公式マニュアル
mantisを使ってみる
サブミッションポート環境下でのメール設定 for mantis sendmailが入ってる環境なら、この方法でOP25Bでもメール通知できそうです。
バグトラッカーMantis
Mantisのconfig_inc.phpに指定できる一覧
[PR]
by jehoshaphat | 2008-12-28 14:58 | サーバがらみ | Trackback | Comments(0)
(CalePHP)日付で初期値を空白にさせる
CakePHP1.2

$fomm->inputヘルパー で'type'=>'date' で日付を入力するコンボボックスを作れますが、デフォルトだと値が本日の日付となってしまいます。
これを選択されていないように空とするには下記のようにすればOKです。
<?php echo $form->input('Member.mem_birthday', array("type" => "date" , "label"=>"" , "dateFormat"=>"YMD" , "minYear"=>"1950" , "maxYear"=>"2008" , "monthNames"=>false , 'separator' => ' / ' , 'selected' => ' ' , 'empty'=>' '))?>

要は、'empty'=>' 'で空の要素を有効にしておき、'selected'=>' 'で空の要素をデフォルト値としておきます。
注意しないといけないのは selected の値は半角空白( ' ' )をクォーテーションで囲む必要があります。自分の環境の場合、空文字( '' )だけだと月と日は本日の日付が入ってしまっていました。
[PR]
by jehoshaphat | 2008-12-27 14:50 | PHP開発 | Trackback | Comments(0)
(.Net)一時ファイル、フォルダの使用方法
■一時ファイルは.Netでは非常に簡単に作成できます。
最初は、System.Environment.GetFolderPath(Environment.SpecialFolder.値) で取れるのかと思いましたが、違ってました。

Dim tmpFile As String = System.IO.Path.GetTempFileName()

とするだけで、ユーザの一時フォルダに「tmp<16進文字列>.tmp」という空のファイルを作成してくれます。
GetTempFileName()の戻り値に作成された一時ファイル名が返されるので、あとは作成された一時ファイルを用いていろいろやってやればいいわけです。

ただし、削除処理はきちんとしてやらないといけませんが。(このメソッドで 65535個を超える数のファイルを作成した場合 IOException が発生するので削除は忘れずに。)

参考:
@IT 一時ファイル(テンポラリ・ファイル)を作成するには?
MSDN: Path.GetTempFileName メソッド

ちなみに、System.Environment.GetFolderPath(Environment.SpecialFolder.値) はマイドキュメントやデスクトップなど特殊フォルダのパスを取得するメソッドです。
詳しくは、MSDN Environment.GetFolderPath メソッドMSDN Environment.SpecialFolder 列挙体、使い方は@IT Windowsのシステム・フォルダのパスを取得するには?参照。


■一時フォルダは、、、
ユーザ毎の一時フォルダは下記のメソッドで取得できます。

Dim tmpDir As String = System.IO.Path.GetTempPath()

で、この一時フォルダ配下に、アプリケーションで使う一時フォルダを作りたいわけですが、その場合は開発者がいちいち一時フォルダを作成してやらなければなりません。どうせなら、GetTempFileName() のフォルダ版のように一時フォルダを勝手に作ってほしいところですが、そこまで気が利くメソッドはないようです。
作成するアプリケーションの一時フォルダと同じ名前のフォルダがすでに存在している場合の処理等も書かないといけませんね。
[PR]
by jehoshaphat | 2008-12-27 14:30 | .Net開発 | Trackback | Comments(0)
VisualStudio2008 アウトラインをすべて展開する方法はないのか?
Visual Studioにはアウトラインという機能がありますが、全てが折りたたまれたアウトラインを全て展開する方法はないのかといろいろ調べてみました。
Ctrl+M→Ctrl+L というショートカットキー(すべてのアウトラインの切替)がありますが、この場合 Region がネストしてる環境だと意図どおりになりません。
ネット等みてもやはりこの問題で悩んでる人は多いようですが、簡単な解決策もなさそうです。

MSDNフォーラム region で囲んだコードを一括展開するには?
には、マクロを使って解決する方法が載せられていました。

このマクロをVSに登録して使ってみましたが、実行時に
Dim result As vsFindResult = DTE.Find.Execute()
のところで、落ちてしまい、VS自体がフリーズしてしまうと結果になってしまいました。

まあ、Regionのネストをなくせばいいんでしょうが、プロジェクトの方針なので今更変更できませんし。。
なんか方法はないでしょうかね。

次期Visual Studioにはぜひ全て展開の機能を設けてほしいものです。
[PR]
by jehoshaphat | 2008-12-27 13:38 | .Net開発 | Trackback | Comments(0)
VisualStudio2008 インテリセンス・オブジェクトブラウザの英語になる問題
Visual Sudio2008 でSP1をあてるとインテリセンスやオブジェクトブラウザの情報が英語で表示されるようになっていました。
しばらくは仕方ないと思いつつ使ってましたが、この不具合の修正プログラムが公開されていたようです。

詳細情報:http://support.microsoft.com/kb/957507?rss_fdn=MSDNTopNewInfo

現在公開されている修正プログラムはまだテスト段階らしいですが、MSDN Code Galleryで公開されています。
修正プログラムダウンロード:http://code.msdn.microsoft.com/KB957507/Release/ProjectReleases.aspx?ReleaseId=1854
上記ページより VS90SP1-KB957507-JPN-x86.exe をダウンロードしてインストールするとちゃんとインテリセンスが日本語に復活していました。

Visual Studio 2008SP1の IntelliSense テキストのBugfixによると、xmlファイルに問題があったっぽいですね。
[PR]
by jehoshaphat | 2008-12-27 13:26 | .Net開発 | Trackback | Comments(0)
Visual SourceSafe 2005でPDFファイルを追加し、取得するとファイルが破壊される
表題のとおりですが、Visual SourceSafe 2005(以下VSS)でPDFを追加し、そのPDFファイルを開こうとすると「この文書を開くときにエラーが発生しました。ファイルが壊れています。修復できませんでした。」とAdobe Reader9に怒られます。

どうやらVSSが悪さをしてPDFファイルを破壊しているようでした。

VSSエクスプローラのオプションから、"ファイルの種類タブ"で、バイナリファイルの欄に"*.pdf"を追加することで解決しました。

しかし、ネットで探すとやはりVSSのバグであり、修正版が出てるとのことでした。

下記のマイクロソフトのサイトからVSSのアップデートを入手しインストールしました。
Visual SourceSafe 2005 更新プログラムで修正された問題の一覧(文書番号:943847 )

参考までに、PDFが破壊されたVSSのバージョンは 8.0.50727.42 で、更新後は 8.0.50727.1551 になっていました。


どうせならマイクロソフト製品なんだからMicrosoftUpdateでVSSも更新してほしいですよね。

ちなみに、Adobeの「PDF」仕様がISO標準に認定に・・・によると、VSSサーバーにあるsrcsafe.iniファイルのバイナリ定義に、*.pdfを指定することでもOKみたいです。
[PR]
by jehoshaphat | 2008-12-26 19:19 | .Net開発 | Trackback | Comments(0)