2015年5月29日金曜日

Variant型引数をもつDLLの呼出(VisualStudio2013)


今回の仕事も古いDLLを使用して相手装置のログを読み出す開発。

DLLの説明書にはVB6.0での使用方法しか書かれていない。
発注元からVisualStudio2013から呼び出せるのか確認してもらうと
実際に確認していないが動作するはずですとの回答。
なんとかなるよなと。。。


正直、私が使ったことがあるのVisualStudio6.0で以降の開発環境って今回が初めて。
ここ数年Javaがメインで開発しているしMicrosoft製品っていうかDLLとかよく判らない。
動的なライブラリってのはわかってますが。



OS     Windows7 Pro 32Bit版
開発環境 Visual Basic 2013

簡単にやりたいことを書き出すとアナログ値を収集する装置から
一定間隔で値を取得しDBへ保存する。
収集装置から値を取り出すのにDLLを使用する。


DLLをどうやって使うのかも微妙な感じで社内のMicrosoft製品での開発に詳しい人に聞いて何とかDLLをソースで呼び出せるようになる。

さて実行して見ると実機を前にDLL側から提供されているInit()、Open()は問題なく呼び出せた。
で、実際に値を読み取るメソッドでエラーとなってしまう。

このメソッドの引数が
Method(String , String, variant)

ソースはこんな感じ

Imports VS6Lib
class test(){
Private vs6Lib As VS6Lib.VS6COMM
sub test() {
Dim ret As Long
Dim ret As Object = new Object
vs6Lib = new VS6Lib.VS6COMM()
'' DLL初期化
ret = vs6Lib.init()
IF ret<>0 THEN
'' エラー処理
ENDIF
'' 装置へ接続
ret = vs6Lib.open()
IF ret<>0 THEN
'' エラー処理
ENDIF
'' アナログ値読み出し
ret = vs6Lib.Method("装置名","ALL_READ", obj)
IF ret<>0 THEN
'' エラー処理
ENDIF
~DB登録等の処理~
}
}

variant型はObject型に置き換えるとの記載を目にしたのでvariantの引数はObjectを
渡しているのだがDLLから帰ってくるエラー内容は、データ配列数が少ないとなっている。

このメソッドを使用するとvariant型に取得したいアナログ値をByte配列にして
戻してくれるらしいのだが…

同じ動作をするメソッドでvariantの箇所をStringでファイル名を指定するとファイルに出力してくれるメソッドがあるのでこちらを試してみると正常終了となりファイルも作成されてて当然値も出力されている。

やっぱりvariant型への引数の渡し方が悪いんだね。

調べてみても有用な情報は見つからず…
既に値が取れる前提で以降の処理は作成されているため変更は手戻りが大きすぎる。

なんとか引数を渡せないのか?
DLLからはByte配列が戻ってくるのでByte配列を引数に指定してみるが型が違うとエラーになる。当然か…

やっぱりファイル経由で値を取らないと駄目なのか?

しばし、考察


variant型の使い方を見ているとユーザ定義型などをvariant型引数に突っ込んだり出来るらしい。
もしかしてObject型にもユーザ定義型って突っ込めるのか?

そう思い試してみることに

'' Byte配列を定義
Dim b(0 To 64) As Byte
obj = b
'' アナログ値読み出し
ret = vs6Lib.method("装置名","ALL_READ", obj)
IF ret<>0 THEN
'' エラー処理
ENDIF

こんな感じで試してみるとエラーは発生しないで値を取れました!

取れたんですがさらに厄介なことに
 byte, byte,       byte, byte, byte, byte
 状態, ステータス, 値(Single 4byte)
ってな状態で返してくれているらしい。浮動小数点byteの中見ても判らんし正しい値が取れているのか?

Singleは浮動小数点なのでbyteを単純に変換出来るのか?
と調べてみると
System.BitConverter.ToSingle(byte配列, 開始位置)
Byte配列からシングルへの変換メソッドが有りました

        Dim sVal as Single = System.BitConverter.ToSingle(b, 2)

こんな便利なメソッドが用意されているなんて素敵です。
これで無事値を取得することが出来ました。


しかしVBって結構沢山の人が使っていると思うのだが情報を見つけるのが大変。
検索の仕方が悪いのか目的の情報になかなかたどり着けない。
情報が多すぎるんだろうなきっと。。。


この装置が出来てから10年近く立ってるんだったらDLL位更新して欲しいよな。後64bit版もね
ハード屋さんなんでソフトを再作成するの面倒なのかな?

2015年5月18日月曜日

外字登録後、Windowsで日本語が正常に表示されなくなってしまった時の対処法


仕事の都合で客先で使用している外字をフォントファイルに組み込んで使用していたのですが、仕事が終了したことも有り外字ファイルを削除したところ、プリンターの設定画面やAdobeReaderでPDFを開くとメニューの日本語が表示されなくなってしまいました。
外字自体はきちんと表示されていたんだが…

日本語部分が表示されない…

日本語部分が全く表示されず、操作が出来ない状態。
せめて英語表示の方がまだ判るんだが。


ネットを調べても同様の現象は見つからない。。。
文字化けの対処方法はあっても日本語が表示されないってのはあまり起きないんだろうな。

たどり着いたのがレジストリ値。
regeditを使用して外字フォントを修正します。


スタート
 プログラムとファイルの検索欄にregeditと入力

  以下のレジストリを編集
  コンピューター
   |-HKEY_CURRENT_USER
    |-EUDC
     |-932
      +SystemDefaultEUDCFont

ここの値が組み込んだ外字ファイル名となっていたので936、949と同じEUDC.TTEに変更。
変更後、再起動を行ったら無事復旧しました。
※regeditで他の値を修正するとwindowsの挙動がおかしくなるので注意!

ダブルクリックすると編集できます

OKで登録されます

この外字ファイルを組み込んだ際に使用したツールで削除したつもりだったんだが上手く解除できていなかったのか?

外字ファイルを変更したらeudc.tteに戻す必要があったんだね。

これなら操作出来ます。



使用しているPCはWindows7 Professional 64bit版です。

同じ現象で苦しんでいる人の助けに慣れれば幸いです。