We have a product but we are doing some rebranding so we need to be able to build and maintain two versions. I used resource files combined with some #if stuff to solve the strings, images, and whatever else, but the program icon is giving me trouble. I couldn't figure it out from msdn or a google search. Thanks!
Are you referring to the application icon? You can edit your project file manually and put in code similar to the following:
<PropertyGroup>
<ApplicationIcon Condition=" '$(Configuration)' == 'Version1' ">Icon1.ico</ApplicationIcon>
<ApplicationIcon Condition=" '$(Configuration)' == 'Version2' ">Icon2.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Version1' ">
<Content Include="Icon1.ico" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Version2' ">
<Content Include="Icon2.ico" />
</ItemGroup>
Create icon files named after your config. (E.g. DebugOld.app.ico DebugBranded.app.ico, ReleaseBranded.app.ico)
Create a pre-build step:
copy "$(ProjectDir)$(ConfigurationName).app.ico" "$(ProjectDir)app.ico"
Set the icon in normal code, and you should be able to use the same techniques as you have elsewhere. You'll need both icons in the resources file (at least so I suspect) but it should work.
Alternatively, set a prebuild step to copy the appropriate icon into a common filename - e.g. copying debug.ico or release.ico into app.ico. A bit hacky, but I think it would work. That way you only end up with one icon in the finished binaries.
Yet another option: look into the build file and see how the icon is built in, then conditionalise it. Marc Gravell did this for references in MiscUtil - the project can be built targeting either .NET 2.0 or 3.5, depending on configuration. I suspect that resources could be conditionalised in a very similar way.
Related
I created a task in our C# Projects to auto-version projects when they are built (changes are made) in release mode. The versioning part works perfectly. However, all the projects are being built regardless if the project actually changed when done from command line. This causes projects to be versioned unnecessarily. Building in Visual Studio works, unchanged projects are not built, however we made a tool to do automated build using msbuild.exe and are using this as a temporary fix while we work on Bamboo and that method always does a blind build, even if there are no changes to the project. I need to be able to identify if changes were made to the project.
Something like
'$(wasSourceUpdated)' == 'true' or some kind of target condition to use on my custom versioning target.
Here is a sample of my versioning task in our projects
<Import Project="..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets" Condition="Exists('..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets') And '$(Configuration)|$(Platform)' == 'Release|AnyCPU' And '$(DeployOnBuild)' != 'true'" />
I also checked this and this articles to no avail.
EDIT
I need the task to run before the build is actually executed in order to stamp the generated assemblies with the new versions
EDIT 2
What I'm really looking for is the condition to run CoreCompile or to run CoreCompile again when I detect that the assembly was updated
What I've tried so far:
<Project>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<_AssemblyTimestampBeforeCompile>%(IntermediateAssembly.ModifiedTime)</_AssemblyTimestampBeforeCompile>
</PropertyGroup>
<PropertyGroup>
<_AssemblyTimestampAfterCompile>%(IntermediateAssembly.ModifiedTime)</_AssemblyTimestampAfterCompile>
</PropertyGroup>
<PropertyGroup>
<_ProjectVersioned Condition="'$(_ProjectVersioned)'==''">false</_ProjectVersioned>
</PropertyGroup>
<Target Name="IncrementVersionBeforeBuild" AfterTargets="CoreCompile" Condition="'$(_AssemblyTimestampBeforeCompile)'!='$(_AssemblyTimestampAfterCompile)' and '$(_ProjectVersioned)' == 'false'">
<Message Text="Before $(_AssemblyTimestampBeforeCompile) After $(_AssemblyTimestampAfterCompile)" Importance="High"/>
<IncrementVersion
ProjectPath="$(MSBuildProjectFullPath)"
VersionRule="3.3.0.+"
FileName="Properties\AssemblyInfo.cs">
</IncrementVersion>
</Target>
<PropertyGroup>
<TaskPath>$(MSBuildThisFileDirectory)..\Tasks\AutoVersionTask\AutoVersionTask\bin\Debug</TaskPath>
</PropertyGroup>
<!-- Sample import for projects
<Import Project="..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets" Condition="Exists('..\..\DXT.BuildTasks\Targets\DXTAutoIncrementVersion.targets') And '$(Configuration)|$(Platform)' == 'Release|AnyCPU' And '$(DeployOnBuild)' != 'true'" />
-->
<UsingTask AssemblyFile="$(TaskPath)\AutoVersionTask.dll" TaskName="AutoVersionTask.IncrementVersion" />
<PropertyGroup>
<_ProjectVersioned>true</_ProjectVersioned>
</PropertyGroup>
Thanks in advance
So Thanks to Lance for getting me to understand MSBuild to the point that I understand the issue way better.
After a long time researching the default task, I ran upon this question that had the perfect solution to my issue. After applying the fix the versioning task now only runs when changes are made to the msbuild code.
The inputs and outputs are the same as the CoreCompile target and ensures that the task is only run if there were changes to the source
Here is the target I ran that works:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<CoreCompileDependsOn>
$(CoreCompileDependsOn);
IncrementVersionBeforeBuild
</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="IncrementVersionBeforeBuild"
Inputs="$(MSBuildAllProjects);
#(Compile);
#(_CoreCompileResourceInputs);
$(ApplicationIcon);
$(AssemblyOriginatorKeyFile);
#(ReferencePath);
#(CompiledLicenseFile);
#(EmbeddedDocumentation);
$(Win32Resource);
$(Win32Manifest);
#(CustomAdditionalCompileInputs)"
Outputs="#(DocFileItem);
#(IntermediateAssembly);
#(_DebugSymbolsIntermediatePath);
$(NonExistentFile);
#(CustomAdditionalCompileOutputs)"
>
<Message Text="Version Task running" Importance="High"/>
<IncrementVersion
ProjectPath="$(MSBuildProjectFullPath)"
VersionRule="3.3.0.+"
FileName="Properties\AssemblyInfo.cs">
</IncrementVersion>
</Target>
<PropertyGroup>
<TaskPath>$(MSBuildThisFileDirectory)..\Tasks\AutoVersionTask\AutoVersionTask\bin\Debug</TaskPath>
</PropertyGroup>
<UsingTask AssemblyFile="$(TaskPath)\AutoVersionTask.dll" TaskName="AutoVersionTask.IncrementVersion" />
<PropertyGroup>
<_ProjectVersioned>true</_ProjectVersioned>
</PropertyGroup>
</Project>
Normaly, we can add the script below into .csproj file:
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<Target Name="AutoVersionWhenBuild" AfterTargets="CoreBuild"
Condition="'$(_AssemblyTimestampBeforeCompile)'!='$(_AssemblyTimestampAfterCompile)'">
<Message Importance="high" Text="Auto-version begins when changes are made!"/>
<!--<AutoVersionTask>Do your auto-version task here.</AutoVersionTask>-->
</Target>
It will be called during the build when changes are really made to the project. See this similar issue.
As for your situation:
It seems your tasks and target comes from the targets file DXTAutoIncrementVersion.targets,you can open that file and change the target in it to the format above.
In addition: Please check the relationship between tasks, targets and .targets file.
1.MSBuild uses tasks to perform these actions.
2.Targets group tasks together.
3.MSBuild includes several .targets files that contain items, properties, targets, and tasks for common scenarios.
So you can either modify your auto-version target in the xx.targets file, or use the script above, and call the auto-version task in the AutoVersionWhenBuild target. Hope it helps:)
In my current project I need to use the Windows Media Transcoding API. However, I can't manage to install it.
Here you can see I'm using the correct namespace.
using System.Windows.Media.Transcoding;
I looked around on NuGet, but couldn't find it there. I read the Microsoft page about it, but that only told me the namespace. I also couldn't find it's Assembly. Could someone please help me install it.
You can follow these instructions:
Modify the target platform by opening your .csproj file with an external editor and add the line
<TargetPlatformVersion>8.0</TargetPlatformVersion>
as for this example
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6D41F51D-5A85-4826-9868-14FB3591F280}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WindowsFormsApplication1</RootNamespace>
<AssemblyName>UseWindowsMediaTranscodingAPI</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>
Reload the solution and add a reference to Windows Core Media DLL
This should already compile.
Additionally to be able handle events and async methods mapping you should add the reference to the system dll:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5\System.Runtime.InteropServices.WindowsRuntime
Remember that the application will work only on Windows 10.
Source: https://blogs.msdn.microsoft.com/cdndevs/2013/10/02/using-windows-8-winrt-apis-in-net-desktop-applications/
got an interesting little problem that I can't seem to find an answer to on here.
My project in visual studio 2013 contains lots of language resource files Resources.en-GB.resx etc for the different languages that it can be used in. They compile to dlls in bin\debug\en-GB\Projecty.Wojecty.resources.dll etc.
I also have different build configurations that change a few things for when in different countries.
My question is how do I only build certain language resource dlls for certain build configurations. For example for a deployment in Russia I only want the russian and english language dlls. For deployment in Germany I only want german and english
Thanks to Jenszcz answer and Alexey Scherbaks comments I've discovered a whole new world of msbuild condition statements. Edited the csproj file to add conditions to all the EmbeddedResources
<ItemGroup>
<EmbeddedResource Include="Localisation\Resources.en-GB.resx" />
<EmbeddedResource Condition=" '$(Configuration)' == 'Debug' OR '$(Configuration)' == 'Germany' " Include="Localisation\Resources.de-DE.resx" />
<EmbeddedResource Condition=" '$(Configuration)' == 'Debug' OR '$(Configuration)' == 'Russia' " Include="Localisation\Resources.ru-RU.resx" />
</ItemGroup>
I am working on an automated c# build that requires me to write/generate the csproj file and then compile it using the command line. For some reason while the dll is created without issue, the class it contains is dumped into the global namespace instead of the one I have specified in . Does anyone have any idea what might be going on here?
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>SimpleDependency.Test</RootNamespace>
<AssemblyName>simpledependency.test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>Bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
I have msbuild set to .net 4.0, and am running this command on the command line:
msbuild /property:Configuration=Release /property:Platform=AnyCPU
I know that it generates the dll successfully because I then have another dependent project that uses the class I have defined in this project, but if I include:
using SimpleDependency.Test;
in that code, I get compile errors saying it cannot find namespace 'SimpleDependency'. Without this using statement, it compiles fine and works. Anyone have any thoughts?
Run MSBuild using the /preprocess:flattened.proj flag. Then load up the resulting file in an XML editor. My recent experience is that when properties are not being seen, it's overwritten someplace later (e.g. setting rather than appending to it) or something about conditions. That's a good start. You might also try getting MSBuildExplorer3 and see if that turns up anything. I'm not familiar with C# projects, but I think you should find where $(RootNamespace) is actually used for its effect, and trace backwards: is it ignored due to a condition, not getting the target variation you expected, etc. Once you know the lay of the land, run MSBuild with /verbosity:diag and grep through that for the target where it's (supposed to be) used, and see what it was thinking.
Copying the feedback from Pierre-Luc into an answer: The rootnamespace appears to only be a suggestion to the IDE to inject whenever creating classes. If the .cs files do not have a namespace specified, rootnamespace will not become the namespace for those classes. More information about that problem in this question.
I am using MSBuild along with MSBuild Extensions and I am looking for a way to determine what machine my build is being conducted on.
I want to rev part of our version number based on this, so a developer can tell if a build was conducted on a dev machine, a production build box, et. al.
I think using $(COMPUTERNAME) would be a good start, but how might I do the comparison?
Example:
3.2.0.416 -> The 0 would tell us that the build is an unofficial dev build.
3.2.1.417 -> The 1 would tell us that this build was produced on our QA CI box.
Can anyone point me in the right direction? I found this article to be a good starting point (Setting .NET Assembly Version with Jenkins and TFS)
Create a property based on the MachineName.
Use that property to update the AssemblyInfo.cs file(s) before
building.
I have "SubVersionRevision" below, but just use an alternate syntax to get the TFS version (from the link you have in your original post)........
The Crux of the solution is : setting and using "MyCustomProperty001"
<Choose>
<When Condition=" '$(Computername)'=='MyDevMachine' ">
<PropertyGroup>
<MyCustomProperty001>0</MyCustomProperty001>
</PropertyGroup>
</When>
<When Condition=" '$(Computername)'=='MyQaMachine' ">
<PropertyGroup>
<MyCustomProperty001>1</MyCustomProperty001>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<MyCustomProperty001>9</MyCustomProperty001>
</PropertyGroup>
</Otherwise>
</Choose>
<ItemGroup>
<AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
</ItemGroup>
<SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
<Output TaskParameter="Revision" PropertyName="MySubVersionRevision" />
</SvnVersion>
<FileUpdate Files="#(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\("(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion("$1.$2.$(MyCustomProperty001).$(SubVersionRevision)" />