I am confused by the rapid pace and terrific work done by Sayed Hashimi and company on SlowCheetah, specifically whether or not SlowCheetah is able to transform files on Build instead of just Package and Publish.
I have SlowCheetah installed and am able to auto-generate the build configuration instances for app.config of a console application I am working with the development team to deploy. On build, a new "SlowCheetah" directory is created under the $(ProjectDir)\obj\x86\$(BuildConfig) directory. The obj\x86\STAGE\SlowCheetah directory, for instance, contains an app.config file with the transform completed as indicated when right clicking the STAGE transform and selecting "View Transforms".
The \bin\$(BuildConfig) directory, however, contains the untransformed app.config file as well as all of the templates for each of the $(BuildConfig) transformations - instead of replacing the app.config file in the bin\x86\STAGE directory with the one from SlowCheetah.
The build completes without error.
Is this the expected action, or is something still not working correctly?
#sayed-ibrahim-hashimi Each $(Configuration) has a transform. The transforms displays properly when viewing in Visual Studio, and is properly transformed in the \slowcheetah directory under the \obj directory tree. Examples of transforms are:
<?xml version="1.0" encoding="utf-8" ?>
<!-- For more information on using transformations see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform
<connectionStrings>
<add name="Portal" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw1;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
<add name="DictionaryDatabase" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw2;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
<add name="LoggingDatabase" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw3;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
The problem may be related to the Nuget/solution configuration. The project I am working with is one part of a very large solution. I had a difficult time getting SlowCheetah installed and working - at one point finding Nuget said SlowCheetah was installed but the solution package directory did not contain SlowCheetah.
I setup a workaround in TeamCity to pickup the transformed app.config file from the \obj directory, but would really like to resolve the problem so I can rollout SC to the full development group. Is there a verbose log we can look at that might point out the details?
I faced with the same problem.
Local compilation in VS works great,
but on build Agent (TeamCity) the transformation magic not happend!
The solution I found relating to the location of the xml element in the proj file
<PropertyGroup Label="SlowCheetah">
<SlowCheetahToolsPath>$([System.IO.Path]::GetFullPath( $(MSBuildProjectDirectory)\..\packages\SlowCheetah.2.5.10.3\tools\))</SlowCheetahToolsPath>
<SlowCheetah_EnableImportFromNuGet Condition=" '$(SC_EnableImportFromNuGet)'=='' ">true</SlowCheetah_EnableImportFromNuGet>
<SlowCheetah_NuGetImportPath Condition=" '$(SlowCheetah_NuGetImportPath)'=='' ">$([System.IO.Path]::GetFullPath( $(MSBuildProjectDirectory)\Properties\SlowCheetah\SlowCheetah.Transforms.targets ))</SlowCheetah_NuGetImportPath>
<SlowCheetahTargets Condition=" '$(SlowCheetah_EnableImportFromNuGet)'=='true' and Exists('$(SlowCheetah_NuGetImportPath)') ">$(SlowCheetah_NuGetImportPath)</SlowCheetahTargets>
</PropertyGroup>
I have noticed is that when the PropertyGroup is above all ItemGroup`s ellements
MsBuild.exe at last did the Transformation
Look for duplicate SlowCheetahTargets section - I had an older version and a newer version and the older one was pointing to a location that no longer existed in the nuget packages directory.
Delete the whole property group for the older / duplicated SlowCheetahTargets section and that should fix it.
Related
I Create a NuGet package and install into another project. but don't copy a file into the location project. only my file reference to NuGet package and I change the code, The package also changes! I want to copy the package to the target project.
<?xml version="1.0"?>
<package>
<metadata minClientVersion="3.3.0">
<id>MyPackage</id>
<version>1.0.0</version>
<authors>Meysam</authors>
<owners>Meysam</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2018</copyright>
<tags>Tag1 Tag2</tags>
<contentFiles>
<files include="cs/*.*/**" buildAction="Compile" />
</contentFiles>
</metadata>
<files>
<file src="ConsoleApp1\CustomClass\CustomClass.cs" target="contentFiles\cs\any\CustomClass" />
</files>
</package>
Copying files into the project that uses a nuget package is only supported when using packages.config, which isn't supported by SDK-style projects, which are required for .NET Core projects. As your screenshots show, contentFiles in PackageReferences projects are included at build time. The little arrow icon in the bottom right corner of the C# and folder icons you pointed to in your screenshot are visual indicators that the file and folder are different to the other files and folders in your project. In fact, that little icon overlay is similar to what Windows adds for shortcuts, so if you understand a shortcut is a file that "points to" another file, it should make sense that these are shortcuts to files outside your project, but are included as part of your project.
Anyway, it's working as designed.
You'll need to find another way to do whatever you want, but you didn't describe why you're trying to include a file in the project that references your package, so I can't give direct advice. My best advice, if you are experienced with ASP.NET and ASP.NET Core is think about how ASP.NET used to read a lot of settings directly from web.config, but ASP.NET Core instead uses a builder pattern, so that users are not forced to store settings in web.config and can store settings anywhere they want. If what you're doing is similar, your package users will have a better experience if you provide them with a configuration builder that they can override, rather than having a file in their project that they must edit and gets overwritten every time they upgrade to a new version of your package.
Cannot copy folder with nuget package in .net core
Yes, just like zivkan said:
Copying files into the project that uses a nuget package is only
supported when using packages.config
But, we could use a workaround to resolve this issue. We could add a copy task in the xx.targets file, and set this file in the \build folder in the .nuspec file.
The content of mypackage.targets file:
<Target Name="CopyFile" AfterTargets="AfterBuild">
<ItemGroup>
<CopyFiles Include="$(NuGetPackageRoot)\mypackage\4.0.0\cs\*.*\**" />
</ItemGroup>
<Copy
SourceFiles="#(CopyFiles)"
DestinationFolder="$(ProjectDir)"
/>
</Target>
And the .nuspec file:
<file src="xxx\xxx\mypackage.targets" target="build" />
Hope this helps.
I'm working with Visual Studio 2017. I've inherited a web project and am trying to introduce build configurations for the config transforms. What I am finding odd is that no matter what build configuration I select, the project always compiles to the bin\ directory, no subdirectory for the build selected.
What's further strange is that I created two new web projects to discover where the problem might be and got different results. One was a .Net Core web project, which did create the Debug and Release directories when compiled under those build configurations. The other, like the inherited project, was a .Net Framework web project, and it also would only compile to the bin\ directory.
Does anyone have any idea what is going on?
While I did not discover why the configuration name was not being automatically appended to the output path during the build, nor why transforms were not being applied to the config files, I fixed the problem by hacking the project file.
For each PropertyGroup node that identified the settings to use for the build, I changed the OutputPath value from bin\ to bin\$(Configuration).
Then, I insert the following into the Project node to get the transforms to work:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="Exists('Web.$(Configuration).config')">
<TransformXml Source="Web.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="Web.$(Configuration).config" />
<ItemGroup>
<AppConfigWithTargetPath Remove="Web.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
I've been wrestling with NuGet for a few days now and I'm turning to StackOverflow in frustration - hopefully someone here can be kind enough to point me in the right direction.
I've used NuGet several times for simple one-man pet projects, but this is the first time I've used it for something I really care about and want to have fully continuous builds, etc. I'm trying to create a simple NAnt build script to get the source for Git, ensure the external dependencies have been brought down, compile, and run tests - vanilla CI.
I originally went down the path of trying to get solution restore working, but it just didn't work or I didn't how it worked. Visual Studio is not on the build server and will not be installed there - that is not an option. As an aside, I couldn't get solution restore to work just with two developers (one trying to bring down the source fresh and build cleanly). I'm assuming it's because "allow solution restore" must be turned on everywhere (and is not by default). I punted on that approach before I got to the bottom of it - frankly, having my package manager so tightly coupled to the IDE makes me uncomfortable and was hoping I could do it another way. The package managers I'm used to using are simple command line tools - the CI build script invokes it on build, and developers do it on demand. I've spent the last two hours trying to get this working with the last 30 minutes in the NuGet source code. I feel like I'm fighting the tool and need to reboot.
Does anyone have any examples of the best to use NuGet in a multi-developer + CI scenario? This is what I want:
Any and all developers can get the source and run the tests in 3 or
less clicks (preferably 1). If the binaries are not present locally, that will be JIT fetched. If they are there, they will be updated if necessary, etc. This would ideally not even require NuGet to be installed (i.e. NuGet.exe would need to be in my repo).
Do #1 via a CI server like Jenkins, TeamCity, etc. (preferably using the same script)
If its not overly fighting the tool, I would like to have all this disconnected from Visual Studio with a single packages.config file and all binaries dumped into a single Lib folder in the root of the repo.
Any pointers would be very much appreciated.
Below, how I think you can achieve each your requisites:
You need to "Enable NuGet Package Restore" in your solution: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
As #alexander-doroshenko mentioned for TeamCity you can use Nuget Installer: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer, but if you want a script to run in Jenkins, try this (works at TC too, as a command line step) for each project:
nuget.exe install "[Project folder]/packages.config" -source "" -solutionDir "" -OutputDirectory "packages"
This requisite will be done by item 1 and 2.
TeamCity has a build step for that, called "NuGet Installer", it fetch required packages from .sln file and download the locally. It does not require Visual Studio to run.
Read more about it here: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer
There are several different solutions for integrating NuGet into your build process depending on how much integration you require. In our case we wanted to use NuGet as package manager and allow developers to build their solutions even if they haven't got NuGet installed on their machine. For that to work we enabled package restore which adds the NuGet binaries to your solution folder and updates the project files. Note that NuGet doesn't always do the update of the project files correctly. In our case we found that some project files got updated but others didn't. To verify that the project was updated you will need to open the project file as XML file. To achieve this load the solution and right click the project in question and select unload project. Then right click the project again and select edit [PROJECT_NAME]. In the project file you should see
A RestorePackages property in the first propertygroup. This property should have the value true
An import statement at the very end of the project file. This import statement should point to the 'NuGet.targets file that accompanies the NuGet binary.
Below is an example of one of our project files (heavily edited)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)\..</SolutionDir>
<ProjectGuid>{8B467882-7574-41B2-B3A8-2F34DA84BE82}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MyCompany.MyNamespace</RootNamespace>
<AssemblyName>MyCompany.MyNamespace</AssemblyName>
<!-- Allow NuGet to restore the packages if they are missing -->
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<Import Project="$(SolutionDir)\BaseConfiguration.targets" />
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="MyClass.cs" />
<!--
.... MANY MORE FILES HERE
-->
</ItemGroup>
<!-- Import the Nuget.targets file which integrates NuGet in the build process -->
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
The next step you'll need to take is to provide a solution level NuGet configuration file in which you'll indicate where the packages need to be 'installed' and what the URL of the package repository is. In our case the solution directory structure looks like:
(D) root
(D) build
(D) packages
(D) source
(D) .nuget
NuGet.config
NuGet.exe
NuGet.targets
(D) MyCoolProject
MyCoolProject.csproj
MyCoolProject.sln
(D) templates
NuGet.Config
Where (D) indicates a directory.
The NuGet.config file contains the following configuration settings.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
</packageRestore>
<config>
<add key="repositorypath" value="packages" />
</config>
<packageSources>
<add key="OurPackageServer" value="PACKAGE_SERVER_ADDRESS" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
This configuration file indicates that package restore is enabled, that the repository path (where the packages are placed) is the packages directory and which package sources are active.
By placing a NuGet.config file in the root directory we can use the hierarchical configuration option with NuGet. This allows the individual solutions to override computer specific configurations. The other benefit is that this way we don't need to have NuGet installed on the build server (because the executable and the configurations are in the repository).
With this setup developers can build the solution from Visual Studio. The build should work fine on developers machines even if they don't have NuGet installed. Note however that they won't be able to add packages to a project without having NuGet installed in visual studio.
On the build server you can simply use MsBuild to build the solution which will automatically download the packages from your package repository. Visual Studio is not required to be installed on the build machine for that (just the .NET framework of your choice).
In Visual Studio 2010, you know how you can change your configuration (debug, release, etc), right-click a project in the solution explorer, click publish, and have all the important web app project files for the selected configuration copied to a target folder along with an xdt-transformed web.config? Well, I am looking for the MSBUILD equivalent of exactly that.
My challenge to you: Provide the ONE LINE that I need to execute at my command prompt in order to accomplish this. No third party programs. No tutorial videos. Just a single, straight-up command that I can literally copy from your response, paste into a command window, modify as necessary to support my directory structure, and then hit enter.
If not, then perhaps someone could provide a link to a complete MSBUILD reference showing every command, switch, and value I can use at the command line.
Put the below to ProjectPublish.MSBuild.xml file (change PropertyGroup as needed):
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Publish">
<PropertyGroup>
<ProjectFile>Path\To\Web.csproj</ProjectFile>
<PublishDir>Path\For\Publish\Output</PublishDir>
<TempDir>Path\To\Temp\Folder</TempDir>
<BuildConfig>Release|Debug</BuildConfig>
</PropertyGroup>
<Target Name="Publish">
<MSBuild Projects="$(ProjectFile)"
Properties="Configuration=$(BuildConfig);WebProjectOutputDir=$(PublishDir);OutDir=$(TempDir)\;BuildingProject=true"
Targets="ResolveReferences;_CopyWebApplication" />
</Target>
</Project>
Calling this from command line (or .bat file) should do the trick:
%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ProjectPublish.MSBuild.xml
I found the solution I was looking for after all these months here
In case the above link goes bad, here's the skinny of what it says:
Unload then edit your project file. Look for the line where it's importing Microsoft.WebApplication.targets. Will look like:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
Beneath that line, paste in this XML:
<Target Name="PublishToFileSystem" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''" Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))" Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)" DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
</Target>
Now, run this in a command prompt within the same folder as your project file:
msbuild TestWebApp.csproj "/p:Platform=AnyCPU;Configuration=Debug;PublishDestination=C:\pub" /t:PublishToFileSystem
Remember to specify the path to MSBUILD in the command or add the path to your global path environmental variable (which is what I did). On my machine, it was here:
C:\Windows\Microsoft.NET\Framework\v4.0.30319
To test this, I put a config transform in my Web.Release.config to add an AppSetting key (if you do this, make sure the AppSettings node is present in your base config file or you will get an error). When I used the above command to build the debug configuration, the key was not present in the published config file as expected. However, when I used the release config, the key was successfully added to the file.
I really wish Microsoft hadn't obfuscated the heck out of this. At any rate, this is the simplest solution I have found anywhere on the internet. I hope it helps the rest of you.
Folks,
In a nutshell, I want to replicate this dialog:
It's a Visual Studio 2010 ASP.Net MVC project. If I execute this command, I get all the files I want, including the transformed web.configs in the "C:\ToDeploy" directory.
I want to replicate this on the command line so I can use it for a QA environment build.
I've seen various articles on how to do this on the command line for Remote Deploys, but I just want to do it for File System deploys.
I know I could replicate this functionality using nAnt tasks or rake scripts, but I want to do it using this mechanism so I'm not repeating myself.
I've investigated this some more, and I've found these links, but none of them solve it cleanly:
VS 2008 version, but no Web.Config transforms
Creates package, but doesn't deploy it..do I need to use MSDeploy on this package?
Deploys package after creating it above...does the UI really do this 2 step tango?
Thanks in advance!
Ok, finally figured this out.
The command line you need is:
msbuild path/to/your/webdirectory/YourWeb.csproj /p:Configuration=Debug;DeployOnBuild=True;PackageAsSingleFile=False
You can change where the project outputs to by adding a property of outdir=c:\wherever\ in the /p: section.
This will create the output at:
path/to/your/webdirectory/obj/Debug/Package/PackageTmp/
You can then copy those files from the above directory using whatever method you'd like.
I've got this all working as a ruby rake task using Albacore. I am trying to get it all done so I can actually put it as a contribution to the project. But if anyone wants the code before that, let me know.
Another wrinkle I found was that it was putting in Tokenized Parameters into the Web.config. If you don't need that feature, make sure you add:
/p:AutoParameterizationWebConfigConnectionStrings=false
I thought I'd post a another solution that I found, I've updated this solution to include a log file.
This is similar to Publish a Web Application from the Command Line, but just cleaned up and added log file. also check out original source http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Create an MSBuild_publish_site.bat (name it whatever) in the root of your web application project
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
set destPath=C:\Publish\MyWebBasedApp\
:: clear existing publish folder
RD /S /Q "%destPath%"
call %msBuildDir%\msbuild.exe MyWebBasedApp.csproj "/p:Configuration=Debug;PublishDestination=%destPath%;AutoParameterizationWebConfigConnectionStrings=False" /t:PublishToFileSystem /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_Publish_LOG.log
set msBuildDir=
set destPath=
Update your Web Application project file MyWebBasedApp.csproj by adding the following xml under the <Import Project= tag
<Target Name="PublishToFileSystem" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''" Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))" Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)" DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
</Target>
this works better for me than other solutions.
Check out the following for more info:
1) http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
2) Publish a Web Application from the Command Line
3) Build Visual Studio project through the command line
My solution for CCNET with the Web.config transformation:
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>E:\VersionesCC\Trunk_4\SBatz\Gertakariak_Orokorrak\GertakariakMS\Web</workingDirectory>
<projectFile>GertakariakMSWeb2.vbproj</projectFile>
<targets>Build</targets>
<timeout>600</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger>
<buildArgs>
/noconsolelogger /p:Configuration=Release /v:diag
/p:DeployOnBuild=true
/p:AutoParameterizationWebConfigConnectionStrings=false
/p:DeployTarget=Package
/p:_PackageTempDir=E:\Aplicaciones\GertakariakMS2\Web
</buildArgs>
</msbuild>
</tasks>
On VS2012 and above, you can refer to existing publish profiles on your project with msbuild 12.0, this would be equivalent to right-click and publish... selecting a publish profile ("MyProfile" on this example):
msbuild C:\myproject\myproject.csproj "/P:DeployOnBuild=True;PublishProfile=MyProfile"
I've got a solution for Visual Studio 2012: https://stackoverflow.com/a/15387814/2164198
However, it works with no Visual Studio installed at all! (see UPDATE).
I didn't checked yet whether one can get all needed stuff from Visual Studio Express 2012 for Web installation.
A complete msbuild file with inspiration from CubanX
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Publish">
<RemoveDir Directories="..\build\Release\Web\"
ContinueOnError="true" />
<MSBuild Projects="TheWebSite.csproj"
Targets="ResolveReferences;_CopyWebApplication"
Properties="Configuration=Release;WebProjectOutputDir=..\build\Release\Web;OutDir=..\build\Release\Web\bin\"
/>
</Target>
<Target
Name="Build"
DependsOnTargets="Publish;">
</Target>
</Project>
This places the published website in the Web..\build\Release folder