Visual Studio for Mac.NET. T4 Template in VS2017 using FxCop.Sdk namespace does not work. Visual studio visual studio 2017 version 15.9 windows 10.0. Alberto Salinas reported Jun 25, 2019 at 07:38 AM. Show comments 5. The EnvDTE assembly is only available to T4 templates on Windows with Visual Studio since it provides access to the Visual Studio object model. In Xamarin Studio a T4 template will generate a single file. It is not possible to run a T4 template and make arbitrary changes to the project.
Several years ago I published a series of articles on how to use T4 to generate code. As part of that series I showed how you can, at build time, get Visual Studio to run environmental transforms on any project. To get this to work we relied on a custom .targets file being installed. The .targets
file was installed as part of a Visual Studio extension that also installed the T4 templates. As newer versions of Visual Studio have been released the extension has been updated through Visual Studio 2017.
- Xamarin Studio will automatically compile and execute the T4 file whenever it's saved, as long as the 'Custom tool' property is set to 'TextTemplatingFileGenerator'. This property is set automatically if you create the file with File - New File - Text Templating - T4 Template. See this blog post. There's also support for preprocessed T4.
- Process your T4 files right from Visual Studio Code. We had been missing this feature of parsing T4 template to easily generate code from VS Code. T4 template parser is a text transformation utility created by Microsoft and has been available in Visual Studio since 2008.
This process still works but as you start moving to build servers in the cloud or that don't have Visual Studio installed you cannot rely on extensions being available. This article will discuss the process of moving the transform process to a NuGet package that can be used in any build system. This is consistent with how popular packages are now injecting .targets
files into the build process as well and reduces the dependencies needed to build a solution.
Who This Isn't For
If you are using Azure or another cloud provider then please note that they generally provide a cloud-specific approach to storing per-environment settings. You may not need to use config transforms anymore. There are plusses and minuses to transforms. On the plus side you can ensure at build time that everything is transforming correctly. On the negative side you are exposing your settings to all your developers.
If you are building .NET Core applications then realize that XML-based configs are out and JSON files (options) are in. The configuration system in .NET Core allows you to have per-environment settings files that override specific settings in the base file. You don't need environmental transforms in these environments anymore.
What Is Changing
The base change that will be made is that the .targets
file that is shipped as part of the VS extension needs to move to a NuGet package. The need for a VS extension at build time has to be eliminated. The original solution has several components: item template, config transform files and .targets
file. The config transform files containing the transformation rules remain unchanged. You can continue to use them as is.
The item template needs to be adjusted to handle the move from an extension-specific .targets
file to a NuGet package. This is a minor change.
The .targets
file needs to be moved from the extension to a NuGet package. At the same time we can update the file to rely on a pre-build assembly that contains the transformation logic. This helps resolve issues with trying to get MSBuild to load an assembly from an inline task like we had in previous versions of the extension.
Creating the NuGet Package
To get started we need to create a new class library to hold the transformation task the .targets
file will call.
- Create a new class library (e.g.
P3Net.BuildExtensions.TransformConfigs
) targeting .NET 4.6.1. - Copy the
TransformXmlFiles.cs
file from the old build extension project into the new project. - Fix up the namespace name.
- Add NuGet packages for the required MSBuild packages.
- Microsoft.Build.Framework
- Microsoft.Build.Utilities.Core
- Microsoft.Web.Xdt
In the sample implementation I'm using the SDK project format to make things easier. Edit the project file or update it via the UI.
- Set the title, description and package tags appropriately.
- Set the version of the package. Note: I'm using a
directory.build.props
to share the versioning across projects. - Set the
GeneratePackageOnBuild
totrue
. - Optionally configure the package and publish information.
- Set the
NuspecFile
attribute to the path to the.nuspec
file below.
XDT Package Changes
The original version of the code used the Microsoft.Web.Publishing.Tasks.TransformXml
task from Microsoft.Web.Publishing.Tasks
. But this assembly is not shipped in NuGet so we have switched to Microsoft.Web.Xdt
. This required some changes to the TransformXmlFiles
task to use the new type. Here are the highlights, the code has the full version.
Defining the NuSpec File
The SDK project format supports generating packages without a .nuspec
file. However I was unable to get it to place the .props
and .targets
files into the correct locations so we are going to use an external file for now.
Packing the Right Files
The .props
files are put into the build
folder which will cause them to be injected into the build file. The .targets
file in the tools
folder is part of the tools that will be referenced by the build. To be found at build time the generated DLL needs to be copied to the tools
folder. Normally we would do this using a post-build event. The problem is that we're relying on the built in packaging feature of the project system and that runs before post build events. Hence when the package is created the binaries haven't been copied yet. To resolve this we need to copy the files before packing occurs.
As of Visual Studio 2017 15.9 I am unable to get the binary files to appear in the package file. The pack target determines what files to include before the build runs. Because the binaries haven't been built yet it won't recognize them as inputs to Nuspec no matter what I've tried to do. Here's some of the things I've tried.
Copy Binaries During Buld
Currently the PackDependsOn
target can be used to run a task before packaging occurs. We just need to add a target that runs before this.
However the pack target determines the files to include before the build step so it won't see these files even if they are there.
Update Package Files Item Group
The pack target uses _PackageFiles
to identify the files to include. In theory updating this item group to include the binaries should include them. But I was unable to get the item group to recognize the new files.
Use a wildcard in Nuspec
Nuspec supports wildcards so you can do something like bin***.dll
to include binary files. The problem is that the folder structure is rebuilt under the target folder. The binaries have to be at the root for the .targets
file to work so the structure would need to be flattened. Unfortunately this isn't supported in the Nuspec file outside content files.
You could also simply hard code the path to the output. For example the following would copy the files correctly.
The downside to this approach is the hard coded configuration and platform information. This is the approach I have gone with.
Use Manual Packaging
The last option is to not use the automated system at all but instead either do it via a post build event or manually.
The base change that will be made is that the .targets
file that is shipped as part of the VS extension needs to move to a NuGet package. The need for a VS extension at build time has to be eliminated. The original solution has several components: item template, config transform files and .targets
file. The config transform files containing the transformation rules remain unchanged. You can continue to use them as is.
The item template needs to be adjusted to handle the move from an extension-specific .targets
file to a NuGet package. This is a minor change.
The .targets
file needs to be moved from the extension to a NuGet package. At the same time we can update the file to rely on a pre-build assembly that contains the transformation logic. This helps resolve issues with trying to get MSBuild to load an assembly from an inline task like we had in previous versions of the extension.
Creating the NuGet Package
To get started we need to create a new class library to hold the transformation task the .targets
file will call.
- Create a new class library (e.g.
P3Net.BuildExtensions.TransformConfigs
) targeting .NET 4.6.1. - Copy the
TransformXmlFiles.cs
file from the old build extension project into the new project. - Fix up the namespace name.
- Add NuGet packages for the required MSBuild packages.
- Microsoft.Build.Framework
- Microsoft.Build.Utilities.Core
- Microsoft.Web.Xdt
In the sample implementation I'm using the SDK project format to make things easier. Edit the project file or update it via the UI.
- Set the title, description and package tags appropriately.
- Set the version of the package. Note: I'm using a
directory.build.props
to share the versioning across projects. - Set the
GeneratePackageOnBuild
totrue
. - Optionally configure the package and publish information.
- Set the
NuspecFile
attribute to the path to the.nuspec
file below.
XDT Package Changes
The original version of the code used the Microsoft.Web.Publishing.Tasks.TransformXml
task from Microsoft.Web.Publishing.Tasks
. But this assembly is not shipped in NuGet so we have switched to Microsoft.Web.Xdt
. This required some changes to the TransformXmlFiles
task to use the new type. Here are the highlights, the code has the full version.
Defining the NuSpec File
The SDK project format supports generating packages without a .nuspec
file. However I was unable to get it to place the .props
and .targets
files into the correct locations so we are going to use an external file for now.
Packing the Right Files
The .props
files are put into the build
folder which will cause them to be injected into the build file. The .targets
file in the tools
folder is part of the tools that will be referenced by the build. To be found at build time the generated DLL needs to be copied to the tools
folder. Normally we would do this using a post-build event. The problem is that we're relying on the built in packaging feature of the project system and that runs before post build events. Hence when the package is created the binaries haven't been copied yet. To resolve this we need to copy the files before packing occurs.
As of Visual Studio 2017 15.9 I am unable to get the binary files to appear in the package file. The pack target determines what files to include before the build runs. Because the binaries haven't been built yet it won't recognize them as inputs to Nuspec no matter what I've tried to do. Here's some of the things I've tried.
Copy Binaries During Buld
Currently the PackDependsOn
target can be used to run a task before packaging occurs. We just need to add a target that runs before this.
However the pack target determines the files to include before the build step so it won't see these files even if they are there.
Update Package Files Item Group
The pack target uses _PackageFiles
to identify the files to include. In theory updating this item group to include the binaries should include them. But I was unable to get the item group to recognize the new files.
Use a wildcard in Nuspec
Nuspec supports wildcards so you can do something like bin***.dll
to include binary files. The problem is that the folder structure is rebuilt under the target folder. The binaries have to be at the root for the .targets
file to work so the structure would need to be flattened. Unfortunately this isn't supported in the Nuspec file outside content files.
You could also simply hard code the path to the output. For example the following would copy the files correctly.
The downside to this approach is the hard coded configuration and platform information. This is the approach I have gone with.
Use Manual Packaging
The last option is to not use the automated system at all but instead either do it via a post build event or manually.
Updating the Targets File
With the build task complete and wrapped in a package we just need to get it called during a build. That is where the .targets
Allegorithmic substance painter 2019 3 3 download free. file comes in. In the previous version the file was copied to a location under MSBuild but it is now going to be part of the package. Artpaper: new daily wallpapers 3 0 5. Counter strike source offline.
Visual Studio For Mac T4 Template Free
- Create a new
Tools
folder in the package project. - Copy the
.targets
file into the new folder and rename toP3Net.BuildExtensions.TransformConfigs.targets
.
The .targets
file needs a couple of adjustments to play nice with the rest of the build system and use the new assembly where the custom task is defined.
We need to make sure the .targets
file gets copied to the output directory so right-click the file in Solution Explorer
and set its Build Action
to Content
.
Handling Binding Redirects
One change from the original version is around looking for the app.config
file. For newer projects using the SDK format the build system can auto-generate binding redirects. This reduces the amount of configuration that goes into the config file and helps ensure the application will use the correct versions. However this transformation occurs at build time and the modified file is stored directly in the output.
To account for this the .targets
file has been modified to use the generated config file instead of the version in source. This will ensure the transforms include any generated binding redirects.
Adding the Props File
The final step is to add a .props
file that will get added to the project file when the package is installed. The property file will import the .targets
file into the build. Create the P3Net.BuildExtensions.TransformConfigs.props
file in the package project. Then paste the following code.
Like the .targets
file it needs to be copied to the output at build time.
Updating the Item Template
The environment config item template (actually the template wizard) currently looks for an import of the targets file so that it can report a warning if a project is using the template but hasn't installed the extension yet. Instead we will look for the NuGet package. Instead of trying to handle both approaaches to package references we'll just look for the props file that the package installs.
Testing the Changes
Go ahead and build the solution. Then find the generated .nupkg
file and open it. If everything is correct then the .props
file will be under the build
folder and the .targets
file under the tools
folder. When the package is installed the .props
file will get added to the project file. Since it references the .targets
file that file will get loaded at build time which will trigger the generation of the config transforms.
Now copy the package file to your local NuGet store so you can add it to a project with a set of config transforms. We'll use a simple web app as a test.
Visual Studio For Mac Download
- Create a new ASP.NET Web Application in Visual Studio.
- Using
Package Manager
add the new package to the project. - Rebuild.
- The existing web config transforms should run during the build and, as in the original article, you should have the transformed files ready for use.
Visual Studio 2019 Support
As a final touch we will update the extension to support VS 2019. This just requires a couple of changes to the vsixmanifest
file as discussed here.
- Update the
InstallationTarget
to[15.0,17.0)]
. - Update any
Prerequisite
elements from Visual Studio to[15.0,]
. - Update the extension version information.
- Rebuild
Note: The templates require T4 Toolbox which has not been updated to VS 2019 as of yet.
Cleaning Up the Code
The build extension project (P3Net.BuildExtensions
) and VSIX (P3Net.BuildExtensions.Setup
) are no longer needed and can be removed.
The installation script and original .targets
files can be removed as they are no longer needed.
The text template VSIX (T4TemplatesSetup
) may have a dependency on the build extension project. This can be removed from the manifest editor now that it is gone.
The code is available on GitHub.
Posts
The EnvDTE assembly is only available to T4 templates on Windows with Visual Studio since it provides access to the Visual Studio object model.
In Xamarin Studio a T4 template will generate a single file. It is not possible to run a T4 template and make arbitrary changes to the project. You could probably do this with a custom T4 template host that provides access to the Xamarin Studio object model. However the T4 template could not be used for Visual Studio.
@mattward What would be the best approach to add code-gen (doesn't need to be T4) to Xamarin Studio? Picking up files that where changed, creating new .cs files for compilation to the project. E.g. using AddIns or custom T4 host, what would be the high level steps to do / APIs to use. Thanks
@DomCS - It depends on your requirements. You can look at using the built-in code generation support, such as T4, and see if that fits your requirements. If not then you will probably need a custom addin. Without knowing your requirements it is not that easy for me to suggest an approach.
A T4 file will generate a new file when the T4 file is saved. So it is a manual process. If you need something more than that, such as generating new files before every build then you will need to create an addin. The TypeScript addin is one example that generates code before the build. Another approach would possibly be to do this all with MSBuild instead of creating an addin.
- 0