ソリューションのVisualStudioテンプレートを作る

もくじ
https://tera1707.com/entry/2022/02/06/144447

テンプレート関連記事

やりたいこと

WinUI3のアプリを開発するときに、本番をつくるまえにいろいろ実験したいときが多い。

その際、実験用の小さなWinUI3アプリを作るのだが、毎回0から作るのが地味にめんどくさい。

(不要なConfigurationを消したり、必要な設定(selfcontainedとか)を入れたり、Pageを入れたり(Window直下だと実験しにくい))

ので、自分の実験用のWinUI3のソリューションのテンプレートを作りたい。

(今までテンプレートを作ったことがなかったので練習しときたい)

作成手順

もとになるソリューション、プロジェクトの作成

WindowsAppSDKが最初から持っている下記のテンプレートでソリューションを作る。

今回は、「WinUI3Template」という名前のソリューションにした。

で、そこから、私の実験に都合の良いように、ソリューションの設定をいじった。

やったことは、、、

  • x64以外のPlatformを削除
  • MainWindowに、NavigationViewを追加
  • Pageを2つほど追加
  • パッケージPJの名前にカッコが入るのが嫌なので変更する

その辺の作業をした結果、下記のような構成になった。

もとになるプロジェクトからテンプレート(.vstemplateと必要ファイル一式)をウィザードを使って作成する

ソリューション全部をテンプレート化する、みたいなことは現状(vs2022)ではできないっぽいので、slnに含まれるプロジェクトを全部テンプレート(.vstemplate)化して、それをソリューションのテンプレートとして手動でまとめる、みたいなことをする。

その作業のうちの、まず、slnに含まれるPJをテンプレート化する。

メニューの[プロジェクト] > [テンプレートのエクスポート]を選択する。

テンプレートのエクスポートウィザードが表示されるので、「プロジェクトのテンプレート」にチェックを入れて、下にあるコンボボックスから、対象のプロジェクトを選んで「次へ」を押す。(今回は、コンボボックス内にあるPJを全部テンプレート化するので、まずはどれを選んでもOK)

説明などを入力する画面が出てくる。

とりあえず今回は、、、

項目名 入力値
テンプレート名 テンプレートの名前になる値。今回は、デフォルト(元のPJ名のまま)にした。
テンプレートの説明 日本語もOK。VSのテンプレート選択画面には、PJではなくソリューションのvstemplateの説明が出るっぽいのでPJ側には適当に簡単な説明を書いておけばよいっぽい。
アイコンのイメージ 今回の実験ではなにもしないので空欄。
イメージのプレビュー 今回の実験ではなにもしないので空欄。

「テンプレートを自動的にVisualStudioにインポート」にチェックを入れると、 作成した.vstemplateが、しかるべき場所に配置されて、実際にVSの新規sln作成時にテンプレートとして出てくるようになる。

(「しかるべき場所」は、後述)

今回は、自分で配置したいのでチェックを外す。

「出力ファイルフォルダーにエクスプローラーウインドウを表示」にチェックを入れると、出力した.vstemplateの保存先フォルダをエクスプローラーで開いてくれる。保存場所は開いてほしいので、チェックを入れておく。

保存場所は、下記になる様子。

C:\Users\<ユーザー名>\Documents\Visual Studio 2022\My Exported Templates

ウィザードが完了すると、zipが出てくる。こんな感じ。

これを、プロジェクトの数だけ実施する。(今回の場合は、2つ分)

ソリューションのテンプレート(.vstemplate)を手で作成する

ベースはmsdocsのこれ

今回作った、

ソリューション全体の.vstemplate ファイルは下記の内容。

ファイル名は、「WinUI3Template.vstemplate」とする。

<VSTemplate Version="2.0.0" Type="ProjectGroup"
    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
    <TemplateData>
        <Name>MyWinUI3PackageProjectTemplate</Name>
        <Description>WinUI3パッケージソリューションの自作テンプレート</Description>
        <Icon>Icon.ico</Icon>
        <ProjectType>CSharp</ProjectType>
    </TemplateData>
    <TemplateContent>
        <ProjectCollection>
            <SolutionFolder Name="$projectname$">
                <ProjectTemplateLink ProjectName="$projectname$">
                    WinUI3Template\MyTemplate.vstemplate
                </ProjectTemplateLink>
                <ProjectTemplateLink ProjectName="$projectname$Package" CopyParameters="true">
                    WinUI3TemplatePackage\MyTemplate.vstemplate
                </ProjectTemplateLink>
            </SolutionFolder>
        </ProjectCollection>
    </TemplateContent>
