もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
WinUI3のUserControlを作って、それを複数のWinUI3アプリで共用したいなと思い、UserControlをdllにして、それをnupkgにして他アプリでも使えるようにしようとした。
いざ、UserControlを含むnupkgを作ってWinUI3アプリから使おうとすると、下図のようなエラーが出た。
どうにかしたい。
前提
- .net6
- WindowsAppSDK 1.1.3
- 2022/12/21時点で試した内容
原因
どうも、作った.nupkgの中に、「XXXXX.xbf」というファイルが含まれていないのが原因らしい。
本当は、nupkgの中の下記のフォルダに、この場合で行くと「MyControl.xbf」というファイルが無いといけないが、これがないためにエラーが起きてしまう。
対応策
このやり方がいいかどうかはおいといて、こうやったら動いた。
VSのプロジェクトのプロパティのビルド操作中にパッケージファイルを生成します
をONにする。 これをONにすると、ビルドすると自動でnupkgを作ってくれる。
※dotnet packコマンドでもできるので、別の方法でnupkg作りたい場合はこのチェック無しでもOK。
次に、 UserControlを含むプロジェクトのcsprojのPropertyGroupに、
<GenerateLibraryLayout>true</GenerateLibraryLayout>
を追記する。
※ただ、これをやらなくても動く気がする。下に挙げた参考ページではやれとあるので、一応書いておく。
ビルドする。
ビルドすると、出力先フォルダに.nupkg
ができる。
この.nupkgを、解凍する。
nupkgは、拡張子を.zipに変えて、zipとして解凍しれやれば、中身を見ることができる。
その中の、下の「★★ココ」のところに、.xamlと並んで、本当は「MyControl.xbf」があってほしいのだが、ない。
│ WinUI3Controls.nuspec │ [Content_Types].xml │ ├─lib │ └─net6.0-windows10.0.19041 │ │ WinUI3Controls.dll │ │ WinUI3Controls.pri │ │ │ └─WinUI3Controls │ MyControl.xaml ←★★ココ │ ├─package │ └─services │ └─metadata
「MyControl.xbf」は、nupkgの中ではなく、普通にビルドした出力フォルダの方には入っている。
ので、それをコピーして、nupkgを解凍したフォルダの中の「★★ココ」に貼り付ける。
その後、そのフォルダを再度zipして、拡張子を.nupkgにして、それを使いたいWinUi3プロジェクトから見ると、エラーなく使うことができた。
※再度zipして.nupkgにするとき、中身のフォルダ階層が間違えてると下図のようなエラーになる。地味にハマったので注意。
22/12/25追記
一つ、マシなやり方を見つけた。
nuspecファイルを作成して、それを使ってnupkgをつくる。
マシなやり方内容
まず、下記のようなnuspecファイルを作る。
ファイル名は何でもいいが、いったんWinUI3Controls.nuspec
にする。
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <metadata> <id>WinUI3Controls</id> <version>1.0.0</version> <authors>WinUI3Controls</authors> <description>Package Description</description> <dependencies> <group targetFramework="net6.0-windows10.0.19041"> <dependency id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.755" exclude="Build,Analyzers" /> <dependency id="Microsoft.WindowsAppSDK" version="1.2.221209.1" exclude="Build,Analyzers" /> </group> </dependencies> </metadata> <files> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\*.dll" target="lib\net6.0-windows10.0.19041\" /> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\*.pri" target="lib\net6.0-windows10.0.19041\" /> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\WinUI3Controls\*.*" target="lib\net6.0-windows10.0.19041\WinUI3Controls" /> </files> </package>
上記の.nuspecを、csprojファイルと同じ階層に置く。
VisualStudioから、WinUI3Controlsのプロジェクトをビルドして、出力フォルダ(binフォルダ)ができた状態にしておく。
VisualStudioの「開発者用Powershell」で、cdでそのcsprojファイルと同じ階層に行く。
そこで、コマンドdotnet pack -p:NuspecFile=.\WinUI3Controls.nuspec
を実行する。
すると、xbfが含まれたnupkgが作成される。
やったこと
nuspecの中の、下記がキモ。
(それ以外の部分は、デフォルト?で出力される(VSが吐いたnupkgの中に含まれる)nuspecと同じ内容。)
<files> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\*.dll" target="lib\net6.0-windows10.0.19041\" /> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\*.pri" target="lib\net6.0-windows10.0.19041\" /> <file src=".\bin\Debug\net6.0-windows10.0.19041.0\WinUI3Controls\*.*" target="lib\net6.0-windows10.0.19041\WinUI3Controls" /> </files>
やったのは、 出力先フォルダの中から、nupkgに含めるファイルを指定した、ということ。
上記をnuspecに書いてあげれば、xbfを含む今回必要なファイルが入ってくれた。
さらにもう少しましなnuspec
下記のnuspecでいけそう。
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <metadata> <id>WinUI3Controls</id> <version>1.0.0</version> <authors>WinUI3Controls</authors> <description>Package Description</description> <dependencies> <group targetFramework="net6.0-windows10.0.19041"> <dependency id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.755" exclude="Build,Analyzers" /> <dependency id="Microsoft.WindowsAppSDK" version="1.2.221209.1" exclude="Build,Analyzers" /> </group> </dependencies> </metadata> <files> <file src=".\bin\Debug\**\*.*" exclude="**/*.pdb;**/*.json" target="lib\" /> </files> </package>
出力先フォルダの中身全部を、nupkgのlibフォルダの下に、pdbとか、不要なもの以外全部入れてやるイメージ。
これで、必要なものが一式入る。
「ビルド操作中にパッケージファイルを生成します」のチェックを外しておいて、ビルド後イベントにdotnet pack -p:NuspecFile=.\WinUI3Controls.nuspec
を入れておいてあげれば、ビルドするごとに新しいnupkg作れるようになりそう。
⇒参考
参考
〇nuspecに好きなアセンブリファイルを含める方法(MS公式)
https://learn.microsoft.com/ja-jp/nuget/reference/nuspec#including-assembly-files
〇XAML コンポーネントを含む NuGet パッケージがある場合は、XAML バイナリ ファイル (.xbf) を手動で含める必要があります。そうしないと、解析が失敗します。よくわかりましたが、なんと頭の痛い問題でしょう。
〇Windows Phone 8.1 NuGet packages with XAML components
そんなに昔から引きずっている現象なのか??
https://dschenkelman.github.io/2014/06/25/windows-phone-8-1-nuget-packages-with-xaml-components/
〇How can I add my UserControl to my NugetPackage?
UWPでもWPFでもなんでも、UserControlをNupkgにしようと思うと、手動で必要なものを含めないといけないっぽい。
https://stackoverflow.com/questions/40182778/how-can-i-add-my-usercontrol-to-my-nugetpackage
UWPのControlをnupkgにしたいときの調査記事。具体的でわかりやすい。
https://blog.tmyt.jp/entry/2015/11/03/040916
上記記事の、nuspecにfilesを書く書き方が、下記の公式にあるっぽい。(まだあまり見てない)
〇nugetパッケージの作成方法公式
https://learn.microsoft.com/ja-jp/nuget/create-packages/creating-a-package