ユーザー名にマルチバイト文字が使われている場合にASP.NET CoreのgRPCプロジェクトのビルドが失敗する場合の対処方法

# はじめに

ASP.NET CoreのgRPCのテンプレートから新しいプロジェクトを作っただけなのに、`protoc-gen-grpc: The system cannot find the path specified` というメッセージが表示され、ビルドが通らない場合の対処方法です。

# エラーの内容

コンソールで新しいgRPCのプロジェクトを作成してビルドした場合、次のようなメッセージが表示されprotoファイルのビルドに失敗することがあります。

```bat:コンソールでの実行結果
❯ dotnet new grpc
テンプレート "ASP.NET Core gRPC Service" が正常に作成されました。

作成後の操作を処理しています...
C:\localrepo\Hoge\Hoge.csproj で ' dotnet restore ' を実行しています...
  復元対象のプロジェクトを決定しています...
  C:\localrepo\Hoge\Hoge.csproj を復元しました (4.08 sec)。
正常に復元されました。

❯ dotnet build
.NET 向け Microsoft (R) Build Engine バージョン 17.1.1+a02f73656
Copyright (C) Microsoft Corporation.All rights reserved.

  復元対象のプロジェクトを決定しています...
  復元対象のすべてのプロジェクトは最新です。
--grpc_out : error : protoc-gen-grpc: The system cannot find the path specified. [C:\localrepo\sugiyama\Hoge\Hoge.csproj]

ビルドに失敗しました。

--grpc_out : error : protoc-gen-grpc: The system cannot find the path specified. [C:\localrepo\sugiyama\Hoge\Hoge.csproj]
    0 個の警告
    1 エラー

経過時間 00:00:04.06
```

# 原因

このIssueで言及され対応されていますが、Nugetの[grpc_tools](https://www.nuget.org/packages/Grpc.Tools/)でインストールされる`protc.exe`が非ASCII文字を含んだパス配下に格納されると、protoファイルのビルドに失敗することが原因のようです。

- [Grpc.Tools: Accented characters in nuget path breaks c# grpc tool compiler #17995](https://github.com/grpc/grpc/issues/17995)

このIssueは[このPR](https://github.com/protocolbuffers/protobuf/pull/10200)がマージされたとしてクローズされているので、もう少し待てば今回の対応は不要になるかもしれません。少なくとも、2022/09/06時点の最新である[2.48.0](https://www.nuget.org/packages/Grpc.AspNetCore/2.48.0)やPreview版の[2.49.0-pre1](https://www.nuget.org/packages/Grpc.AspNetCore/2.49.0-pre1)では対応が必要なようです。

# grpc_toolsの場所
grpc_toolsがどこにインストールされているかは次のコマンドで確認できる`global-packages`配下のディレクトリに保存されます。見事に日本語のディレクトリ配下に保存されていますね。

```
❯ dotnet nuget locals all --list
http-cache: C:\Users\杉山洋一\AppData\Local\NuGet\v3-cache
global-packages: C:\Users\杉山洋一\.nuget\packages\
temp: C:\Users\杉山洋一\AppData\Local\Temp\NuGetScratch
plugins-cache: C:\Users\杉山洋一\AppData\Local\NuGet\plugins-cache
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/6da42b2b-71d9-c324-2d26-bb61573dfa7e.png)

ユーザー名を英語などで定義すればこの問題は起きませんが、企業で利用している場合などで、AzureADなどのユーザー名が日本語で定義されていると逃れようがないので、`global-packages`ディレクトリを非マルチバイトなディレクトリに変更してする必要があります。

# 対処方法

`global-packages`ディレクトリを変更にするには次のような方法があります。

- dotnet コマンドの`--packages`オプションを利用して復元する
- OSの環境変数 NUGET_PACKAGES を設定する
- グローバルな Nuget.Config を利用する
- ローカルの Nuget.Config を利用する

OSの環境変数やグローバルな設定ファイルでは他のプロジェクトへの影響が大きいですし、dotnetコマンドを使った解決ではVisual Studioでの作業の時に困るので、今回はプロジェクトディレクトリ(もしくはソリューションディレクトリ）に下記のような[Nuget.Config](https://docs.microsoft.com/ja-jp/nuget/reference/nuget-config-file)を作成する方法で対応しました。

```xml:Nuget.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <config>
        <add key="globalPackagesFolder" value="c:\temp\nuget\packages" />
    </config>
</configuration>
```

改めてディレクトリを確認すると、`global-packages`が書き換わっているのがわかりますね。

```
❯ dotnet nuget locals all --list
http-cache: C:\Users\杉山洋一\AppData\Local\NuGet\v3-cache
global-packages: c:\temp\nuget\packages
temp: C:\Users\杉山洋一\AppData\Local\Temp\NuGetScratch
plugins-cache: C:\Users\杉山洋一\AppData\Local\NuGet\plugins-cache
```

念のため、Nugetのキャッシュをクリアした後に
```
dotnet nuget locals global-packages --clear
```

ビルドすると、問題なくビルドできるようになります。

```
> dotnet build
.NET 向け Microsoft (R) Build Engine バージョン 17.1.1+a02f73656
Copyright (C) Microsoft Corporation.All rights reserved.

  復元対象のプロジェクトを決定しています...
  復元対象のすべてのプロジェクトは最新です。
  Hoge -> C:\localrepo\sugiyama\Hoge\bin\Debug\net6.0\Hoge.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:07.02
```

# おわりに
Windowsの文化圏にいると忘れがちですが、外から入ってくるツールではまだまだ日本語とかマルチバイトをちゃんと考慮できていないツールのことを気にしないとダメですね。