</VSTemplate>

★ポイント★

★ソリューション配下のPJのテンプレートで、テンプレートのパラメータを使えるようにする

<ProjectTemplateLink ProjectName="$projectname$Package" CopyParameters="true">

この部分で、CopyParameters="true" を書かないと、配下の.vstemplate(今回だとWinUI3Template\MyTemplate.vstemplateWinUI3TemplatePackage\MyTemplate.vstemplate)の中で、テンプレートのパラメータ$ext_safeprojectname$ など)を使えないので、必ずつける。

また、上で使っているテンプレートパラメータの$ext_safeprojectname$は、テンプレート使用してslnを作成したときにVSで付けたsln名を指す。なので、上の例だと、「WinUI3Template」フォルダの下にあるテンプレートのPJ名をその名前にしようとしている。 (もうひとつのほうは、「その名前+Package」というPJ名にしようとしている。)

★配下のプロジェクト名を、ソリューション名とそろえる

ProjectTemplateLinkProjectNameに名前を指定しておくと、WinUI3Template\MyTemplate.vstemplateの子テンプレートの中に書かれているプロジェクト名を、自分で$ext_safeprojectname$とかを書かなくても、勝手に、テンプレート使用時にVisualStudioで付けたsln名と同じにしてくれる。

ここまでで作ったものを一旦集める

プロジェクトのテンプレート(2つ分)はzipで出てきたが、

このzip(2つ分)を一旦解凍して、同じフォルダに置く。

さらに、上で作ったソリューション全体の.vstemplate ファイル(WinUI3Template.vstemplate)も、同じフォルダに置く。

配下のPJのテンプレートの中身を調整する

どうも、ソリューションのvstemplateの中で、

                <ProjectTemplateLink ProjectName="$projectname$">
                    WinUI3Template\MyTemplate.vstemplate
                </ProjectTemplateLink>

等と書いているので、WinUI3Templateのプロジェクトの中にある「WinUI3Template」と書かれている個所については、自動的に$projectname$の内容に置き換わってくれるっぽい。

が、今回のパッケージプロジェクトの中の、wapprojが画面のほうの「WinUI3Template」のPJを「参照」している部分、具体的には下記の部分が、作ったテンプレートを使った新規ソリューションの中身に自動でついていかないようで、

こういうエラーが出た。

なので、wapprojの中のプロジェクト名(今回だと「WinUI3Template」)を直値で使っている部分を、テンプレートのパラメータに置き換える。

<PathToXAMLWinRTImplementations>WinUI3Template\</PathToXAMLWinRTImplementations><PathToXAMLWinRTImplementations>$ext_safeprojectname$\</PathToXAMLWinRTImplementations>
    <EntryPointProjectUniqueName>..\WinUI3Template\WinUI3Template.csproj</EntryPointProjectUniqueName><EntryPointProjectUniqueName>..\$ext_safeprojectname$\$ext_safeprojectname$.csproj</EntryPointProjectUniqueName>
    <ProjectReference Include="..\WinUI3Template\WinUI3Template.csproj" /><ProjectReference Include="..\$ext_safeprojectname$\$ext_safeprojectname$.csproj" />

にそれぞれ直した。

※正直、3つ目の「ProjectReference 」の修正以外は直さなくてもエラーは消えたのだが、元の名前のままでよいことはなさそうなので、一緒に直しておくことにした。

ここまでで作ったものをzipして固める

ここまでで、できたものを置いているフォルダは、下記のような構成になっているはず。

この3つのものをまとめて1つのzipにする。

細かいが、

  • この3つのファイル、フォルダを選択して、
  • 右クリックし、
  • [送る] > [圧縮(zip形式) フォルダー] を選択する

