Skip to content

Commit ceb5f28

Browse files
authored
Updating CpsExtension sample to Dev 17, extending existing rule, fixes (#376)
* Updating CpsExtension sample to Dev 17, extending existing rule, various fixes * Adding a few additional diagnostic environment variables and some comments * Documentation improvements, better formatting * Re-introducing VsSDK.targets import as .vsix stopped being produced
1 parent c1bc8c7 commit ceb5f28

10 files changed

Lines changed: 78 additions & 26 deletions

File tree

doc/extensibility/extending_rules.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ existing rule of the same name.
77
This is useful if you are building ontop of an existing project system and want to add
88
or change properties to the existing rules.
99

10+
Please refer to the [CpsExtension sample](/samples/CpsExtension/) that shows adding a custom property to to a .cs file in an SDK-Style C# project.
11+
1012
Example:
1113

1214
```xml
@@ -42,6 +44,8 @@ and extending rule. In the case of collisions, the value of the extending rule i
4244
The source of a rule affects which rules it can override/extend, and which rules can override/extend it. Here are the sources in decreasing priority order (i.e. rules from sources earlier in the list can override/extend those later in the list):
4345

4446
1. MSBuild `PropertyPageSchema` items
47+
* Note that in SDK-style projects, the order of these items can be difficult to control due to how the SDK props and targets are included implicitly.
48+
* Using the default SDK-Style projects behavior, this mechanism works as expected if the `.targets` file defining the custom `PropertyPageSchema` items is imported via nuget package, but it doesn't work if it is imported from the project file directly.
4549
2. Rule _files_ added via `IAdditionalRuleDefinitionsService`
4650
3. Rule _objects_ added via `IAdditionalRuleDefinitionsService`
4751
4. Embedded `XAML` rules

samples/CpsExtension/CpsExtension.Nuget/Build/CpsExtension.Nuget.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
33

44
<PropertyGroup>
5-
<CpsExtensionDesignTimeTargetsPath Condition="'$(CpsExtensionDesignTimeTargetsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\CpsExtension\CpsExtensionNuget.DesignTime.targets</CpsExtensionDesignTimeTargetsPath>
5+
<CpsExtensionDesignTimeTargetsPath Condition="'$(CpsExtensionDesignTimeTargetsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\CpsExtension\CpsExtensionNuget.DesignTime.targets</CpsExtensionDesignTimeTargetsPath>
66
</PropertyGroup>
77

88
<Import Project="$(CpsExtensionDesignTimeTargetsPath)" Condition="'$(DesignTimeBuild)' == 'true' and Exists('$(CpsExtensionDesignTimeTargetsPath)')" />

samples/CpsExtension/CpsExtension.Nuget/CpsExtension.Nuget.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net461</TargetFramework>
4+
<TargetFramework>net472</TargetFramework>
55
<IsTool>true</IsTool>
66
<IncludeBuildOutput>false</IncludeBuildOutput>
77
<Version>1.1.0</Version>

samples/CpsExtension/CpsExtension.Vsix/BuildSystem/CpsExtension.DesignTime.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)CustomDebugger.xaml">
1010
<Context>Project</Context>
1111
</PropertyPageSchema>
12+
13+
<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)Compile.BrowseObject.xaml">
14+
<Context>BrowseObject</Context>
15+
</PropertyPageSchema>
16+
1217
</ItemGroup>
1318

1419
</Project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--Copyright, Microsoft Corporation, All rights reserved.-->
3+
<Rule
4+
Name="Compile"
5+
DisplayName="File Properties"
6+
PageTemplate="generic"
7+
Description="File Properties"
8+
OverrideMode="Extend"
9+
xmlns="http://schemas.microsoft.com/build/2009/properties">
10+
11+
<StringProperty Name="Foo" DisplayName="Foo Property" Category="Custom" />
12+
</Rule>

samples/CpsExtension/CpsExtension.Vsix/CpsExtension.Vsix.csproj

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
1414
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
1515

1616
<PropertyGroup>
17-
<TargetFramework>net461</TargetFramework>
17+
<TargetFramework>net472</TargetFramework>
1818
<GeneratePkgDefFile>false</GeneratePkgDefFile>
1919
<IsPackable>false</IsPackable>
20+
<!--Avoid embedding unneeded assemblies into the vsix. Note that this excludes all referenced assemblies (regardless if they are needed or not).
21+
An alternative option is to remove this property and suppress each extra assembly using SuppressFromVsix items. E.g.:
22+
<SuppressFromVsix Include="Microsoft.IO.Redist.dll" />-->
23+
<IncludeCopyLocalReferencesInVSIXContainer>false</IncludeCopyLocalReferencesInVSIXContainer>
2024
</PropertyGroup>
2125

2226
<ItemGroup>
23-
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Sdk" Version="15.8.243" />
24-
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="15.8.3247" />
27+
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.0.32112.339" ExcludeAssets="runtime" />
28+
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Sdk" Version="17.9.376" />
29+
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.9.3168" />
2530
</ItemGroup>
2631

2732
<ItemGroup>
@@ -37,7 +42,7 @@
3742
<ItemGroup>
3843
<VSIXSourceItem Include="BuildSystem\**" Exclude="**\*.cs">
3944
<InstallRoot>MSBuild</InstallRoot>
40-
<VSIXSubPath>Microsoft\VisualStudio\v15.0\CpsExtension\%(RelativeDir)</VSIXSubPath>
45+
<VSIXSubPath>Microsoft\VisualStudio\v17.0\CpsExtension\%(RelativeDir)</VSIXSubPath>
4146
<Visible>false</Visible>
4247
</VSIXSourceItem>
4348
</ItemGroup>
@@ -48,6 +53,15 @@
4853
</XamlPropertyRule>
4954
</ItemGroup>
5055

56+
<!--Copy the rule files to the output folder as a workaround for MSBuild issue https://github.com/dotnet/msbuild/issues/4494-->
57+
<Target Name="CopyRules" AfterTargets="Build">
58+
<ItemGroup>
59+
<RulesToCopy Include="BuildSystem\Rules\**\*" />
60+
</ItemGroup>
61+
<Message Importance="normal" Text="Copying rules to $(OutputPath)\BuildSystem\Rules" />
62+
<Copy SourceFiles="@(RulesToCopy)" DestinationFiles="@(RulesToCopy->'$(OutputPath)\BuildSystem\Rules\%(RecursiveDir)%(FileName)%(Extension)')" SkipUnchangedFiles="true" />
63+
</Target>
64+
5165
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
5266
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="Exists('$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets')" />
5367

samples/CpsExtension/CpsExtension.Vsix/CustomDebugger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
using System;
44
using System.Collections.Generic;
5-
using System.Composition;
5+
using System.ComponentModel.Composition;
66
using System.Threading.Tasks;
77
using Microsoft.VisualStudio.ProjectSystem;
88
using Microsoft.VisualStudio.ProjectSystem.Debug;
Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
{
2-
"profiles": {
3-
"CpsExtension": {
4-
"commandName": "Executable",
5-
"executablePath": "$(DevenvDir)devenv.exe",
6-
"commandLineArgs": "/rootsuffix exp",
7-
"environmentVariables": { "CpsExtensionDesignTimeTargetsPath": "$(OutputPath)BuildSystem\\CpsExtension.DesignTime.targets" }
2+
"profiles": {
3+
"CpsExtension": {
4+
"commandName": "Executable",
5+
"executablePath": "$(DevenvDir)devenv.exe",
6+
"commandLineArgs": "/rootsuffix exp",
7+
"environmentVariables": {
8+
// Environment variable that overrides where `CpsExtension.Nuget.targets` imports `CpsExtension.DesignTime.targets` from. This way you can develop without affecting the MSBuild directory for your VS install.
9+
"CpsExtensionDesignTimeTargetsPath": "$(OutputPath)BuildSystem\\CpsExtension.DesignTime.targets",
10+
11+
// When set to 1 it creates a new Output window pane called 'Project' that displays CPS diagnostics.
12+
"CPS_DiagnosticRuntime": "1"
13+
14+
// Uncomment the following line to increase the verbosity of the CPS diagnostics.
15+
// "CPS_DiagnosticRuntimeLevel": "Verbose"
16+
// Uncomment the following two lines to capture binlogs of all builds, including design-time builds.
17+
// "MSBuildDebugEngine": "1",
18+
// "MSBUILDDEBUGPATH": "c:\\binlogs"
19+
}
20+
}
821
}
9-
}
1022
}

samples/CpsExtension/CpsExtension.Vsix/source.extension.vsixmanifest

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
<Description>Example CPS extension for an existing project type.</Description>
77
</Metadata>
88
<Installation AllUsers="true">
9-
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0, 16.0)" />
9+
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0, 18.0)" >
10+
<ProductArchitecture>amd64</ProductArchitecture>
11+
</InstallationTarget>
1012
</Installation>
1113
<Dependencies>
1214
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
@@ -15,6 +17,6 @@
1517
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
1618
</Assets>
1719
<Prerequisites>
18-
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
20+
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,18.0)" DisplayName="Visual Studio core editor" />
1921
</Prerequisites>
2022
</PackageManifest>

samples/CpsExtension/README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,28 @@
22
This sample demonstrates:
33
* Extending an existing project type in CPS
44
* How to dynamically turn on or off a feature implemented in a vsix by adding and or removing a nuget package that defines a custom `ProjectCapability`
5-
* How to author vsix projects using an SDK-style project which is CPS based (keep in mind that this is not an oficially supported scenario currently)
5+
* How to author vsix projects using an SDK-style project which is CPS based (keep in mind that this is not an officially supported scenario currently)
66
* Custom rule delivered via a nuget package that provides custom properties for a xaml rule file (`XamlPropertyRule.xaml` defined in `Microsoft.VisualStudio.ProjectSystem.Sdk.Tools`)
77

88
## Instructions
9-
1. Generate the nuget package
10-
* Open a developer command prompt
11-
* Build the `Pack` target of the `CpsExtension.Nuget` project
12-
msbuild /t:Pack CpsExtension.Nuget.csproj
9+
1. Open the solution in Visual Studio
10+
2. Create the nuget package
11+
* In Visual Studio, right click on the `CpsExtension.Nuget` project and select `Pack`
1312
* This will generate a nuget package: `CpsExtension.Nuget.1.1.0.nupkg` (located in the `bin\debug` subfolder)
1413
2. Build and run the CpsExtension vsix
15-
* Open the solution in Visual Studio
16-
* Build and run the soltution (Ctrl + F5) - this will build the vsix and launch the Visual Studio experimental hive with the vsix installed
14+
* Right click on the `CpsExtension.Vsix` project and select `Set as StartUp Project`
15+
* Build and run the solution (Ctrl + F5) - this will build the vsix and launch the Visual Studio experimental hive with the vsix installed
1716
3. Create a .Net Core project and install the CpsExtension.Nuget package
1817
* In the experimental hive launched at previous step, Create a new .Net Core Console App
1918
* Right click on the project -> Manage Nuget Packages
2019
* Add the location where `CpsExtension.Nuget.1.1.0.nupkg` was generated at step 1 as a [package source](https://learn.microsoft.com/nuget/tools/package-manager-ui#package-sources)
2120
* Install the `CpsExtension.Nuget.1.1.0.nupkg` package into your project
2221
4. See the results
2322
* Once the nuget package was added to the project, you should notice a new debugger named `Custom Debugger` on the main tool bar on the start button
24-
* Note: the custom debugger is not implemented, so it will report an error if you try to run/debug the project using it
25-
* If you uninstall the nuget package from the project, the `Custom Debugger` entry will be automatically removed
23+
* Note: the custom debugger is not implemented, so it will report an error if you try to run/debug the project using it
24+
* If you uninstall the nuget package from the project, the `Custom Debugger` entry will be automatically removed
25+
* Select a .cs file in the solution explorer and you will see a custom property `Foo Property` available in the properties window
26+
* Note: Currently, you need to close and reload the solution after adding or removing the nuget package in order to see the updates in the property window (due to a known limitation in CPS)
2627

2728
## Implementation notes
2829
This sample solution can be used as a starting point for extending an existing project type in CPS.
@@ -37,7 +38,9 @@ This project contains all the optional design-time functionality. This includes
3738

3839
The project itself is an sdk-style project changed to build vsix's. This is not an officially supported scenario, but it is possible to get it to work.
3940

40-
The produced VSIX is an all-users vsix that installs the targets and xaml rules to the per-VS-instance MSBuild directory. When F5'ing the VSIX, an environment variable is set that overrides where the nuget package targets to pick up the design time targets from the bin directory. This way you can develop without affecting the MSBuild directory for your VS install.
41+
The produced VSIX is an all-users vsix that installs the targets and xaml rules to the per-VS-instance MSBuild directory.
42+
43+
When F5'ing the VSIX, the `CpsExtensionDesignTimeTargetsPath` environment variable is set (specified in `launchSettings.json` under the `Properties folder`) that overrides where the targets file from the nuget package (`CpsExtension.Nuget.targets`) picks up the design time targets (`CpsExtension.DesignTime.targets`) from the bin directory. This way you can develop without affecting the MSBuild directory for your VS install.
4144

4245
Because this is a CPS based project, you will notice the rich set of properties available when you select a xaml rule file in the solution explorer (`BuildSystem\Rules\CustomDebugger.xaml`). That is because the `Microsoft.VisualStudio.ProjectSystem.Sdk.Tools` package delivers a custom rule `XamlPropertyRule.xaml` that defines these properties. Simply installing and uninstalling the `Microsoft.VisualStudio.ProjectSystem.Sdk` package will turn on or off this behavior.
4346

0 commit comments

Comments
 (0)