Skip to content

MS_ApplicationUnicodeMigration

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

アプリケーションのUnicode化

概要

アプリケーションの Unicode 対応

GUI

GUI アプリケーションの Unicode 対応

非UnicodeアプリケーションとUnicodeアプリケーション

古いアプリケーションには、非 Unicode 対応の GUI アプリケーションが存在する。

  • 拡張文字セットを扱うにはアプリケーションの Unicode 対応が必要である。

    • 非 Unicode アプリケーションでは JIS2004 の拡張文字セットだけでなく、
      Shift-JIS にない文字は全て入力できない。
    • 但し、アプリの画面上で、明確に「?」表示になるので、
      予期せず JIS2004 の拡張文字セットが入力されることもない。
  • システムが Unicode に統一されている場合は、
    エンコーディングされる箇所を意識する必要がある。

非UnicodeアプリケーションとUnicodeアプリケーション

補足(「予期せず入力されない」という利点は失われつつある): 原文の
「非 Unicode アプリでは『?』になるので、予期せず入力されない」
という指摘は、当時の運用上の安心材料として的確だった。

しかし現在は、入力経路が増えたためこの前提が崩れている。

【現在のデータの入り口】
   ・Web フォーム(ブラウザは完全に Unicode)
   ・スマートフォン・タブレット(Unicode。絵文字も入る)
   ・CSV / Excel の取り込み
   ・API 経由(JSON は UTF-8 が既定)
   ・OCR、名刺読み取り、外部サービス連携

   → 「画面から入らないから安全」は、もはや成立しない

現在の対策は「入力を止める」から「正しく扱う」へ移った

当時 現在
非 Unicode アプリで入力を物理的に止める 全経路を Unicode で通し、必要な箇所だけ検査する
「?」になるので気付く 文字のチェック方式 で明示的に検査する
Shift_JIS 前提の設計 UTF-8 前提の設計

「気付かないうちに壊れる」のを防ぐという目的自体は今も重要で、
それを明示的な検査で実現するのが現在の形である。

非Unicodeアプリケーション

  • 非 Unicode アプリケーションでは、Shift-JIS にない文字の入力ができない
    (これは、IME から、ウィンドウ プロシージャ経由でデータを正しく受け取れないため)。
  • 例えば、JIS2004 で追加された拡張文字セット以外の、Shift-JIS にない
    鱓(ごまめ)という文字を非 Unicode アプリケーションに入力して見ると、
    この文字も入力できないことが確認できる。

[参考]:CyberLibrarian(図書館員のコンピュータ基礎講座参考資料) > 参考資料JIS補助漢字(JIS X 0212)
http://www.asahi-net.or.jp/~ax2s-kmtn/ref/jisx0212/jisx0212-4.html

・・・ 「鱓」は、JIS90(JIS X 0212)補正漢字

補足(仕組み): Win32 API には同じ関数の A 版と W 版があり、
これが「非 Unicode / Unicode アプリ」の実体である。

【A 版】 …ANSI(=OS の既定コードページ。日本語なら CP932)
           例: CreateWindowExA、SendMessageA、DefWindowProcA

【W 版】 …Wide(=UTF-16)
           例: CreateWindowExW、SendMessageW、DefWindowProcW
【非 Unicode アプリで文字が消える経路】

  IME(内部は Unicode)
    ↓ 確定文字を WM_IME_CHAR / WM_CHAR で送る
  ウィンドウが A 版で登録されている
    ↓ OS が【UTF-16 → CP932 に変換して】渡す
  CP932 にない文字は「?」(0x3F)になる
    ↓
  アプリには「?」しか届かない(元の文字は失われている)

重要なのは「変換は OS が勝手に行う」点である。
アプリ側でどれだけ頑張っても、
ウィンドウが A 版である限り、文字は届く前に失われる
原文が「ウィンドウ プロシージャ経由でデータを正しく受け取れないため」と
書いているのは、まさにこの構造を指している。

Unicodeアプリケーション

アプリケーションの Unicode 対応の方法

VB

補足(VB6 の話である): この KB は **VB6(Visual Basic 6.0)**向けで、
VB.NET には該当しない

内部表現 Unicode 対応
VB6 UTF-16 だが、フォームは A 版 API 非対応(回避策が要る)
VB.NET / C# UTF-16(string 最初から対応済み

.NET のコントロールはすべて W 版 API で作られているため、
Windows Forms / WPF / WinUI のいずれでも
Unicode 対応の作業は不要である。

・.NET の string は最初から UTF-16
・TextBox 等のコントロールは W 版 API を使う
・したがって、𠮷 も 髙 も 絵文字も、そのまま入力・保持できる

