【Visual Basic】Windows 10 ver 2004(20H1)/20H2以降の日本語固有不具合について

# はじめに
会社では、Windows 10になってから半年ごとにバージョンアップによる既存アプリケーションの動作検証しています。
WSUS（Windows Server Update Services）を使用しているので、最新アップデートよりズレがあります。現時点では、Windows 10 ver 2004の動作検証しているところです。

この記事は、[Visual Basic Advent Calendar 2020](https://qiita.com/advent-calendar/2020/vb)の10日目の記事となります。11月15日に先行記事として書きました。Visual Basicでは記事が少ないので、今年書いた記事ならOKにしています。

# 現象
「コード」と「ｺｰﾄﾞ」や「サンプル」と「ｻﾝﾌﾟﾙ」のように濁点・半濁点を含む半角カナと全角カナを比較した時に同じ文字として解釈されなくなりました。
不具合と件名に書いたのですが、~~Microsoft的には修正するつもりはないので仕様となります。~~

[Windows 10 バージョン 2004 (20H1) / 20H2 で VBA 関数 StrComp() で全角カナと半角カナが一致判定されない](https://social.msdn.microsoft.com/Forums/ja-JP/bd9d55e4-1f73-4a25-a9a3-1ff105d5b40c/windows-10-1249612540124721251912531-2004-20h1-20h2-12391-vba-3830625968?forum=officesupportteamja)

【2021/02/10追記】 不具合を修正する予定があるとのこと
>**既にリリース済のバージョン 2004 および 20H2 において既存のバージョンのまま問題を回避することは機能仕様上出来ず、2021年以降の Windows 10 OS にて本問題を修正したバージョンがリリースされます。**
[Windows 10 バージョン 2004 (20H1) / 20H2 上で 半角カナのフォームを含んだ Access ファイルでエラーが発生する](https://social.msdn.microsoft.com/Forums/ja-JP/4e6223e2-34d0-4a5f-bb61-109bc28040b6/windows-10-1249612540124721251912531-2004-20h1-20h2-1997812391?forum=officesupportteamja)

## VBアプリケーション【2021/02/10追記】
これまでVBアプリケーションでStrComp関数を使用していなければ問題ないと思っていたのですが、StrComp関数を使用していなくても内部的に比較している場合に問題が発生することが分かったため、あえてVBアプリケーションとして追記しました。

>原因を調査すると、DB項目名とvbアプリで使用している項目名が全角・半角で異なっているアプリでした。
例）DB項目名：担当者コード、vbアプリ項目名：担当者ｺｰﾄﾞ
[Windows10 2004　ユーザーアプリケーションがエラーになる](https://answers.microsoft.com/ja-jp/windows/forum/windows_10-other_settings/windows10-2004/dd3605c4-1854-452b-a47a-5363f0d348b5)

下記のようにDB項目名とVBアプリケーション項目名で、これまでは全角カタカナと半角カタカナは同一と判断されていて動作していたが、2004(20H1)/20H2以降から全角と半角は別扱いになることで正常に動作しなくなる。

例1）DB項目名：担当者コード、VBアプリケーション項目名：担当者ｺｰﾄﾞ
例2）DB項目名：ﾗﾍﾞﾙ種類、VBアプリケーション項目名：ラベル種類

この場合、プログラム修正が駄目ならDB側の項目名をプログラム側に合わせるとかすればいいのでしょうが、プログラム側で項目名が全角カタカナと半角カタカナで混在していたら、どうしようもないですね。
DB側の項目名変更も連携しているアプリケーションがあったら修正も駄目ですよね。

そもそもこんなプログラムを書いている時点どうかと思うのですが、実際こういう問題で動作しないアプリケーションが見つかり1月予定のWSUSが延期になりました。

## VBA/VBScript
StrComp関数の第3引数の比較モードでテキストモードの「１」または「vbTextCompare」を指定している場合です。
※未指定の場合は通常はバイナリモード（Access VBAの場合は「Option Compare Database」）で比較になっているのですが、VB.NETのところで記載しているように「Option Compare Text」を指定していた場合には、未指定でもテキストモードになります。
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/strcomp-function

```vb:Windows10-Ver.1909
MsgBox StrComp("ｺｰﾄﾞ","コード", vbTextCompare)
0
```

Windows 10 ver 2004/20H2になると結果が変わります。

```vb:Windows10-Ver.2004/20H2
MsgBox StrComp("ｺｰﾄﾞ","コード", vbTextCompare)
1
```

## VB.NET
「Option Compare Text」を指定していた場合またはVBA/VBScriptのところで記載しているようにStrComp関数の第3引数の比較モードでテキストモード「CompareMethod.Text」を指定している場合になります。
https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.strings.strcomp?view=net-5.0

※.NET上のStrComp関数は、Microsoft.VisualBasic名前空間になっているので C#でも使えるのですが、あまり使われることはないと思います。

```vb:Windows10-Ver.1909
Option Compare Text

Dim s1 As String = "ｺｰﾄﾞ"
Dim s2 As String = "コード"
Debug.WriteLine(String.Format("{0},{1}", StrComp(s1, s2), s1 = s2))

0,True
```

.NET Framework 4.0〜4.8では、Windows 10 ver 2004/20H2になると結果が変わります。

```vb:Windows10-Ver.2004/20H2
Option Compare Text

Dim s1 As String = "ｺｰﾄﾞ"
Dim s2 As String = "コード"
Debug.WriteLine(String.Format("{0},{1}", StrComp(s1, s2), s1 = s2))

1,False
```

.NET Framework 2.0〜3.5では、Windows 10 ver 2004/20H2でも結果は変わりません。

```vb:Windows10-Ver.2004/20H2
Option Compare Text

Dim s1 As String = "ｺｰﾄﾞ"
Dim s2 As String = "コード"
Debug.WriteLine(String.Format("{0},{1}", StrComp(s1, s2), s1 = s2))

0,True
```

## Access
Accessでフォーム名に半角カナ + カナに濁音を含んでいる場合、Accessファイルを開くとエラーが発生します。

>Access アプリケーションでは、フォーム名に関して OS で用意している機能を利用し、半角と全角とを区別せずに比較しています。
[Windows 10 バージョン 2004 (20H1) / 20H2 上で 半角カナのフォームを含んだ Access ファイルでエラーが発生する](https://social.msdn.microsoft.com/Forums/ja-JP/4e6223e2-34d0-4a5f-bb61-109bc28040b6/windows-10-1249612540124721251912531-2004-20h1-20h2-1997812391?forum=officesupportteamja)

## Excel
Excelのシート名に「社員コード」と「社員ｺｰﾄﾞ」のように混在していた場合、「この名前は既に使用されています。別の名前を入力してください。」というエラーになります。

## その他
合字データ (㋿ や ㍻) のソート順も変更されています。
よって、合字を利用する場合にソート順が変わります。

|OS バージョン|合字の昇順|
|:--|:--|
|1909|㋿ ㍻ ㍾ ㍼|
|2004 (20H1) / 20H2|㍾ ㍼ ㍻ ㋿|

# 原因
Windows 10 バージョン 2004 で、OS の自然言語処理を担う NLS (National Language Support) バージョンが更新されました。

|OS バージョン|NLS バージョン|
|:--|:--|
|1909|6.2|
|2004 (20H1) / 20H2|6.3|

この新しいバージョン 6.3 の NLS ソート テーブルにて、「濁点・半濁点を含む半角カナと全角カナを同じ文字として解釈しない」という変更が行われたことにより、この問題が発生しています。

>Certain Japanese half-width Katakana and full-width Katakana characters that have a consonant mark aren’t interpreted as the same character. When you use the CompareStringEx() function with the NORM_IGNOREWIDTH flag to compare them, these characters are evaluated as different because of an issue in the sorting rule. This issue affects all the updates starting on October 29, 2020 for Windows 10, version 20H2.
https://support.microsoft.com/en-us/help/4581839/windows-10-update-history

# 対応
## StrConv関数 
StrConv 関数で全角、または半角に統一してから比較する。

```vb
str1 = "サンプル"
str2 = "ｻﾝﾌﾟﾙ"
MsgBox StrComp(StrConv(str1, vbWide), StrConv(str2, vbWide), vbTextCompare)
```

## Accessフォーム名
Accessでフォーム名は全角に変更する。

## OSレベル
レジストリーを変更します。これによりシステム全体で影響を受けるため、Office 以外のアプリケーションも以前の NLS バージョンを使用するようになります。
※アプリケーションの実装によっては、ソートの整合が崩れたりデータが不正となる可能性があります。

NLS のバージョン 6.3 → 6.2 にダウングレード

```bat:ダウングレード
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Nls\Sorting\Versions /ve /d 0006020F /f
```

NLS のバージョン 6.２ → 6.３ にアップグレード

```bat:アップグレード
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Nls\Sorting\Versions /ve /d 00060305 /f
```

# 動作検証テスト
## ソースコードによる検証
ソースコードがあるなら、grep検索で「StrConv」または「Option Compare Text」を使用しているか確認しましょう。比較モードがテキストモードになっていると問題が発生します。
Accessの場合はフォーム名に半角カナを使用しているか確認する。もっともAccessファイルを開いた時点でエラーが発生するので、動作検証はすぐ確認が出来ます。

【2021/02/10追記】
DB項目名とVBアプリケーションの項目名で半角カナを使用しているか確認する。

## 実施による検証
* 名称検索する箇所で「半角カナ + カナに濁音」により抽出されないことで検索結果が異なることが考えられます。しかし、DBを使わないで独自処理していることってあまり考えられない。
* 合字データ (㋿ や ㍻)を使用していた場合にソート順が異なるので、和暦をリストボックスで使用していた場合に順序が変わる可能性があります。

# 最後に
個人ではあまり問題にならないと思います。企業だとWSUSを使用していることが多いので、これからWindows 10 ver 2004の動作検証で問題が発生してくる可能性はありますね。
.NETアプリケーションでも、.NET Framework 2.0〜3.5を使用した場合は以前のままなので、ターゲットフレームワークを変更した場合に確認が必要になります。

Microsoft的にも仕様として~~今後も修正するつもりはない~~ですから、問題が発生したなら素直に修正するしかないですね。

# 参照
* [魔界の仮面弁士氏のツイート](https://twitter.com/Benshi_Orator/status/1326689347127500800)
* [2004、パパがﾊﾟﾊﾟでなくなった日（Windows 10 ver 2004/20H2 の日本語固有のバグ）](https://yamanxworld.blogspot.com/2020/11/2004windows-10-ver-200420h2.html)