msbuild TransformWebConfig task - doesn't work for App.configs? - visual-studio-2010

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

Related

MSBuild.ExtensionPack.tasks inheritance of variables from MSBuild main project file

Case:
When I build from MSBuild (with VS Build Tools 2017) I don't get any value for $(ExtensionTasksPath) variable
from main msbuild file, when I build with integrated VS MSBuild value is passed from main file to MSBuild.ExtensionPack.tasks, is that expected behavior and why does it happen? I don't use any properties for the sake of testing that particular case.
Is that expected behavior and why does it happen?
I think it's not we expect.As I test on a VM, the msbuild from VS Build Tools2017 get the same value as what we can get in msbuild from VS IDE.
For the reason of this behavior I have some suggestions to help trouble
shooting:
1.First of all, make sure both two scenarios builds successfully.
2.As you mentioned above, you runs them in separate VMs, make sure the two file under test are the same and entire solution folder.(The package folder under solution directory makes sense)
3.Check in the .xxproj file, check if exists <Import Project="..\packages\MSBuild.Extension.Pack.1.9.1\build\net40\MSBuild.Extension.Pack.targets" ...>
I've found the $(ExtensionTasksPath) property is defined in MSBuild.Extension.Pack.targets file, and this file is imported into .xxproj file by <Import> tag.
Have a look at pics below from my sample project which install MSBuild.Extension.Pack by nuget:
After my project install the extension bu nuget, there is an Import sentence in csproj file, open it we can find:
The value of $(ExtensionTasksPath) in defined here. So i guess you may have sth missing with the targets file or the import sentense or have sth corrupt this property.
In summary:
1.keep the entire solution folder could be the best suggestion.
2.And if it not works, add a script below to your .xxproj file can work:
<PropertyGroup>
<ExtensionTasksPath> Absolute path of your MSBuild.ExtensionPack.dll</ExtensionTasksPath>
</PropertyGroup>
It will overwrite values from tag and no matter where you put the assembly, just add the absolute path can work.
It my answer is helpful, please give me a feedback. And any update please feel free to contact me.

Using the solution's configuration name as a test condition for MSBuild Target

I finally realized why my BeforeBuild Target is no longer executing as expected -- it's so silly, it's because the project's configuration names had changed. But what I really want to do is test for the solution's configuration name, not the project's.
I know that the project's configuration name is stored in $(Configuration). Is there one for the solution's configuration name? Or is this simply not possible because (presumably) the solution names are only known to the configuration manager? If so, can anyone recommend a good method for managing configurations? I'd hate to have to add duplicate project configuration names everywhere...
UPDATE: after searching and reading some docs, I haven't been able to find any proof that MSBuild is aware of the solution's configuration name when its individual project files are compiled. I went ahead and build the solution from the command line, passing /v:diag, and dumped the output to a file. I searched through the file to find any signs of it knowing that the solution's configuration name is "Deployment", but the only occurences of that string appear when the BeforeBuild condition is checked.
See my other answer. I was able to create a VS extension to get the solution configuration name as a build macro ($(variable) notation).
The only solution I've come up with so far is to create my own environment variable on the TeamCity server, and have MSBuild check for its presence in the BeforeBuild target.
EDIT: I couldn't use my own environment variable because it wasn't getting passed to the build runner for some reason. But when I used /v:n in the TeamCity MSBuild settings, I noticed that there is $(COMPUTERNAME), which is exactly what I wanted anyway. I ended up trying this and it totally did the trick.
There is property SolutionConfigurationContents witch is created by Msbulid during soluton file processing it contains solution configuration in it. When building from VS it will contains project (not solution) configuration.

When do Web.Config transformations in VS2010 fire?

