Skip to content

Commit

Permalink
Updating CpsExtension sample to Dev 17, extending existing rule, fixes (
Browse files Browse the repository at this point in the history
#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
  • Loading branch information
adrianvmsft authored Apr 24, 2024
1 parent c1bc8c7 commit ceb5f28
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 26 deletions.
4 changes: 4 additions & 0 deletions doc/extensibility/extending_rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ existing rule of the same name.
This is useful if you are building ontop of an existing project system and want to add
or change properties to the existing rules.

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.

Example:

```xml
Expand Down Expand Up @@ -42,6 +44,8 @@ and extending rule. In the case of collisions, the value of the extending rule i
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):

1. MSBuild `PropertyPageSchema` items
* 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.
* 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.
2. Rule _files_ added via `IAdditionalRuleDefinitionsService`
3. Rule _objects_ added via `IAdditionalRuleDefinitionsService`
4. Embedded `XAML` rules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">

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

<Import Project="$(CpsExtensionDesignTimeTargetsPath)" Condition="'$(DesignTimeBuild)' == 'true' and Exists('$(CpsExtensionDesignTimeTargetsPath)')" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<TargetFramework>net472</TargetFramework>
<IsTool>true</IsTool>
<IncludeBuildOutput>false</IncludeBuildOutput>
<Version>1.1.0</Version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)CustomDebugger.xaml">
<Context>Project</Context>
</PropertyPageSchema>

<PropertyPageSchema Include="$(CpsExtensionSchemaDirectory)Compile.BrowseObject.xaml">
<Context>BrowseObject</Context>
</PropertyPageSchema>

</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Copyright, Microsoft Corporation, All rights reserved.-->
<Rule
Name="Compile"
DisplayName="File Properties"
PageTemplate="generic"
Description="File Properties"
OverrideMode="Extend"
xmlns="http://schemas.microsoft.com/build/2009/properties">

<StringProperty Name="Foo" DisplayName="Foo Property" Category="Custom" />
</Rule>
22 changes: 18 additions & 4 deletions samples/CpsExtension/CpsExtension.Vsix/CpsExtension.Vsix.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />

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

<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Sdk" Version="15.8.243" />
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="15.8.3247" />
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.0.32112.339" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Sdk" Version="17.9.376" />
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.9.3168" />
</ItemGroup>

<ItemGroup>
Expand All @@ -37,7 +42,7 @@
<ItemGroup>
<VSIXSourceItem Include="BuildSystem\**" Exclude="**\*.cs">
<InstallRoot>MSBuild</InstallRoot>
<VSIXSubPath>Microsoft\VisualStudio\v15.0\CpsExtension\%(RelativeDir)</VSIXSubPath>
<VSIXSubPath>Microsoft\VisualStudio\v17.0\CpsExtension\%(RelativeDir)</VSIXSubPath>
<Visible>false</Visible>
</VSIXSourceItem>
</ItemGroup>
Expand All @@ -48,6 +53,15 @@
</XamlPropertyRule>
</ItemGroup>

<!--Copy the rule files to the output folder as a workaround for MSBuild issue https://github.com/dotnet/msbuild/issues/4494-->
<Target Name="CopyRules" AfterTargets="Build">
<ItemGroup>
<RulesToCopy Include="BuildSystem\Rules\**\*" />
</ItemGroup>
<Message Importance="normal" Text="Copying rules to $(OutputPath)\BuildSystem\Rules" />
<Copy SourceFiles="@(RulesToCopy)" DestinationFiles="@(RulesToCopy->'$(OutputPath)\BuildSystem\Rules\%(RecursiveDir)%(FileName)%(Extension)')" SkipUnchangedFiles="true" />
</Target>

<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="Exists('$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets')" />

Expand Down
2 changes: 1 addition & 1 deletion samples/CpsExtension/CpsExtension.Vsix/CustomDebugger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
using System;
using System.Collections.Generic;
using System.Composition;
using System.ComponentModel.Composition;
using System.Threading.Tasks;
using Microsoft.VisualStudio.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Debug;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
{
"profiles": {
"CpsExtension": {
"commandName": "Executable",
"executablePath": "$(DevenvDir)devenv.exe",
"commandLineArgs": "/rootsuffix exp",
"environmentVariables": { "CpsExtensionDesignTimeTargetsPath": "$(OutputPath)BuildSystem\\CpsExtension.DesignTime.targets" }
"profiles": {
"CpsExtension": {
"commandName": "Executable",
"executablePath": "$(DevenvDir)devenv.exe",
"commandLineArgs": "/rootsuffix exp",
"environmentVariables": {
// 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.
"CpsExtensionDesignTimeTargetsPath": "$(OutputPath)BuildSystem\\CpsExtension.DesignTime.targets",

// When set to 1 it creates a new Output window pane called 'Project' that displays CPS diagnostics.
"CPS_DiagnosticRuntime": "1"

// Uncomment the following line to increase the verbosity of the CPS diagnostics.
// "CPS_DiagnosticRuntimeLevel": "Verbose"
// Uncomment the following two lines to capture binlogs of all builds, including design-time builds.
// "MSBuildDebugEngine": "1",
// "MSBUILDDEBUGPATH": "c:\\binlogs"
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
<Description>Example CPS extension for an existing project type.</Description>
</Metadata>
<Installation AllUsers="true">
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[15.0, 16.0)" />
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0, 18.0)" >
<ProductArchitecture>amd64</ProductArchitecture>
</InstallationTarget>
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
Expand All @@ -15,6 +17,6 @@
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,18.0)" DisplayName="Visual Studio core editor" />
</Prerequisites>
</PackageManifest>
23 changes: 13 additions & 10 deletions samples/CpsExtension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,28 @@
This sample demonstrates:
* Extending an existing project type in CPS
* 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`
* 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)
* 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)
* 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`)

## Instructions
1. Generate the nuget package
* Open a developer command prompt
* Build the `Pack` target of the `CpsExtension.Nuget` project
msbuild /t:Pack CpsExtension.Nuget.csproj
1. Open the solution in Visual Studio
2. Create the nuget package
* In Visual Studio, right click on the `CpsExtension.Nuget` project and select `Pack`
* This will generate a nuget package: `CpsExtension.Nuget.1.1.0.nupkg` (located in the `bin\debug` subfolder)
2. Build and run the CpsExtension vsix
* Open the solution in Visual Studio
* Build and run the soltution (Ctrl + F5) - this will build the vsix and launch the Visual Studio experimental hive with the vsix installed
* Right click on the `CpsExtension.Vsix` project and select `Set as StartUp Project`
* Build and run the solution (Ctrl + F5) - this will build the vsix and launch the Visual Studio experimental hive with the vsix installed
3. Create a .Net Core project and install the CpsExtension.Nuget package
* In the experimental hive launched at previous step, Create a new .Net Core Console App
* Right click on the project -> Manage Nuget Packages
* 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)
* Install the `CpsExtension.Nuget.1.1.0.nupkg` package into your project
4. See the results
* 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
* Note: the custom debugger is not implemented, so it will report an error if you try to run/debug the project using it
* If you uninstall the nuget package from the project, the `Custom Debugger` entry will be automatically removed
* Note: the custom debugger is not implemented, so it will report an error if you try to run/debug the project using it
* If you uninstall the nuget package from the project, the `Custom Debugger` entry will be automatically removed
* Select a .cs file in the solution explorer and you will see a custom property `Foo Property` available in the properties window
* 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)

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

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.

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.
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, 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.

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.

Expand Down

0 comments on commit ceb5f28

Please sign in to comment.