現在の課題は「入力できるか」ではなく、
その先(DB、ファイル、連携先)で失われないか
に移っている
文字のチェック方式)。

VC++

補足(原文の「ウィンドウクラスの登録が決め手」という指摘は正確): この
一連の記述は、Win32 の仕様を正しく捉えている。要点を補強しておく。

【IsWindowUnicode が True になる条件】
   ウィンドウの「クラス」を RegisterClassW で登録したこと
     ← CreateWindowEx の A/W は関係ない(原文の通り)

【なぜ A でも W でも良いのか】
   CreateWindowEx の A/W が影響するのは
   「ウィンドウ【タイトル】の文字列」の解釈だけ
     → ウィンドウ自体の性質はクラス登録時に決まる

原文の「ただし」以降——コモン コントロールは W 版で作れ——も重要で、
これはコモン コントロールのクラスが
comctl32.dll 側で登録済み
(A/W 両方ある)であるため、
CreateWindowExW を呼ぶことで W 版のクラスが選ばれる、という理屈である。

現在の VC++ での書き方:

// プロジェクト設定で「Unicode 文字セットを使用する」を選ぶと
// UNICODE / _UNICODE が定義され、A/W なしの名前が W 版に解決される
#define UNICODE
#define _UNICODE

// 以降、RegisterClass / CreateWindowEx / DefWindowProc は
// すべて自動的に W 版になる

Visual Studio の既定は「Unicode 文字セット」であり、
新規プロジェクトでは対応済みである。
問題になるのは、「マルチバイト文字セット(MBCS)」で作られた古い資産

引き継いだ場合だけである。

【MBCS プロジェクトを Unicode 化する際の作業】
   ① プロジェクト設定を「Unicode 文字セット」に変更
   ② char / LPSTR → TCHAR / LPTSTR(または直接 wchar_t / LPWSTR)
   ③ "文字列" → _T("文字列") または L"文字列"
   ④ strlen / strcpy → _tcslen / _tcscpy(または wcslen / wcscpy)
   ⑤ ファイル I/O、DB アクセス、外部 DLL との境界を洗い出す ★

   ⑤ が最も工数を食う。②~④ は機械的に置換できる

MFC も既定で Unicode ビルドである。
VS 2015 以降、MBCS 版の MFC ライブラリは別途インストールが要る
(非推奨扱い)。

補足(この記事全体の現在的な意味): 原文が扱う
「アプリケーションの Unicode 化」は、
デスクトップ アプリの層ではほぼ完了した課題である。

現在「Unicode 化」が問題になる場所は、以下に移っている。

現在の課題
データベース varcharnvarchar、照合順序に _SC(サロゲート対応)
ファイル連携 固定長・CSV が CP932 前提で作られている
外部システム連携 相手が CP932 しか受けない文字のチェック方式 の可逆チェック)
帳票・印刷 フォントに字がない帳票出力
外字 私用領域を使った既存資産Windowsの外字
バッチ・シェル コンソールのコードページ(後述の CMD の話)

「アプリは Unicode になったが、周辺が追いついていない」——
というのが現在の実情である。
本ページの後半(CUI / FTP)が扱っているのは、まさにその周辺の話である。

CUI

CMD

FTP をコマンドで実行した所、文字化けしたという話がありましたが、
コマンド・プロンプト(CMD)が SJIS アプリケーションとして動作しているためです。

コマンド・プロンプト(CMD)は、

cmd /u その他コマンドライン引数

で Unicode 対応します。

それ以外は SJIS です(日本のロケールでは)
#日本語以外では各国のロケールの既定の文字コード。

↓のコマンドを /u 有り・無しで起動したコマンド・プロンプト(CMD)から実行テストすると解ります。

C:\Users\daisukenishino>echo 鱓 > aa.txt

鱓(ごまめ)は、Unicode にしか無い文字。
(Unicode で BOM 無しで出力されるためサクラエディタなどから開いて下さい)

移行メモ(cmd /u の効果は限定的): /u
「内部コマンドがパイプ・リダイレクトへ出力する際に UTF-16 で書く」
という指定であり、「CMD 全体が Unicode 対応になる」わけではない

【cmd /u が影響する範囲】
   ○ echo、dir、type などの【内部コマンド】の
     パイプ・リダイレクト出力 → UTF-16 LE(BOM なし)

   ✗ 画面表示のコードページ    → 変わらない(chcp のまま)
   ✗ 外部コマンド(ftp.exe 等)→ 影響しない
   ✗ 入力(コマンドライン引数)→ 影響しない