Our code uses different settings for development and production environments so we were looking at using VS2010's web.config transform capabilities. After hours of trial and error, nothing has worked. We found a Web.config transformation tester and found that what we had been trying was supposed to work (according to this tool.)
We tried testing the transformations using Build, not Publish. Does it only run on Publish or could something else be wrong?
Yes, it only runs on Publish. To test, publish to a local dir. You'll want to publish your application with the correct target environment set.
You can also integrates web config transformations with MS Build.
It seems you don't have to be in Publish mode to generate a transformed Web.config file. There's just a bit more work involved.
Open the Visual Studio Command Prompt and navigate to your working project directory that contains your .csproj file. Enter the following command:
MSBuild project.csproj /t:TransformWebConfig /p:Configuration=Debug
The example above would run the Debug transformation during the build of project.csproj. This will output a Web.config file into the obj\Debug\TransformWebConfig\transformed\ directory, where Debug is whatever Configuration you set in the command above.
Copy this file to replace your root Web.config file, and you're done. You could write a batch script to run both of those items automatically, but for larger projects with many configurations it could become unwieldy.
You might be able to add those command line arguments to the build process inside of Visual Studio, but I'm not sure how - as far as I know for this method to work you would have to build from the command line instead of inside Visual Studio. You can still use Clean inside of Visual Studio to clean out the obj folder but it will only clean the solution configuration mode selected in the IDE. Clean will not revert your edited web.config file, so you may want to back it up before proceeding if you need to.
(Command line arguments found from this MSDN article.)
You don't need run Publish/Build Package in order to test Web.config transformation. There is a cool trick to quickly know the transformation result here. Scroll down until you see a comment about creating TransformConfig project. It works like a charm, note that you can safely ignore 7th step (frankly I don't know how to do that step properly but fortunately we don't need it :)).

app.config Transformations

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.

Run a Visual Studio custom tool at build time

I have a script that will convert a text file into a resource file, so that I can have multiple language support by having text files for different languages converted into different resources. Once I run the script to get the resx file, I then have to run a custom build tool (as described here:Link to Code Project) in order to create the Designer.cs files to use the new files.
In keeping with the philosophy that I should be able to build the entire project with a single button click, how can I remove the step where I have to explicitly call the custom build tool in order to make the codebehind files?
I've tried automatically deleting the Designer.cs files as a pre-build step, since I would think that the custom build tool would automatically run if there were no Designer.cs files, but no dice.
So, I want my build script in Visual Studio/msbuild to do:
1) convert text to resx (done)
2) move resx files to appropriate directory (done)
3) create designer.cs files using a custom build tool (not done)
It's that last step...
Unfortunately I don't think there's an easy way of doing this. Custom Build Tools only run from within VS.NET - they don't run when you build your project using MSBuild from the command line.
In general, if you have the choice of writing a build tool as a Customer Build Tool or an MSBuild Task then choose the MSBuild Task every time as these Tasks will run in VS.NET and from the command line.
The designer.cs files for resources are there to support your coding. They give you the strongly typed access into the resource file. So, as long as you create your culture invariant resources in VS.NET (and let it create the .designer.cs files) then adding additional language support later (additional .resx files) should work fine.
If, however, your text files are your primary resource files, and you're adding new resource strings into these text files first, then you'll need to find another way of generating .cs files that allow you to code against those resources. If you HAD to, generating the .designer.cs file yourself (or somethign similar) wouldn't be that difficult. Using CodeDom or T4 you could create the helper class, using an existing .designer.cs file as a template.
There is a way to generate the *.Designer.cs for *.resx as part of the build process. There is a built-in MSBuild task GenerateResource, which basically a wrapper around the SDK tool resgen.exe. Here you can find an example how to use it.
Another thing you would find useful, if the generated *.Designer.cs version is not correct, basically, GenerateResource task is not calling the desired version of resgen.exe, setting property SdkToolsPath might help you.
Have you tried adding a Exec step in Before/AfterBuild step in your csproj? You have to manually edit the file for this, but that should solve your problem.
I'm not fully clear on if you want this done before or after the build. If you need it done sometime after Pass1/Pass2, you can hook into the targets directly. Try looking into Microsoft.Build.Common.Targets to get a feel for how to do this.

Resources