タグ別アーカイブ: 開発

Visual Basic で相対パスの設定は、オススメできない

最近の弊社では、Visual Basic を用いた開発を始めました。

Visual Basic は、Microsoftが開発した言語の中で長い歴史持った開発言語で、
プログラマー初心者でも、安定性のあるGUIアプリケーションを早く開発できることで高い評価を受けています。

ですが、そんな Visual Basic にも欠点があり、
いざリポジトリを整理しようとなったとき、C++/C# のように相対パスの設定がVisual Studio上でできないことです。

そこで今回、ご紹介するのは Visual Basic で相対パスを設定する方法になります。

本題に入る前に、先にお伝えしたいことがあります。

Visual Basic で相対パス設定を行うことは、非常に手間がかかる作業となり業務においても支障が出る恐れがありますので、
正直オススメできません。
あくまで、開発言語の知識を深めるために実施してください。

まず、Visual Studio を立ち上げ、新規でVBのプロジェクトを作成してください。(今回は、Windows フォームアプリケーションを選択 を使用します。)

作成したら上書き保存をして一度保存します。

保存が完了したら、プロジェクトを作成したパスに移動し、作成したソースコード「UserControl1」と「My Project」を切り取ります。

次に、ソースコードを配置するフォルダを任意で作成し、貼り付けます。(今回は、「\TestPath\SourceTest」というフォルダに配置します。)

次に先ほど作成したプロジェクトファイル「TestPath.vbproj」をエディタで開き、移動したソースコードの読み込み先を手作業で変更していきます。

<Compile Include="..\SourceTest\UserControl1.vb">
<Compile Include="..\SourceTest\UserControl1.Designer.vb">
<EmbeddedResource Include="..\SourceTest\UserControl1.resx">

そして、読み込み先の変更が完了したら、ソリューションファイルを開きます。

すると、Visual Studio が開きソリューションエクスプローラーの「UserControl1」を確認すると、新規作成時のアイコンから表示が変わっており、相対パスで読み込まれていることが確認できます。

このように Visual Basicで相対パスを設定は、プロジェクトファイル内で設定しているファイルの読み込み先のパスを変更することで相対パスの設定が可能です。

しかし、Visual Studio 上でのパスの編集ができず、ソースコードの直接編集およびプロジェクトファイルの再読み込みも必要となるため、面倒な作業が増えます。

そのため、Visual Basic で開発する際は、プロジェクトファイルを直接編集することが無いよう、プロジェクトファイル直下にソースコードを置くようにし、いつでもソリューションエクスプローラー上でソースコードを整理できる状態にしておくことをオススメします。

最後に余談ですが、Microsoft の開発者ブログより、.NET 5.0 の実装完了後、以降 Visual Basic に新しい機能は追加しないという事が発表されました。
新機能の追加が今後ないとはいえ、サポート自体はしっかり行うとのこともブログで伝えておりますが、
これを機に、 Visual Basic から今後も新機能が開発される C# に切り換えるデベロッパーが徐々に増えていくと思います。

Visual Basic support planned for .NET 5.0 (Microsoft の開発者ブログ)
https://devblogs.microsoft.com/vbteam/visual-basic-support-planned-for-net-5-0/


DLLを作るときの注意事項

WindowsでDLLを作るときには注意事項がいろいろあります。
どの言語で開発するかを問わず必ず問題になるのは、

  • 呼び出し規約
  • DLLヘル
  • メモリの確保と解放
  • 構造体のパディング
  • 例外
  • スタックサイズ
  • FPU制御レジスタ、MXCSRレジスタ

くらいでしょうか。

C++の場合は更に、

  • STLの公開と非互換性
  • クラスの公開
  • オーバーロード

などが追加されます。

ネット上でこれらの問題と解決法(諦めることも含めて)を見つけることはできますが、「FPU制御レジスタ、MXCSR」についてはDLLと絡めた情報は見つかりません。

FPU制御レジスタ、MXCSRレジスタの設定値はコンパイラによって変わります。
FPU制御レジスタの初期値はVCでは0x027f、VB6は0x137f、Delphiは0x1372で全て値が違います。実行中に変えることもできます。
DLLは自分の呼び出し元がどれで作られているかは関知しないので、制御レジスタがどんな値でも対応できなければなりません。

基本的には公開関数の最初で制御レジスタを都合のいい値に変更し、最後で呼び出されたときの値に戻せばOKです。
関数からEXE側にコールバックする等、モジュールを越える場合は都度対応が必要です。

この問題はわかりにくい形で発生します。
以前弊社で利用したOCRライブラリではDelphiからの呼び出しで認識精度がガタ落ちしました。
また弊社PDFDriverに対して16bitのVBアプリからの印刷で例外が出ることがありました。
いずれもFPU制御レジスタの設定で解消できましたが、OCR問題の時はこれを知らなかったのでかなり解決に時間がかかりました。

EXE制作で外部のDLLを利用する場合に、サンプルコード通りなのに結果がおかしい、VCからならOKなのにVC以外からだと同じ入力でも結果が違う、という問題がおきたらFPU制御レジスタを変えると期待通りの動作になるかもしれません。

VCではFPU制御レジスタの初期値は0x027f、MXCSRレジスタの初期値は0x1f80です。