原文の実験(echo 鱓 > aa.txt が UTF-16 BOM なしで出る)は
この仕様の通りであり、観察は正確である。
ただし「FTP の文字化けが /u で直る」わけではない
ftp.exe は外部コマンドのため)。

コンソールのコードページを変えるには chcp を使う。

chcp 65001    :: UTF-8 に切り替える
chcp 932      :: CP932(既定)に戻す

現在の状況:

項目 現在
Windows Terminal UTF-8 で正しく動く。既定のターミナルになった
PowerShell 7 既定が UTF-8(BOM なし)。CMD の制約がない
Windows 10 1903 以降 ベータ: ワールドワイド言語サポートで UTF-8 を使用」を設定するとシステム既定が UTF-8 になる
.NET の Console Console.OutputEncoding で明示的に設定できる
# PowerShell 7 では既定で UTF-8(BOM なし)
"" | Out-File aa.txt
// .NET のコンソール アプリで確実に UTF-8 を出す
Console.OutputEncoding = Encoding.UTF8;

「ベータ: UTF-8 を使用」の設定には副作用がある点に注意する。
システムの ANSI コードページが 65001 になるため、
CP932 前提の古いアプリが軒並み文字化けする
検証環境で確認してから有効化すること。

**現在の指針は「CMD を使わない」**である。
PowerShell 7 か、
UTF-8 を明示設定した .NET コンソール アプリ
自作CUI(CLI)の話)を使う方が確実である。

FTP

FTP は、転送モード(ascii または binary)があり、
転送モード:ascii では、自動エンコーディングするので、

設定で回避

文字化けが発生する場合は、設定などで回避する必要がある。

サーバ側でエンコード

エンコーディングの指定は無いようなので、
ファイル名などの文字化けなどが発生した場合、
convmv というコマンドを使用して変換するなどが必要になる。

補足(FTP の文字化けの構造と、現在の代替): FTP の文字化けには
2 つの別々の原因があり、混同されやすい。

【原因① ファイルの中身】
   転送モードが ascii だと、改行コードが変換される
     Windows: CRLF ←→ Unix: LF
   → バイナリ ファイルが壊れる(画像、ZIP、Excel)
   → 対策: binary モードで転送する

【原因② ファイル名】
   FTP はファイル名の文字コードを規定していなかった
     サーバ: CP932 / EUC-JP / UTF-8 のどれか
     クライアント: 別のもの
   → 対策: RFC 2640(UTF-8 対応)の OPTS UTF8 ON

原文の「エンコーディングの指定は無いようなので」は
RFC 2640 以前の理解
である。
現在はRFC 2640 で UTF-8 が規定され、
主要なサーバ・クライアントは対応している
(FileZilla、vsftpd、IIS FTP など)。

・サーバが FEAT 応答で UTF8 を返す
・クライアントが OPTS UTF8 ON を送る
   → 以降、ファイル名は UTF-8 でやり取りされる

ただし、古いサーバや、CP932 でファイル名を保存済みの環境では
依然として問題が残るため、原文の convmv の話は今も有効である。

より本質的な補足:FTP 自体を使わない

【FTP の問題】
   ・【認証情報が平文で流れる】(FTPS/SFTP でなければ)
   ・ファイアウォール越えが面倒(PASV / PORT、データ用ポート)
   ・文字コードの規定が後付け
   ・転送の完全性を保証しない
代替 内容
SFTP(SSH File Transfer Protocol) SSH 上で動く別プロトコル(FTP とは無関係)
FTPS FTP を TLS で保護。FTP の他の問題は残る
HTTPS(REST API) 最も素直。ファイアウォールを通る
オブジェクト ストレージ(Azure Blob、S3) 現在の第一選択。SDK で扱える
rsync / robocopy 差分転送。同一ネットワーク内向け

SFTP は名前が似ているが FTP とは別物である
(FTPS と混同しないこと)。
ファイル名は UTF-8 が規定されており、この点でも優れる。

【現在のシステム間ファイル連携の指針】
   ① 可能なら【オブジェクト ストレージ + SDK】
   ② 相手が FTP しか話せないなら【SFTP か FTPS】
   ③ ファイル名は【ASCII に限定する】
        → 日本語ファイル名は、連携の入口では使わない
        → 論理名はメタデータ(JSON、DB)側で持つ
   ④ 中身の文字コードは【UTF-8 + BOM の有無を明記】して合意する

③ が実務的に最も効く。
ファイル名を ASCII に限れば、文字コードの問題は消える

参考

Microsoft Learn


Tags: 移行, .NET開発, 国際化対応, 文字コード

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally