リッチテキストボックスに左余白を設定する

leftmargin-test.png備忘。右画像のようにテキストボックス内に左余白を設定する。リッチテキストボックスのプロパティパネル内を見渡しても左余白を設定するプロパティは見つからなかった。右余白については、RightMarginというプロパティはあってテキストボックス内の右余白を設定することができるようになっている。しかし、RightMarginがありながらLeftMarginの設定をすることはできないらしい。あってもよさそうなのだけれど・・・。で、左余白を設定するにはselectionIndentを設定することで実現できる。

サンプルコード

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Me.RichTextBox1.SelectionIndent = 30

    End Sub

余白を設定する方法を調べていたらプロパティパネル内にShowSelectionMarginというプロパティがあることに気づいた。これもよくわからないもので、ShowSelectionMarginのプロパティをtrueに設定するとわずかばかり左側に余白が設定される。その余白サイズについては不明。サイズを設定することはできない模様。SelectionIndentを設定することで事足りるので、ShowSelectionMarginの設定はおそらく要らないのではないかと思う。

listviewのSelectedIndexChangedイベントの挙動

listviewの一覧のアイテムをマウスでクリックして、そのクリックした項目のアイテム名を取得しようとしたら、

  Message="'0' の InvalidArgument=Value は 'index' に対して有効ではありません。
パラメータ名: index"
  ParamName="index"

というエラーが発生した。listviewのアイテムを初回選択時にはエラーは出ず、2回目にアイテムを選択したときにエラーが発生した。どうも挙動が怪しい。1回目に選択して2回目に選択し直すときにselectedindexの値がクリアされてから選択をし直す、というような動きをしている。なぜそのような動きなのかはよくわからないけれど、とにかくエラーを回避するには、selectedindexのcountの値を見て、0である場合は読まないようにするしかない。

サンプルコード

If Me.listView1.SelectedItems.Count > 0 Then

memo_file_name = Me.lv_index.SelectedItems.Item(0).Text

(省略)

End If

googleのインデックスにipアドレスが登録される

google_kochi_news.png高知新聞のホームページをgoogleで検索してみたところ、検索結果の一番初めに目的の高知新聞のホームページが表示されたのだけれど、そのアドレスがおかしい。ドメインではなくipアドレスで直接インデックスされている。新聞社の比較的大きなサイトなので当然固定ipを取得してるのだろうけど、ドメインではなくipがまず先にインデックスされるとは一体どういうことになってるのだろうか。謎。

proftpdサーバにログインできない

debianをインストール後にproftpdをapt-getでインストールした後、クライアントPCからftp接続をしてみたところログインできなかった。ユーザ名とパスワードは作成されたものを正しく入力していたにもかかわらず。proftpdのログを調べてみた。

KURO-BOX:/# tail /var/log/proftpd/proftpd.log
Jun 07 06:46:49 KURO-BOX proftpd[6832] KURO-BOX (192.168.11.2[192.168.11.2]): USER nakahira (Login failed): Invalid shell: ''

Invalid shell: ”という部分が問題になっている。useraddでユーザを作成したときにシェルを指定することを忘れていた模様。では、usermodでシェルを指定することにしてみる。

KURO-BOX:/# usermod -s /bin/sh nakahira

これでfpt接続に再挑戦。しかし・・・、

User (192.168.11.10:(none)): nakahira
331 Password required for nakahira.
Password:
530 Login incorrect.
Login failed.

また失敗。もういちどproftpdのログを調べてみる。

KURO-BOX:/# tail /var/log/proftpd/proftpd.log
Jun 07 07:12:32 KURO-BOX proftpd[6846] KURO-BOX (192.168.11.2[192.168.11.2]): FTP session opened.
Jun 07 07:12:37 KURO-BOX proftpd[6846] KURO-BOX (192.168.11.2[192.168.11.2]): USER nakahira: Login successful.
Jun 07 07:12:37 KURO-BOX proftpd[6846] KURO-BOX (192.168.11.2[192.168.11.2]): nakahira chdir("/home/cdn/nakahira"): No such file or directory
Jun 07 07:12:37 KURO-BOX proftpd[6846] KURO-BOX (192.168.11.2[192.168.11.2]): FTP session closed.

ログインは成功している。しかし、ディレクトリが見つからないと言っている。作ったはずなんだけれど・・・。

KURO-BOX:/# mkdir /home/cdn/nakahira

もういちどfpt接続に挑戦。

220 ProFTPD 1.3.0 Server (Debian) [192.168.11.10]
User (192.168.11.10:(none)): nakahira
331 Password required for nakahira.
Password:
230 User nakahira logged in.

無事ログイン成功。めでたしめでたし。

文字列中にある一部分だけを置き換える

備忘。正規表現を使ってある条件にマッチする場合、その文字列の一部分を別の文字列に置き換える、ということをやってみる。たとえば次のような文字列があったとする。

“00 abcde” “01 fghij”

上記の文字列を、ダブルクォートで囲まれた部分に半角スペースがあれば、その半角スペースをアンダーバーに置き換えるという処理をする。目的の形式としては次のような文字列が作成されればいい。

“00_abcde” “01_fghij”

考え方としては、ダブルクォートで囲まれた部分は、1個のダブルクォートから始まり1個以上の文字列があり、スペースが続き、そして1個以上の文字列があって1個のダブルクォートで終わる、という範囲になる。これによりダブルクォートで囲われた部分が複数あっても識別することができる。下記にサンプルコードを記載する。半角”(” “)”で囲われた部分は置換せずに残すという意味になる。置換後の文字列には$1と$2という部分があるが、これは置換前のカッコを意味しており、その数字はカッコの出現順を意味している。置換対象は半角スペースのみで、それを半角アンダーバーに置き換える、となる。

サンプルコード

Imports System.Text.RegularExpressions

...

searchStr = Regex.Replace(targetString, "("".+?) ([^""]+?"")", "$1_$2")

メタ文字のエスケープ

sqlインジェクション対策の一つのメタ文字のエスケープ処理。ローカルで利用するwindowsアプリケーションなので、インターネット上のwebアプリのように攻撃されることはないけれど、操作している上でメタ文字を入力してしまうということが起こりうるため一応対策。

“‘”(シングルクォート)をエスケープ処理する。入力文字列中にシングルクォートが存在すれば、その前にもう一個シングルクォートを挿入するようにコーディングする。シングルクォートを見つける手段は正規表現を使うことにする。

サンプルコード

Imports System.Text.RegularExpressions

‘文字列中にシングルクォートが存在すれば、シングルクォート2個に置き換える
Dim inputedValue As String = Regex.Replace(Me.textBox1.text, “‘”, “””)

windowsアプリケーションに最新バージョン確認の機能を追加する

現在使用しているwindowsアプリケーションのバージョンが、公開されている最新バージョンであるかどうかを確認するための機能を追加してみる。どういう実装にするのが最善かまだ見えていないけれど、単純に考えるなら最新バージョンの情報があるファイルをサイトからダウンロードして、そのファイルにあるバージョン情報を読み取り、現在のアプリケーションのバージョンと比較をするというのが簡単に実現できそうだ。

この機能を実現するにはインターネットにアクセスして対象のファイルをダウンロードするという方法をとらなければならない。アプリケーションを公開する側では、公開時にリリースするソフトと一緒にそのバージョンが記されたファイル(テキストファイルなど)をするという準備が必要になる。ソフト側では最新バージョンのチェックを行ったらそのバージョンが記されたファイルをダウンロードするという手順になる。筋道としてはこんな感じだろうか。

注意点は、

  • インターネットに接続できない場合の対処
  • 対象のファイルが存在しなかった場合の対処

・・・ということを想定して実装してテストを繰り返せば致命的なエラーにはならない、かな。

サンプルコード

MonthCalendarの表示がxpとvistaでサイズが異なる

visual studio 2005のwindowsアプリケーションを作成する場合に使うコントロールの一つにMonthCalendarというのがある。これをフォーム内に配置して表示確認を行ったところ、どうもxpとvistaではデザインとサイズが大幅に異なるようになっている。しかもサイズの変更ができず、どちらかに合わせることもできない。

xpとvistaの両方で同じように表示する方法は一つあって、コンパイル時の設定でxpのスタイルを無効に設定することで一応、同じように表示はすることができる。ただこれはデザインがクラシックスタイルになってしまってせっかくのvistaの美しいインターフェースが使えなくなってしまう。

フォームに埋め込み式でMonthCalendarを使う場合にはサイズの問題でxpとvistaに両対応させることは難しい。困った。

System.Data.OleDb.OleDbException: ファイル ’ファイルパス ’ が見つかりませんでした。

データベースファイルを相対指定にしていて、openfiledialogでローカルのファイルを選択後に、データベースのファイルの指定が絶対指定に変わってしまった。その結果、当然ながらデータベース接続エラーが発生するようになった。fileopendialogを使うと別の部分で相対指定しているファイルパスを変更してしまうのだろうか。とりあえず。データベースファイルのパスは絶対パスに変更することでエラーは出なくなった。

テーブルのフィールドのデータ型を調べる

プログラムで使っているテーブルのあるフィールドが設計ミスで使われていないことに気づき、せっかくだからそのフィールドのデータ型を変えて別の用途に使ってみようというトリッキーなことをやろうとしたけれど、やっぱりやめることにした。こういうのは大抵上手くはいかず、別のもっと良い方法がある。でも、途中まで調べたので記念に残しておく。

やろうとしたことは、テーブル内にある使ってないフィールドのデータ型=char型をlongchar型に変えてみようとした。プログラムの処理としては、フィールドのデータ型がchar型ならlongchar型に変えるsqlを走らせる、というもの。

データ型を取得する際のポイントは、OleDbCommandのExecuteReader().GetDataTypeName(0) という部分。これで対象のフィールドのデータ型が手に入る。実際に取得してみたらdbtype_wvarcharという値が取得できた。

        dim sqlStrType as string = "select field1 from table1"

        Dim isDataType As OleDb.OleDbCommand = cn.CreateCommand
        Dim fieldType As String

        isDataType.CommandText = sqlStrType
        cn.Open()
        fieldType = is_data_type.ExecuteReader().GetDataTypeName(0)
        cn.Close()


        'char型の場合(=DBTYPE_WVARCHAR)
        If fieldType = "DBTYPE_WVARCHAR" Then

            'データ型をテキスト型からメモ型へ変換する
            dim sqlStrChange as string = "alter table table1 alter column field1 longchar"
            Dim changeType As OleDb.OleDbCommand = cn.CreateCommand
            change_type.CommandText = sqlStrChange
            cn.Open()
            changeType.ExecuteNonQuery()
            cn.Close()

       '通常の処理

            'longchar型の場合(=DBTYPE_WLONGVARCHAR)
        ElseIf fieldType = "DBTYPE_WLONGVARCHAR" Then

            '通常の処理

        End If