【実務・中級編】.NET Core / .NET 6以降への移行:VB.NETでクロスプラットフォーム対応のモダンコンソール・APIアプリを作る – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

VB.NETを捨てずにクラウドへ行け:.NET 6以降で実現するクロスプラットフォーム開発の極意

開発現場を見渡すと、「VB.NETはWindows専用のレガシー言語だから、Linuxで動くクラウド環境やコンテナ化には使えない」という誤解がまかり通っている。だからといって、無理にC#へリプレイスしてスケジュールを炎上させる必要はない。

事実を言おう。.NET 6、そしてLTSである.NET 8以降のランタイムにおいて、VB.NETはC#と完全に対等なファーストクラス市民である。コンパイラ(Roslyn)のバックエンドは共通であり、生成されるIL(中間言語)のパフォーマンスに差はない。

今回は、業務効率化ツールやバッチ処理のバックエンドとして長年培ったVB.NETの資産を生かしつつ、LinuxサーバーやDockerコンテナといったクロスプラットフォーム環境で完全に動作するモダンなコンソール・APIアプリを構築する手法を、チーフアーキテクトの視点からロジカルに伝授する。

1. なぜ「Windows専用」の呪縛を捨てるべきなのか?

従来のVB.NET(.NET Framework時代)は、COMコンポーネントやWindows Forms、そして何よりCLR(共通言語ランタイム)がWindows OSに深く結びついていた。

しかし、.NET Core以降(.NET 5/6/7/8…)のモダン.NETは、完全にオープンソース化され、OS依存層が抽象化された。これにより、VB.NETで書かれたコードであっても、以下のメリットをそのまま享受できる。

  • Linux(Ubuntu / AlmaLinux等)上での高速実行: クラウド(AWS ECS, Azure Container Apps等)の安価なLinux基盤でそのまま動く。
  • 圧倒的な起動速度と低メモリフットプリント: 旧来の.NET Frameworkに比べ、ランタイムのオーバーヘッドが劇的に削減された。
  • 依存関係のローカル化: サーバー側に特定の.NET Frameworkをインストールする必要がなく、アプリと一緒にランタイムを同梱(セルフコンテナ)できる。

「VB.NETだからクラウド化できない」というのは、古い設計を引きずっている開発者の怠慢にすぎない。

2. 厳禁!クロスプラットフォーム開発でやりがちな「3大アンチパターン」

Linux環境やコンテナへ移行する際、Windows時代のコーディング習慣をそのまま持ち込むと、確実にアプリはクラッシュするか、深刻なバグを生む。以下の3点は絶対に避けてほしい。

1. ハードコードされたWindowsパスの利用
`”C:\Data\input.csv”` のようなパス指定はLinux環境(`/var/data/input.csv`)で例外を吐く。必ず `System.IO.Path.Combine` や `System.Environment.GetFolderPath` を使うこと。
2. 大文字・小文字の無視(ファイルシステムの違い)
Windowsはファイル名の大文字・小文字を区別しないが、Linuxは厳密に区別する。`Config.json` と `config.json` を混同すると、テスト環境では動いて本番で死ぬ現象を引き起こす。
3. COMオブジェクトやWindows特有APIへの依存
`Microsoft.VisualBasic.Interaction.CreateObject(“Excel.Application”)` など、Excelのサーバーサイドオートメーションは論外だ。LinuxにはExcelはない。ファイル操作は専用のライブラリ(ClosedXMLやCsvHelperなど)を用いるべきである。

—.

3. 実践:.NET 8対応モダンVB.NETコンソールアプリの構築

ここからは、実際にLinux環境やコンテナで動作し、堅牢なファイル処理・データベース連携を行うプロダクションコードを解説する。

まずはプロジェクトの作成だ。コマンドラインから以下の通り実行する(.NET 8 SDKがインストールされている前提)。

dotnet new console -n ModernVbApp -lang “VB”
cd ModernVbApp
dotnet add package Microsoft.Extensions.Hosting –version 8.0.0
dotnet add package Microsoft.Extensions.Logging –version 8.0.0
dotnet add package System.Data.SQLite –version 1.0.118.0

プロダクションコード例 (`Program.vb`)

以下のコードは、依存性注入(DI)、構造化ロギング、そしてクロスプラットフォームに対応した堅牢なパス解決を網羅した、そのまま現場で使えるテンプレートである。

Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Hosting
Imports Microsoft.Extensions.Logging

Namespace ModernVbApp
‘ アプリケーションのメイン処理をカプセル化するサービス
Public Class BusinessProcessor
Private readonly _logger As ILogger(Of BusinessProcessor)

Public Sub New(logger As ILogger(Of BusinessProcessor))
_logger = logger
End Sub

Public Async Function ExecuteAsync(cancellationToken As CancellationToken) As Task
_logger.LogInformation(“業務処理の実行を開始します。”)

Try
‘ 1. クロスプラットフォーム対応のパス解決
‘ Linuxなら /var/app/data, Windowsなら C:\Users\xxx\AppData\Roaming\app\data 等に安全にフォールバック
Dim baseDir As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), “ModernVbApp”)

