{"id":5108,"date":"2022-10-10T20:34:23","date_gmt":"2022-10-10T20:34:23","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=5108"},"modified":"2022-10-11T08:30:16","modified_gmt":"2022-10-11T08:30:16","slug":"creating-a-vsix-based-project-template","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/creating-a-vsix-based-project-template\/","title":{"rendered":"Creating a VSIX based project template"},"content":{"rendered":"<p><em>Note: This post was written a while back but sat in draft. I&#8217;ve published this now, but I&#8217;m not sure it&#8217;s relevant to the latest versions etc. so please bear this in mind.<\/em><\/p>\n<p>In this post we&#8217;re going to create a Prism Project Template using VSIX (as opposed to the File | Export Template option in Visual Studio). This is a relatively simple project template which will create a simple Prism based WPF application, so will demonstrate creating the project template itself along with adding nuget packages etc. and can be used as a starting point for other, more complex Prism based applications.<\/p>\n<ul>\n<li>Create New Project<\/li>\n<li>Extensibility | VSIX Project<\/li>\n<li>Delete index.html and stylesheet.css &#8211; no use for our project<\/li>\n<li>Add New Project | Extensibility | C# Project Template<\/li>\n<li>Double click source.extension.vsixmanifest<\/li>\n<li>Select Assets tab<\/li>\n<li>New, Type Microsoft.VisualStudio.ProjectTemplate<\/li>\n<li>&#8220;Source&#8221; set to A project in current solution<\/li>\n<li>&#8220;Project&#8221; set to the added C# project template<\/li>\n<li>Remove Class1.cs and remove the following line from the vstemplate in the project\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;Class1.cs&lt;\/ProjectItem&gt;\r\n<\/pre>\n<\/li>\n<li>From ProjectTemplate.csproj also remove the line\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Compile Include=&quot;Class1.cs&quot; \/&gt;\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>Now we have an empty class library template (in every sense). <\/p>\n<p><strong>Creating a very basic WPF Project template<\/strong><\/p>\n<ul>\n<li>In ProjectTemplate.csproj change OutputType from Library to WinExe<\/li>\n<li>In ProjectTemplate.csproj in the ItemGroup with Reference elements add\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Reference Include=&quot;System.Xaml&quot;&gt;\r\n   &lt;RequiredTargetFramework&gt;4.0&lt;\/RequiredTargetFramework&gt;\r\n&lt;\/Reference&gt;\r\n&lt;Reference Include=&quot;WindowsBase&quot; \/&gt;\r\n&lt;Reference Include=&quot;PresentationCore&quot; \/&gt;\r\n&lt;Reference Include=&quot;PresentationFramework&quot; \/&gt;\r\n<\/pre>\n<\/li>\n<li>To the Project template project add new item WPF | User Control(WPF) name it App.xaml<\/li>\n<li>Replace the XAML with\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Application x:Class=&quot;$safeprojectname$.App&quot;\r\n             xmlns=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&quot;\r\n             xmlns:x=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&quot;&gt;\r\n    &lt;Application.Resources&gt;\r\n    &lt;\/Application.Resources&gt;\r\n&lt;\/Application&gt;\r\n<\/pre>\n<\/li>\n<li>Change App.xaml.cs to\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing System.Windows;\r\nusing System.Windows.Controls;\r\nusing System.Windows.Data;\r\nusing System.Windows.Documents;\r\nusing System.Windows.Input;\r\nusing System.Windows.Media;\r\nusing System.Windows.Media.Imaging;\r\nusing System.Windows.Navigation;\r\nusing System.Windows.Shapes;\r\n\r\nnamespace $safeprojectname$\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Interaction logic for App.xaml\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public partial class App : Application\r\n    {\r\n        protected override void OnStartup(StartupEventArgs e)\r\n        {\r\n            base.OnStartup(e);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<\/li>\n<li>For both files, show the properties (F4) window and set Build Action to None or the compiler will attempt to compile the code<\/li>\n<li>Inthe project&#8217;s vstemplate add the following within the project element\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;App.xaml&lt;\/ProjectItem&gt;\r\n&lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;App.xaml.cs&lt;\/ProjectItem&gt;\r\n<\/pre>\n<\/li>\n<li>In the csproj file add the following to the ItemGroup with the line<br \/>\n&gt;Compile Include=&#8221;Properties\\AssemblyInfo.cs&#8221; \/&lt;<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    &lt;Compile Include=&quot;App.xaml.cs&quot;&gt;\r\n      &lt;DependentUpon&gt;App.xaml&lt;\/DependentUpon&gt;\r\n      &lt;SubType&gt;Code&lt;\/SubType&gt;\r\n    &lt;\/Compile&gt;\r\n<\/pre>\n<\/li>\n<li>Create a new ItemGroup in the csproject with the following\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;ItemGroup&gt;\r\n    &lt;ApplicationDefinition Include=&quot;App.xaml&quot;&gt;\r\n      &lt;Generator&gt;MSBuild:Compile&lt;\/Generator&gt;\r\n      &lt;SubType&gt;Designer&lt;\/SubType&gt;\r\n    &lt;\/ApplicationDefinition&gt;\r\n  &lt;\/ItemGroup&gt;\r\n<\/pre>\n<\/li>\n<\/ul>\n<p><strong>Adding Prism<\/strong><\/p>\n<p>At this point if you try to run this template it should create a valid  project but it will not run as there&#8217;s no Main entry point. This was on purpose as we don&#8217;t need the StartupUri set in the App.xaml.<\/p>\n<p>We&#8217;re going to need to load up nuget packages for prism<\/p>\n<ul>\n<li>Add the following after the &lt;\/TemplateContent&gt;\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;WizardExtension&gt;\r\n    &lt;Assembly&gt;NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&lt;\/Assembly&gt;\r\n    &lt;FullClassName&gt;NuGet.VisualStudio.TemplateWizard&lt;\/FullClassName&gt;\r\n  &lt;\/WizardExtension&gt;\r\n  &lt;WizardData&gt;\r\n    &lt;packages repository=&quot;extension&quot; repositoryId=&quot;productId&quot;&gt;\r\n      &lt;package id=&quot;Prism.Core&quot; version=&quot;6.3.0&quot; \/&gt;\r\n      &lt;package id=&quot;Prism.Wpf&quot; version=&quot;6.3.0&quot; \/&gt;\r\n      &lt;package id=&quot;Prism.Unity&quot; version=&quot;6.3.0&quot; \/&gt;\r\n      &lt;package id=&quot;Unity&quot; version=&quot;4.0.1&quot; \/&gt;\r\n      &lt;package id=&quot;CommonServiceLocator&quot; version=&quot;1.3.0&quot; \/&gt;\r\n    &lt;\/packages&gt;\r\n  &lt;\/WizardData&gt;\r\n<\/pre>\n<p>Replacing the productId with the Product ID from your vsixmanifest\n<\/li>\n<li>In your vsix add a folder named Packages<\/li>\n<li>Goto https:\/\/www.nuget.org\/packages\/Prism.Core\/ and press download to grab Prism.Core<\/li>\n<li>As above for https:\/\/www.nuget.org\/packages\/Prism.Wpf\/, https:\/\/www.nuget.org\/packages\/CommonServiceLocator\/ and https:\/\/www.nuget.org\/packages\/Unity\/<\/li>\n<li>Copy\/save the nupkg to your new Packages folder<\/li>\n<li>Back in Visual Studio select show all files then right mouse click on the nupkg files and select include in project<\/li>\n<li>Set the build action to Content in the Properties (F4) view on each file and Copy to output to Copy Always, also set Include in VSIX to True<\/li>\n<li>Add the following to the Assets section in the vsixmanifest\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    &lt;Asset Type=&quot;prism.core.6.3.0.nupkg&quot; d:Source=&quot;File&quot; Path=&quot;Packages\\prism.core.6.3.0.nupkg&quot; d:VsixSubPath=&quot;Packages&quot; \/&gt;\r\n    &lt;Asset Type=&quot;prism.unity.6.3.0.nupkg&quot; d:Source=&quot;File&quot; Path=&quot;Packages\\prism.unity.6.3.0.nupkg&quot; d:VsixSubPath=&quot;Packages&quot; \/&gt;\r\n    &lt;Asset Type=&quot;prism.wpf.6.3.0.nupkg&quot; d:Source=&quot;File&quot; Path=&quot;Packages\\prism.wpf.6.3.0.nupkg&quot; d:VsixSubPath=&quot;Packages&quot; \/&gt;\r\n    &lt;Asset Type=&quot;unity.4.0.1.nupkg&quot; d:Source=&quot;File&quot; Path=&quot;Packages\\unity.4.0.1.nupkg&quot; d:VsixSubPath=&quot;Packages&quot; \/&gt;\r\n    &lt;Asset Type=&quot;commonservicelocator.1.3.0.nupkg&quot; d:Source=&quot;File&quot; Path=&quot;Packages\\commonservicelocator.1.3.0.nupkg&quot; d:VsixSubPath=&quot;Packages&quot; \/&gt;\r\n<\/pre>\n<\/li>\n<\/ul>\n<p><strong>Add the Boostrapper<\/strong><\/p>\n<p>For Prism to work we need to add the boostrapper so in your project template add a new CS file named ShellBootstrapper.cs and as we&#8217;re using Unity here, it should look like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing Microsoft.Practices.Unity;\r\nusing Prism.Unity;\r\nusing System.Windows;\r\n\r\nnamespace $safeprojectname$\r\n{\r\n    class ShellBootstrapper : UnityBootstrapper\r\n    {\r\n        protected override DependencyObject CreateShell()\r\n        {\r\n            return Container.Resolve&lt;MainWindow&gt;();\r\n        }\r\n\r\n        protected override void InitializeShell()\r\n        {\r\n            Application.Current.MainWindow.Show();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>set the Build Action in the properties (F4) window to None. In the csproj add under the other Compile entry<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    &lt;Compile Include=&quot;ShellBootstrapper.cs&quot; \/&gt;\r\n<\/pre>\n<p>We now need a MainWindow, so add a UsecControl.xaml named MainWindow.xaml, set Build Action to None and changed the XAML from UserControl to Window and the same in the cs file, here&#8217;s the code<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Window x:Class=&quot;$safeprojectname$.MainWindow&quot;\r\n             xmlns=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&quot;\r\n             xmlns:x=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&quot;\r\n             xmlns:mc=&quot;http:\/\/schemas.openxmlformats.org\/markup-compatibility\/2006&quot; \r\n             xmlns:d=&quot;http:\/\/schemas.microsoft.com\/expression\/blend\/2008&quot; \r\n        xmlns:cal=&quot;http:\/\/www.codeplex.com\/prism&quot;\r\n             xmlns:local=&quot;clr-namespace:$safeprojectname$&quot;\r\n             mc:Ignorable=&quot;d&quot; \r\n             d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;300&quot;&gt;\r\n    &lt;ItemsControl cal:RegionManager.RegionName=&quot;MainRegion&quot; \/&gt;\r\n&lt;\/Window&gt;\r\n\r\n<\/pre>\n<p>and the code is<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing System.Windows;\r\nusing System.Windows.Controls;\r\nusing System.Windows.Data;\r\nusing System.Windows.Documents;\r\nusing System.Windows.Input;\r\nusing System.Windows.Media;\r\nusing System.Windows.Media.Imaging;\r\nusing System.Windows.Navigation;\r\nusing System.Windows.Shapes;\r\n\r\nnamespace $safeprojectname$.App\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Interaction logic for MainWindow.xaml\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public partial class MainWindow : Window\r\n    {\r\n        public MainWindow()\r\n        {\r\n            InitializeComponent();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>add the following in after the last ProjectItem in the vstemplate<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n      &lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;MainWindow.xaml&lt;\/ProjectItem&gt;\r\n      &lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;MainWindow.xaml.cs&lt;\/ProjectItem&gt;\r\n      &lt;ProjectItem ReplaceParameters=&quot;true&quot; OpenInEditor=&quot;true&quot;&gt;ShellBootstrapper.cs&lt;\/ProjectItem&gt;\r\n<\/pre>\n<p>Also add to csproj<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Compile Include=&quot;MainWindow.xaml.cs&quot;&gt;\r\n   &lt;DependentUpon&gt;MainWindow.xaml&lt;\/DependentUpon&gt;\r\n&lt;\/Compile&gt;\r\n<\/pre>\n<p>within the ItemGroup in the template&#8217;s csproj that has the None Include App.xaml place<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;Page Include=&quot;MainWindow.xaml&quot;&gt;\r\n   &lt;Generator&gt;MSBuild:Compile&lt;\/Generator&gt;\r\n   &lt;SubType&gt;Designer&lt;\/SubType&gt;\r\n&lt;\/Page&gt;\r\n<\/pre>\n<p>In the OnStartup of App.xaml.cs add<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar bootstrapper = new ShellBootstrapper();\r\nbootstrapper.Run();\r\n<\/pre>\n<p>If you now run the VSIX from Visual Studio, it should load up the Visual Studio Experimental instance and you should be able to create a project from the template which will build and run successfully.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Note: This post was written a while back but sat in draft. I&#8217;ve published this now, but I&#8217;m not sure it&#8217;s relevant to the latest versions etc. so please bear this in mind. In this post we&#8217;re going to create a Prism Project Template using VSIX (as opposed to the File | Export Template option [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[50],"tags":[],"class_list":["post-5108","post","type-post","status-publish","format-standard","hentry","category-visual-studio"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=5108"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5108\/revisions"}],"predecessor-version":[{"id":9572,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5108\/revisions\/9572"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=5108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=5108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=5108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}