それでできたフォルダが、テンプレートのもとになるファイルとなる。

作ったテンプレートをしかる場き場所に配置する

ここまでで作ったzipファイルを、しかるべき場所に配置する。

しかるべき場所とは下記。

%USERPROFILE%\Documents\Visual Studio <version>\Templates\ProjectTemplates

私の環境だと下記になった。

C:\Users\<ユーザー名>\Documents\Visual Studio 2022\Templates\ProjectTemplates

ここの直下に、できたテンプレートを置くと、VSのsln新規作成時に出てくる。

★注意★

そのフォルダには、なんだか、C#やらVisualBasicやらのフォルダがあるので、そっちに入れたくなるが、 下の図のように、自分で作ったテンプレートはこのフォルダの直下に入れること。(C#とかのフォルダに入れるとVSに出てきてくれない。)

完了

これで完了。

こんな感じで、新規ソリューション作成時に、テンプレートとして出てきてくれる。

そのテンプレートから作ったソリューションはこうなる。

もちろん、元のソリューションと同じように、ビルドすればそのまま動く。

サンプル構成

ソリューションのテンプレート を元に、下記のような構成にした。

│─WinUI3Template.vstemplate
│  
├─WinUI3Template
│  │  app.manifest
│  │  App.xaml
│  │  App.xaml.cs
│  │  MainWindow.xaml
│  │  MainWindow.xaml.cs
│  │  MyTemplate.vstemplate
│  │  vstg0005.xaml
│  │  vstg0006.xaml
│  │  vstg0007.xaml
│  │  vstg0008.xaml
│  │  vstg0009.xaml
│  │  WinUI3Template.csproj
│  │  __TemplateIcon.ico
│  │  
│  ├─PROPERTIES
│  │  └─PUBLISHPROFILES
│  │          win10-x64.pubxml
│  │          
│  └─VIEW
│          MainPage.xaml
│          MainPage.xaml.cs
│          SubPage.xaml
│          SubPage.xaml.cs
│          vstg0001.xaml
│          vstg0002.xaml
│          vstg0003.xaml
│          vstg0004.xaml
│          
├─WinUI3TemplatePackage
│  │  MyTemplate.vstemplate
│  │  Package.appxmanifest
│  │  WinUI3TemplatePackage.wapproj
│  │  __TemplateIcon.ico
│  │  
│  └─IMAGES
│          LockScreenLogo.scale-200.png
│          SplashScreen.scale-200.png
│          Square150x150Logo.scale-200.png
│          Square44x44Logo.scale-200.png
│          Square44x44Logo.targetsize-24_altform-unplated.png
│          StoreLogo.png
│          Wide310x150Logo.scale-200.png

次やること

今回、テンプレートに「タグ」を付けてないので、テンプレートを使うときに、なんの括りにも属さないので探しにくい。

タグをつけて、「WinUI3」とかのカテゴリに属するようにして、探しやすくする。

ここを参考にするはず。

https://learn.microsoft.com/ja-jp/visualstudio/ide/template-tags?view=vs-2022

参考

ベースとなるmsdocs

https://learn.microsoft.com/ja-jp/visualstudio/ide/how-to-create-multi-project-templates?view=vs-2022

ソリューションのテンプレートを作るときのvstemplate

https://learn.microsoft.com/en-us/visualstudio/ide/how-to-create-multi-project-templates?view=vs-2022#example-with-solution-folders

.vstemplateファイルで使うタグの説明

https://learn.microsoft.com/en-us/visualstudio/extensibility/visual-studio-template-schema-reference?view=vs-2022

.vstemplateで使うテンプレートパラメータ($safeprojectname$ など)の一覧

https://learn.microsoft.com/ja-jp/visualstudio/ide/template-parameters?view=vs-2022

テンプレートのエクスポートウィザード

https://learn.microsoft.com/en-us/visualstudio/ide/how-to-update-existing-templates?view=vs-2022#use-the-export-template-wizard

あんまり関係なかったが、

csproj内で使えるマクロ($(ProjectName) など)の一覧

https://learn.microsoft.com/ja-jp/cpp/build/reference/common-macros-for-build-commands-and-properties?view=msvc-170