If Not Directory.Exists(baseDir) Then
Directory.CreateDirectory(baseDir)
_logger.LogInformation(“データディレクトリを作成しました: {Path}”, baseDir)
End If

Dim targetFile As String = Path.Combine(baseDir, “processing_target.csv”)

‘ 2. ファイル読み書きのシミュレーション
If File.Exists(targetFile) Then
Dim lines = Await File.ReadAllLinesAsync(targetFile, cancellationToken)
_logger.LogInformation(“ファイルから {Count} 行のデータを読み込みました。”, lines.Length)
Else
_logger.LogWarning(“対象ファイルが見つかりません。新規作成します: {Path}”, targetFile)
Dim defaultData As String() = {“ID,Name,Timestamp”, $”1,Sample,{DateTime.UtcNow:O}”}
Await File.WriteAllLinesAsync(targetFile, defaultData, cancellationToken)
End If

‘ 3. 非同期処理の模倣(実際のDBやAPI連携プレースホルダー)
Await Task.Delay(1000, cancellationToken)

_logger.LogInformation(“業務処理が正常に完了しました。”)

Catch ex As OperationCanceledException
_logger.LogWarning(“処理がキャンセルされました。”)
Catch ex As Exception
_logger.LogError(ex, “業務処理の実行中に予期せぬエラーが発生しました。”)
Throw
End Try
End Function
End Class

‘ エントリーポイント
Module Program
Public Async Function Main(args As String()) As Task
‘ ホストビルダーの構築(DI、ログ、設定のモダンな管理)
Dim host = Host.CreateDefaultBuilder(args) _
.ConfigureServices(Sub(context, services)
‘ サービスの登録
services.AddTransient(Of BusinessProcessor)()
End Sub) _
.Build()

‘ サービスの取得と実行
Using scope = host.Services.CreateScope()
Dim processor = scope.ServiceProvider.GetRequiredService(Of BusinessProcessor)()

‘ キャンセルートークンの設定(Ctrl+Cなどで安全に停止するため)
Using cts As New CancellationTokenSource()
Console.CancelKeyPress += Sub(s, e)
e.Cancel = True
cts.Cancel()
Console.WriteLine(“シャットダウン要求を受信しました…”)
End Sub

Try
Await processor.ExecuteAsync(cts.Token)
Catch ex As Exception
Environment.ExitCode = 1
End Try
End Using
End Function
End Function
End Module
End Namespace

4. コードの解説とアーキテクチャの要点

1. `Environment.GetFolderPath` の活用
Windows固有のレジストリや固定パスに依存せず、OSが管理する適切なアプリケーションデータディレクトリを動的に取得する。これにより、Linuxサーバー上で実行権限エラーやパス不存在エラーを防げる。
2. `Microsoft.Extensions.Hosting` によるコンテナ対応
従来の `Sub Main()` にベタ書きするスパゲッティコードを排除し、C#のモダンなバックエンド開発と全く同じDI(依存性注入)とロギングの仕組みをVB.NETに持ち込んでいる。これにより、単体テスト(Unit Test)が極めて容易になる。
3. 非同期プログラミング(Async / Await)の徹底
I/Oバウンドな処理(ファイルI/OやDBアクセス、外部API呼び出し)では、スレッドをブロックしない `Await` を使用する。これにより、限られたリソースのコンテナ環境でも高スループットを維持できる。

5. Dockerによるコンテナ化:Linux上でVB.NETを走らせる

このアプリをLinuxコンテナとしてパッケージングするのは極めて容易だ。プロジェクトのルートに以下の `Dockerfile` を配置する。

ビルドステージ
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY [“ModernVbApp.vbproj”, “./”]
RUN dotnet restore “ModernVbApp.vbproj”
COPY . .
RUN dotnet publish “ModernVbApp.vbproj” -c Release -o /app/publish /p:UseAppHost=false

ランタイムステージ(軽量なLinuxイメージを使用)
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS final
WORKDIR /app
COPY –from=build /app/publish .
ENTRYPOINT [“dotnet”, “ModernVbApp.dll”]

以下のコマンドでビルドしてコンテナを実行すれば、Windowsのコードベースのまま、完全にLinux環境上でVB.NETアプリが稼働する。

docker build -t modern-vb-app .
docker run –rm modern-vb-app

総括

VB.NETは「過去の言語」ではない。.NET 8という強力なエンジンを手に入れた今、VB.NETはWindowsのデスクトップアプリだけに縛られる必要は一切なくなった。

設計をモダンに保ち、OS依存のコードを排除し、DIや非同期処理の作法を守れば、VB.NETの圧倒的な開発生産性をそのままクラウド時代の最前線に投入できる。
「VBだからリプレイスしよう」という安易なコストを払う前に、まずは手元のVB.NET資産を.NET 8へアップグレードし、Linuxの風を吹かせてみてほしい。プロフェッショナルなエンジニアであれば、その選択がどれほど合理しか、すぐに理解できるはずだ。

タイトルとURLをコピーしました