I'm a huge fan of the addition of web.config transformations in Visual Studio 2010. See also Scott Hanselman's recent talk at MIX2011.
What sucks is that this functionality (appears at least) to only be available to web projects.
In our solution we have several Windows Services that connect to a different database dependant on the environment they are deployed under.
Has anyone come up with a nice, tidy way of achieving similar 'app.config transformation' functionality?
Note: We are using TFS 2010 to build our solutions in a Continuous Integration manner.
I realize you already have an answer, but I stumbled across SlowCheetah this morning which is the best implementation I've seen to date. There is also a blog post on getting this running from a CI server.
You can use the XML transformation functionality with any XML file - we do this all the time. It's available via an MSBuild task.
Try adding the following to your build script:
<UsingTask TaskName="TransformXml"
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>
<TransformXml Source="Path\To\Your\Xml.config"
Transform="Path\To\Your\Xml.$(Configuration).config"
Destination="Path\To\Your\Output.config" />
I wrote nice extension to automate app.config transformation like the one built in Web Application Project
Configuration Transform
Using Luke Bennett's answer to set me off on the right track. I found this to be the answer for us.
FTA (see link for code snippets):
Add a new property ProjectConfigFileName that points to your App.Config file
Add a version of App.Config for each configuration, i.e., App.Debug.config To have them nested under App.Config, edit your csproj file,
Import Microsoft.Web.Publishing.targets into your csproj file right after the Microsoft.CSharp.targets import.
Call the TransformXml task in your AfterBuild target. Note, the BeforeBuild and AfterBuild targets are commented out by default.
If you have multiple client assemblies and don't want to duplicate the same configuration data, I created Profigurator. It'll take a JSON file as input and apply the settings to an app.config or web.config.
It's a little rough as I write this, but I am currently using it on a production system for deploys and it works great.
Related
I am a Visual Studio noob. My background is more Unix-related and mostly used to building things via scons or make. I don't even have much Eclipse experience.
Anyway, I am frustrated how it seems very difficult to move files between projects in VS. (I am running Visual Studio 2013). For example, suppose I have a ProjectXRel (release) and I want a ProjectXDev (development). I want them both to be runnable, and the dev version might have just a few editing changes that differ it from the rel version.
The intuitive thought is to just copy the files from ProjectXRel to create ProjectXDev, but VS seems to fight me on that (it wants to rename all the namespaces to the title of the project).
Also, some of the files, like .cs files derived from .dbml via OR designer, seem uncopyable, and rely on one replicating the process of using the utility to having valid files. I'm used to a project being defined by its files, but that's not really the case in VS. Instead it seems defined by process steps used to create and organize the files.
Also, do serious developers just use command line calls and powershell? That's seems harder, but at least you know what the %#$$# is going on.....
So, the basic question is, how does one replicate an existing project to produce a similar one for development purposes? (I know source control such as git could help with that, but that's not an option for this situation.)
Thanks!
You should be using the same project for both Development and Release.
The things that are different between Development and Release should be stored in a config file (web.config or app.config, depending on what type of project).
You should then be using Configuration Transformations to transform that .config file into Development or Release.
In Visual Studio, right click on the project and click Add New Item, select "Application Configuration File".
In this file you can put connection strings or key/value pair settings in the AppSettings element (MSDN Link).
Once you have your basic settings defined, you can then right click on the config file and click Add Transformation. This will add transformations for each of the Project Configurations you have. (by default Debug and Release).
It will look like this:
Now you can build deployment packages.
Or install Slowchetah and then when you press F5 to debug it will run the selected project configuration with the configuration transformation applied.
Maybe I just can't figure out the right keywords to get an answer out of Google, but here goes.
Say I have a Project I'm working on named "Project." For it's first version, I have it stored in the folder "Project_Version1", and have the name of it's solution, project, build exe, etc as "Project_Version1".
Now I want to make the next version of the Project, and call it "Project_Version2". To do this currently, I copy the original folder, and rename it to "Project_Version2", and I want to rename all of the other internal stuff to that as well. Currently, I have to do that with a combination of changing the names in windows explorer, and some of the various properties pages in my solution.
There has to be a better way to do this. How does somebody make a second version of their project, and store it's files separately from the first version? Is there a way to also rename appropriate files that contain version numbers?
Indeed, there is a better way to do this, it is called version control.
If you check your source into TFS (or git or any other SCM software) all versions will be tracked over time.
If you then need to maintain multiple versions simultaneously (e.g. for a customer base where customers slowly migrate to the bleeding edge and patches are required to fix critical issues in older, supported versions) you can keep these versions as branches and selectively merge changes.
If you do decide source control is a good fit for managing your versions (It brings a lot of other benefits as well), consider reading some posts such as this git tutorial or why use version control.
If you REALLY can't use source control, for some reason, I suggest trying to reference as much as you can using language constructs which can be easily changed (e.g. with C# and a reasonable IDE, a quick refactor, or with other languages some rigorous de-duplication of version-specific data).
Ideally you would have just one definition of the version for your code along with a version definition in the project files (which could be set as a build variable to change quickly).
In this case you would copy the project, change the code version and the version variable for the project and, assuming good use of relative paths etc. (no hardcoded versions!), a quick rename of a couple of variables should get you going.
Ideally, the bulk of of the file-names would not reference the version. The only thing referencing the version should probably be the containing directory, the project/solution files and a few isolated references in your code.
You can do some pretty neat tricks with MSBuild. Let's say, for instance, that this is your project.
Program.cs:
namespace MyCustomBuild
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("Hello World");
}
}
}
Create your MSBuild file as shown. build.msbuild:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MajorVersion>1</MajorVersion>
<MinorVersion>0</MinorVersion>
</PropertyGroup>
<Target Name="Default">
<CombinePath BasePath="$(MSBuildProjectDirectory)"
Paths="Program.$(MajorVersion).$(MinorVersion)">
<Output TaskParameter="CombinedPaths" PropertyName="OutputDir"/>
</CombinePath>
<MakeDir Directories="$(OutputDir)"/>
<Csc Sources="program.cs"
OutputAssembly="$(OutputDir)\Program.$(MajorVersion).$(MinorVersion).exe"/>
</Target>
</Project>
After running msbuild build.msbuild, this is the result:
Ways to make what I posted even better:
Use the MSBuild Extension Pack AssemblyInfo. This will allow you to change the version info if you have it defined inside an AssemblyInfo.cs file. Or you can look into the GenerateApplicationManifest Task, which can set assembly versions, but as of right now the file version of the executable will always be 1.0.0.0
Implement some sort of autoincrement system like this one
You can copy all your source files into the versioned directory using the Copy Task
It's a lot to take in, especially if you aren't familiar with MSBuild, but it's a powerful program that allows customization that Visual Studio can't even imagine! Note that a solution file (.sln) is a MSBuild file, even though it's not xml.
Hopefully this is what you are looking for. I do also recommend that you use an official version control, as others have mentioned, but you seemed to have a specific task you wanted automated, which is MSBuild's forte.
Ideally, versioning your project should be done within a source control system since Visual Studio in and of itself is just an IDE.
In the situation of not using a source control system, unfortunately I'm not aware of a better solution than what you are doing currently.
When I debug a web application, the web.config transforms are not applied.
I simply find that the configuration in web.config is not applying the transform for the configuration I'm currently using.
Yet if I build a deployment package then I find that the web.config does have the current transforms applied.
Are transforms not applied when debugging? I'm starting to wonder if this is the case, but I have coworkers insisting that it works for them.
Web.config transforms are only applied when publishing or deploying.
Jared Harding provided a link where a member of the .NET Team answered this question in the response here: VS2010 Clean Web.configs - not updating
The link he provided for ease of reference is: http://forums.asp.net/p/1532038/3711423.aspx
You can start a transform by introducing a "AfterBuild" entry in your project file as described here.
Downside: you have 2 web.config files...
http://kfigy.blogspot.ch/2010/03/making-visual-studio-2010-webconfig.html
I have a windows service that will need to have the same kind of transformations that the web.configs would use, but VS 2010 doesn't seem to support that. I've tried manually adding the App.Release.Config files, and then using msbuil [PROJ] /T:TransformWebConfig /p:Configuration=Release but no transformation is performed. I got a TransformWebConfig folder createed in my obj subdirectory, but that's it.
Is this thing hardcoded to only work with web.configs?
Yes, the TransformWebConfig task is designed to work on web.config
(File: $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets Line: 199)
But you could make it work by :
Setting the Build Action of your App.config file to Content
Setting the value of ProjectConfigFileName to App.config :
msbuild $ProjectFile$ /t:TransformWebConfig /p:ProjectConfigFileName=App.config;Configuration=Release
I was having the same issue and came across an article that details how to accomplish transforming app.config files:
http://vishaljoshi.blogspot.com/2010/05/applying-xdt-magic-to-appconfig.html
I walked through the steps and was successfully able to transform my app.config file.
You can now use a plugin called SlowCheetah to transform not only app.configs but any xml files using the same transformation engine
I have written a code generator using CodeDom and it generates a number of classes from stored procedures. I'd like to add its execution as a build step and then add all of its classes to the solution programatically at build-time.
How do I do this?
Use Custom Build Providers
Subsonic also uses Build Providers to generate its DAL and code. Please check subsonic configuration for custom build provider. It is open source you can check its implementation also.
<configuration>
<system.web>
<compilation>
<buildProviders>
<add extension=".abp" type="SubSonic.BuildProvider, SubSonic"/>
</buildProviders>
</compilation>
</system.web>
</configuration>
It uses .abp extension file to initiate its build provider.
Edit : Yes, Custom build providers are super feature of ASP.Net. But
traditional winform or other
developers can use MSBuild custom
tasks to get the same effect. Dino
Esposito has provided a great article
for the same. You can check it
here.
I don't know how this would work, but here goes:
If your CodeDOM code is generated in a separate project, generate the classes and then add the file names to the .csproj file (it's just XML) of a library. Have it ordered to build first as well. Then have the library's pre-build event run the code generating app, then it will compile. When you click on VS the next time, it will ask you to reload because the project file has changed and your new classes should show up.
It seems a little hacky, but with a little scripting it could be automated.