Programmatically (using C#) determine current Visual Studio build configuration - msbuild

My Visual Studio 2013 C# app needs to programmatically determine if another Visual Studio solution has been saved in "build mode" or "release mode". Is there an API for accomplishing this?
Alternatively, I was thinking of using the MSBuild API to build the solution and then check to see if the app has debug symbols. Is there a way of doing this?

Debug, Release or any other custom configuration are just names, anyone can make one to look like the other one in Advanced Build Settings of Project Properties or by tweaking properties in the .csproj directly. Those flags will dictate how you identify a "debug" assembly and how much of "debug" debug really means. That said, the difference in output for default combination of properties is in Debuggable assembly attribute, both default configurations have it and you can see it for yourself using ILSpy.
Debug
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default
| DebuggableAttribute.DebuggingModes.DisableOptimizations
| DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints
| DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
Release
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
On how to read this Debuggable attribute value -- see #MobyDisk answer.

When you build an assembly in debug mode, the compiler adds the [assembly: DebuggableAttribute] automatically. You can use reflection to see if that attribute is present on the assembly. Take a look here for details on how to read attributes from an assembly: How to read assembly attributes

I'm currently solving the same problem using Web.config:
My Web.config (as default this will be equivalent to Web.Debug.config and Web.Development.config) file contains (using your naming above):
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="mode" value="build"/>
<add key="anotherKey" value="another value"/>
</appSettings>
</configuration>
My Web.Test.config and Web.Release.config files contain:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="mode" value="release" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
</appSettings>
</configuration>
Then you can access the 'mode' using:
WebConfigurationManager.AppSettings.Get("mode");
[you don't have to use 'mode' for the key, as long as you are consistent]

Related

MSBuild not restoring NuGet packages

I have a solution consisting of multiple projects, several of which reference NuGet packages. There's a web site but also a service which has to be built for x86 or x64; the service is what I'm currently trying to build.
We're on TFS 2013; for this particular solution, I'm using Visual Studio 2015.
"Allow NuGet to download missing packages" and "Automatically check for missing packages during Visual Studio build" are both checked.
I was running NuGet 3.4.4, I've updated to 4.6.2.
I can build fine from Visual Studio. But automated builds on the server fail; but more importantly, it also fails if I try to run MSBuild locally. Similar to this question and this one.
As far as I can tell, the release template is the correct version (12), but I don't think it's a server issue, since I can't build locally either.
The packages are not in source control.
I have a nuget.config in the solution root folder; it previously was in a .nuget folder under the solution root. I do not (and never did) have nuget.exe or nuget.targets in the nuget folder. Here's the config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="NuGetCache" value="\\BuildServer\NuGetPackages" />
<add key="NuGetV2" value="https://www.nuget.org/api/v2/" />
</packageSources>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<solution>
<add key="disableSourceControlIntegration" value="true"/>
</solution>
</configuration>
If I (manually) clear the packages and run
MSBuild /p:Configuration=Release;Platform=x64
(from a VS2015 command prompt), it fails, because it can't find the referenced packages.
As suggested in this answer, I've removed the EnsureNuGetPackageBuildImports targets from my projects; they did not have a RestorePackages tag or an import for nuget.targets.
I tried adding a pre-build event to do the package restore (yes, I realize this is the "old" way of doing things)
"C:\Program Files (x86)\NuGet\nuget.exe" restore -ConfigFile "$(SolutionDir)nuget.config" -PackagesDirectory "$(SolutionDir)packages"
... but it consistently fails ("The command exited with code 1"). If I copy the NuGet command line from the MSBuild output and execute it on its own, it succeeds.
I have noticed one odd thing: in the pre-build event, NuGet says "The folder d:\path\to\solution\project1\bin\Release-x64 does not contain an msbuild solution or packages.config file to restore". I'm not sure why it's looking for those in the output folder.
I do have a workaround for this. We have a network share set up to use as sort of a package cache. If I hand-edit the project files and change each reference so that the HintPath points to \\BuildServer\NuGetPackages\ rather than ..\packages\, the build will succeed. But this is ugly, and more importantly it significantly degrades the performance of Visual Studio.

Replace config value in teamcity build step

I have a build step in teamcity which allows me to replace web.config values with web.release.config values. I would like to add one more step - pass some parameter from teamcity to web.config. In my case it will be release version, which is part of connection string. The best idea I have is just to have some powershell script which will replace text in some file (web.config). Are there any better options?
Example web config
<add key="Version" value="Replace me, please from teamcity"/>
<add key="some key" value="example 2. version as part of some value #VERSION"/>
You could use File Content Replacer.
Instead of making the creation of the web.config in release dependent of TeamCity, you can use the web.config transformation syntax
ie: To create a specific connection string:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="MyDB"
connectionString="value for the deployed Web.config file"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>

The key 'LocalizedPerfCounter' does not exist in the appSettings configuration section

I have a desktop application coded in VB.Net with .net 2.0 and then upgraded VS many times and latest framework is 3.5 with VS 2015.
On application start I've noticed an exception in Diagnostic Tool which is caught silently
The key 'LocalizedPerfCounter' does not exist in the appSettings configuration section.
Any ideas to fix this problem because this is an application I distribute.
Found an answer on this link and seems it is related to app setting which was missing in app.config file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="LocalizedPerfCounter" value="true" />
</appSettings>
</configuration>
I needed to add appSettings section after configSections section.

Specify Machine Name in Web.Config Transform

I am using Web.config transforms to successfully create debug and release versions of the my web.config - this is working correctly.
I am interested to know whether there is a 'machine name' property to specify the current machine name which I can use in a debug URL, rather than hard-coding a specific machine name (using localhost isn't an option in the case), e.g.
<add name="XrmService" connectionString="http://$(ComputerName):5555/Service.svc" />
Are there any properties available using Web.config transforms? Similar to MSBuild's $(ComputerName) property?
I faced a similar issue, what I ended up doing is :
1) Added the following build target to the project file. (Which is an MSBuild script effectively)
<Target Name="AfterBuild">
<TransformXml Source="Web.config" Condition="Exists('Web.$(Computername).config') " Transform="Web.$(Computername).config" Destination="Web.config" />
</Target>
2) Added a Web.MyMachineName.config config transform file to the project. In your case it should look like this:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="XrmService"
connectionString="http://MyMachineName:5555/Service.svc"
xdt:Transform="SetAttributes"
xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
This has the benefit of running different transformations based on the machine name, without creating a separate build configuration. You can configure it to be debug only by specifying Condition="'$(Configuration)' == 'Debug'".
There is an Environment Variable that you can use. It is $(COMPUTERNAME).
Open a command window, type "set" (without the double quotes) and press Enter. You will see this Environment Variable somewhere at the top of the screen.

MSBuild: building website using AspNetCompiler - adding references?

I'm attempting to build a ASP.NET website using MSBuild - specifically the AspNetCompiler tag. I know that, for my project, I need to add some references. Within Visual Studio I have several references, one is a project reference and the others are some DLLS (AjaxControlToolkit etc). I'm happy not referencing the project and referencing the DLL instead - however I just can't work out how to add a reference. I've looked up and down and this is what I've found so far:
<Target Name = "PrecompileWeb">
<AspNetCompiler
VirtualPath = "DeployTemp"
PhysicalPath = "D:\AutoBuild\CruiseControl\Projects\Websites\MyCompany\2.0.0\WorkingDirectory\VSS"
TargetPath = "D:\AutoBuild\CruiseControl\Projects\Websites\MyCompany\2.0.0\PreCompiled"
Force = "true"
Debug = "true"
Updateable = "true"/>
</Target>
Also - I've picked up this bit of code from around the web somewhere, which I thought might help:
<ItemGroup>
<Reference Include="My.Web.DataEngine, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>D:\AutoBuild\CruiseControl\Projects\Components\My.Web.DataEngine\bin\Debug\My.Web.DataEngine.dll</HintPath>
</Reference>
</ItemGroup>
What I want to do is add a attribute to the AspNetCompiler tag, something like:
References="#(Reference)"
but MSBuild isn't very happy about this.
I've been a bit stuck in not being able to find decent references on doing this anywhere: so I'd really apprechiate some pointers or reference material etc. (or just the answer!)
Thanks for you help.
-tom
The aspnet_compiler tool doesn't have a reference property.
Have you looked at using Web Deployment Projects (2005 version)?
You can add references to assemblies used during the compilation of an ASP.NET application by adding to the <assemblies> element, under <compilation> if your web.config. For example:
<compilation targetFramework="4.6.2" debug="true">
<assemblies>
<add assembly="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
Read more here: https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/bfyb45k1(v=vs.100)