三行要約
- 🔥 Windows用のCLIツールを作りたい!wingetに登録だ!
- 💀 GitHub Releaseしたexeファイルをwingetcreate newしてもエラーになる!
- 🤔 原因はもしや言語設定にある...?
はじめに
当方3回目のQiitaへの投稿となります、Helloween Head's Depotです。よろしくお願いします。
Windowsにおけるコマンドラインパッケージマネージャ(つまりCLIツールを簡単に入れたり消したりできるやつ)、Winget へ自分で新しくCLIツールを作成し申請したい!といった、wingetcreate newを使おうとしている方に向けた備忘録です。
Wingetにコマンドを登録する本来の方法
WingetはOSSとしてGitHub上にリポジトリが公開されており、ここにPull Requestを投げかける事で一応登録ができるようなのですが、、、これが主導でやると非常に面倒くさい。調べた範囲によると、YAML形式のマニフェストを書くそうですが、日本語の参考ブログの少ないこと!
wingetcreateとは
でもMicrosoftも馬鹿じゃない。その為にwingetcreateという簡単にちょちょっとコマンドを打っていくつか質問に答えるだけでwingetリポジトリへのツール申請ができるツールを既に公開してあるのです。
インストール方法:
winget install wingetcreate
ここで次にwingetcreate newというのを打つのですが、その前に一旦自分が提出したいバイナリファイル(exe, msi, msix等々)をどっかサーバーに置かなくてはいけません。当然個人サイトという手もありますが、最も手軽な手法はGitHub Releaseに置く事です。
wingetcreate newは引数としてバイナリファイルをダウンロードできるURLを求めますので以下のように打てます。
wingetcreate new <Binary File URL>
ここでもしあなたが僕と同じように日本語環境を使っていると、以下のようなエラーが出るかもしれません。
PS C:\> wingetcreate new "https://github.com/OWNER/REPO/releases/download/TAG/tool.exe"
ダウンロードして解析しています: https://github.com/OWNER/REPO/releases/download/TAG/tool.exe...
[https://github.com/OWNER/REPO/releases/download/TAG/tool.exe] からパッケージを解析できませんでした。
PS C:\>
なんでぇ!?
原因
原因は恐らくですが、特定しました。winget-createリポジトリのsrc/WingetCreateCore/Common/PackageParser.cs、そのにこのようなコードがあるのです。
catch (Win32Exception err)
{
if ((err.Message == "The specified resource type cannot be found in the image file."
&& err.NativeErrorCode == 1813) ||
(err.Message == "The specified image file did not contain a resource section."
&& err.NativeErrorCode == 1812))
{
installerTypeEnum =
(baseInstaller.InstallerType == InstallerType.Portable ||
baseInstaller.NestedInstallerType == NestedInstallerType.Portable) ?
nstallerType.Portable : InstallerType.Exe;
}
else
{
return false;
}
}
ここで、Win32Exceptionとは、Win32 API由来のエラーを表す.NETの例外エラーです。
問題は条件分岐、ここ、指定した種類のリソースが見つからないというエラーの判別です。私のケースではここで求められている「EXEに埋め込まれたWindowsアプリケーションマニフェスト」が存在しないので、err.NativeErrorCode == 1813に則り、ifに引っ掛かり下の処理の通りに通常のEXEファイルとして扱われるはずでした。
ところが、ここが恐らくTerminalの設定が日本語になっているとerr.Message自体も日本語で表示される為ifの分岐が狂わされているという感じのようです。
対処法
大凡2 つあります。現在最新版のv1.12.13.0 wingetcreateで試してこのエラーを得たため、同じエラーが出る場合、それでもwingetcreateを使うとなると少し工夫が要ります。
wingetcreate自体を改造して使う
私はこの方法で上手く申請ができました。大事なファイル等が置かれていないディレクトリで
git clone https://github.com/microsoft/winget-create
cd .\winget-create
でwingetcreate本体のソースコードを下ろし、上で触れた問題個所をの修正します。
catch (Win32Exception err)
{
if (err.NativeErrorCode == 1813 || err.NativeErrorCode == 1812)
{
installerTypeEnum =
(baseInstaller.InstallerType == InstallerType.Portable ||
baseInstaller.NestedInstallerType == NestedInstallerType.Portable) ?
nstallerType.Portable : InstallerType.Exe;
}
else {
return false;
}
}
英語のエラーメッセージによる条件分岐を消した上でプロジェクトを以下のコマンドでビルドします。
dotnet build .\src\WingetCreateCLI\WingetCreateCLI.csproj -c Release -p:Platform=x64 -r win-x64 -o .\artifacts\local
これで改造したexeファイルが出てきますので、
.\artifacts\local\WingetCreateCLI.exe new "https://github.com/OWNER/REPO/releases/download/TAG/tool.exe"
を打ってください。すると、日本語環境でも同様にwingetツールの申請ができます。
自分でyaml等を書き手動でpull requestを行う
調べたけど、、、、よくわからなかったぁ。(本当にスミマセン。。。)
でも理論上はできるはずです!たぶん!(なんかClaudeに相談してたら「もうお前手動でやれよ」ってな勢いで勝手にyaml書いてきました。使ってないけど。)
一応公式のマニュフェスト作成方法は見つけました。ただし、読んでみましたが私にはちんぷんかんぷんです。
まとめ
一応今回のバグについては本家のwinget-createにてIssueを立ててみました。しかし、実際の改善までには暫し時間がかかると思うので、もしも同じエラーで困った方がいらっしゃればお助けになると幸いです。
お読みいただきありがとうございました。💛