I need to update the application's manifest with a new value for 'product'. With mage.exe I can update the name and publisher but NOT the product. In MageUI you can do this, but I need to do it on the commandline.
Is there a solution or workaround for this?
I played around and it seems the command line tool indeed lacks this capability. I guess it was done for keeping it lightweight (or maybe cost issues).
Alternative would be to use the GenerateApplicationManifest MSBuild task:
Example:
<Target Name="Build">
<GenerateApplicationManifest
AssemblyName="myapp.exe"
Product="My Product"
...
OutputManifest="SimpleWinApp.exe.manifest">
<Output
ItemName="ApplicationManifest"
TaskParameter="OutputManifest"/>
</GenerateApplicationManifest>
</Target>
This gives you lot more options (in fact everything that you can do through MageUI, can be done from here) and you bypass mage.exe (and its limitations) totally.
You should be able to use it anywhere MSBuild is supported (csproj files, TFS Build proj files etc).
Related
I have a solution with many projects, about a dozen of which have Octopack installed and packages are being produced correctly when TeamCity runs msbuild /p:RunOctoPack=true /p:OctoPackEnforceAddingFiles=true. As you can probably tell from the p:/OctoPackEnforceAddingFiles flag, each project with Octopack installed also has a nuspec file.
The problem we're having is that Octopack is not honouring the nuspec placeholders as specified at https://learn.microsoft.com/en-gb/nuget/reference/nuspec#replacement-tokens. The one we want to use right now is $id$ which should equal the assembly name of the project being packaged. Instead, when we run Octpack, that $id$ token is empty.
I can see at https://octopus.com/docs/packaging-applications/creating-packages/nuget-packages/using-octopack#UsingOctoPack-Replacementtokens that Octopack allows one to manually override these tokens, but that doesn't help me since Octopack is run on the solution, but I need the name of the project that is being packaged.
What can I do to get around this issue? At the moment we essentially have the project name hardcoded in the nuspec files, but this is becoming brittle and unwieldy and we'd like to fix it.
I have this working by adding the following to the csproj file
<PropertyGroup>
<OctoPackNuGetProperties>id=$(AssemblyName)</OctoPackNuGetProperties>
</PropertyGroup>
This passes the assembly name through as id to Octo.exe, which will in turn pass it through to NuGet.exe via its -Properties argument.
Have you tried not providing the $id$ section at all in NuSpec? Octopack should try and generate it (it knows what it is being applied to)?
Alternative could be to use the pre-build event with the $(ProjectName) macro to update the relevant nuspecs. In your case, depending on your build process, potentially sticking to a solution wide pre-build process to update all nuspec's.
P.S. I personally stepped away from using Octopack and currently employ Fake (F# Make).
this is my situation:
I have VS2010 solution with X projects included.
Wix project that can create msi from all compiled artifacts.
I have build machine \ Jenkins that first compile (MSBuild .Net 4) all the solution, then compile the wix to package it to msi.
What\how can I inject to all artifacts\dlls the number of the product (e.g 11.2.0.4789) - as simple as possible?
Is there and command line arguments that can be passed while compiling the solution?
There are tools, such as several extensions for MSBuild, that do version stamping but each assumes a particular workflow. You might find one that works for you but a DIY method would help you evaluate them, even if it isn't your final solution.
You can add a property to the MSBuild command-line like this:
msbuild /p:VersionStamp=11.2.0.4789
Note: I assume you are going to parameterize the Jenkins build in some way or generate the number during a preceding build step. Here is a simulation of that:
echo 11.2.0.4789 >version.txt
set /p version=reading from pipe <version.txt
msbuild /p:VersionStamp=%version%
Now, the work is in getting each project to use it. That would depend on the project type and where you want VersionStamp to appear.
For a csproj, you might want to use it as the AssemblyVersion. The simplest way is to move the attribute to a cs file by itself and rewrite it every time. I would leave a comment in AssemblyInfo.cs as a clue to where it now comes from. You can include the cs file in your project either dynamically or permanently. I prefer dynamically since it is effectively an intermediate file for the build. So, in your .csproj add the following in a text editor (e.g. Visual Studio. Unload and Edit project):
<Target Name="BeforeBuild">
<PropertyGroup>
<AssemblyVersionPath>$(IntermediateOutputDir)AssemblyVersion.cs</AssemblyVersionPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(AssemblyVersionPath)" />
</ItemGroup>
<WriteLinesToFile
File='$(AssemblyVersionPath)'
Overwrite="true"
Condition="'$(ProductVersion)' != ''"
Lines='using System.Reflection%3b;
[assembly: AssemblyVersion("$(VersionStamp)")]' />
</Target>
This is sufficient but a more thorough solution would include adding the file to a list so it is cleaned with other files and only writing the file if the version changed to prevent unnecessary rebuilds, etc.
Use a similar technique for other project types.
I'm trying to write a code generation tool. For this tool it's important that the generated code is available prior to building (i.e., for IntelliSense). I know Visual Studio will at least partially evaluate the project build plan automatically to generate IntelliSense, but I can't find much information on the details.
As a simpler example, let's say I want to take all items with build action None and compile them. I have a project like this:
<Project [...]>
[...]
<Compile Include="Foo.cs" />
<None Include="Bar.cs" />
</Project>
One way to get Bar.cs to compile is to add the following to the project:
<PropertyGroup>
<CoreCompileDependsOn>
$(CoreCompileDependsOn);IndirectCompile
</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="IndirectCompile">
<CreateItem Include="#(None)">
<Output ItemName="Compile" TaskParameter="Include" />
</CreateItem>
</Target>
If I do it this way, Visual Studio acts basically the same as if Bar.cs had the Compile action to begin with. IntelliSense is fully available; if I make a change in Bar.cs it's reflected immediately (well, as immediate as the background operation normally is) in IntelliSense when I'm editing Foo.cs, and so on.
However, say instead of directly compiling the None entry, I want to copy it to the obj directory and then compile it from there. I can do this by changing the IndirectCompile target to this:
<Target Name="IndirectCompile"
Inputs="#(None)"
Outputs="#(None->'$(IntermediateOutputPath)%(FileName).g.cs')"
>
<Copy SourceFiles="#(None)"
DestinationFiles="#(None->'$(IntermediateOutputPath)%(FileName).g.cs')"
>
<Output TaskParameter="DestinationFiles" ItemName="Compile" />
</Copy>
</Target>
Doing this causes IntelliSense to stop updating. The task works on build, dependency analysis and incremental building work, Visual Studio just stops automatically running it when an input file is saved.
So, that leads to the title question: How does Visual Studio choose to run targets or not for IntelliSense? The only official documentation I've found has been this, specifically the "Design-Time IntelliSense" section. I'm pretty sure my code meets all those criteria. What am I missing?
After a few days of experimenting and poking around in the debugger I think I have found the answer, and unfortunately that answer is that this is not possible (at least not in a clearly supported way -- I'm sure there are ways to trick the system).
When a project is loaded, and when the project itself changes (files added/removed, build actions changed, etc), the IntelliSense build is executed (csproj.dll!CLangCompiler::RunIntellisenseBuild). This build will run tasks up to and including the Csc task. Csc will not execute normally, but instead just feed its inputs back into its host (Visual Studio).
From this point on, Visual Studio keeps track of the files that were given as Sources to the Csc task. It will monitor those files for changes, and when they change, update IntelliSense. So in my example, if I manually edit Bar.g.cs those changes will be picked up. But the build tasks themselves will not be run again until the project changes or a build is explicitly requested.
So, that's disappointing, but not surprising, I guess. It also explains something else I had always wondered about -- XAML files with a code-behind tend to have a Custom Tool action of MSBuild:Compile, presumably for exactly this reason.
I'm going to mark this as the answer, but I'd love to be told I'm wrong and that I missed something.
What we currently have:
SVN as source repository
MSBuild scripts for building and setting version numbers
This version numbers is a combination, properties in the build file, and the latest revision from SVN
Cruise control to run the build scripts
What I would like to do:
We have our build scripts updating the version number each time we do the build. I would like to do that automatically each time we do a build by pressing F5 within visual studio. So update the GlobalAssemblyInfo.cs with the correct version number, from the revision number in SVN
A better way to do this is with a SVN hook. The version number would only be changed on a commit, so you can write a hook that updates that file as part of the commit.
Or check out this: http://www.codeproject.com/KB/architecture/svn_visual_studio.aspx
I was just reading about this yesterday with regards to builds from TFS 2010. I know it isn't completely applicable to your situation or architecture, but he raises some good points about how to go about your assembly versioning.
More specifically, the author references this post. Again, it is specific to MSBuild, but there are some points that are applicable to assembly versioning in general
Edit:
The first link talks about the pros and cons of various approaches including using the date as part of your version number (not particularly useful), but leans towards including the TFS build number as part of the assembly version. He refers to his preferred versioning scheme which allows him to identify quickly and easily what the build relates to (hotfix etc). This link is mainly useful to give you some alternative views on assembly versioning.
The second link is referred to by the first link and has some code examples on how he uses MSBuild to help version his assemblies. This could also give some useful ideas on how to go about it. Maybe combine some of these with a post-build event to achieve your goal.
I found a way to do it with the F5 by modifying the project file, and using the MSBUILD.Community.Tasks
<Target Name="BeforeBuild">
<MSBuild.Community.Tasks.Subversion.SvnInfo Username="$(SvnUserName)" Password="$(SvnPassword)" RepositoryPath="$(SvnPath)">
<Output TaskParameter="Revision" PropertyName="SvnRevision" />
</MSBuild.Community.Tasks.Subversion.SvnInfo>
<CreateProperty Value="$(Major).$(Minor).$(Build).$(SvnRevision)">
<Output TaskParameter="Value" PropertyName="FullVersionNumber" />
</CreateProperty>
<MSBuild.Community.Tasks.AssemblyInfo
OutputFile="$(ProjectFolder)\GlobalAssemblyInfo.cs"
CodeLanguage="CS"
AssemblyVersion="$(FullVersionNumber)"
AssemblyFileVersion="$(FullVersionNumber)" />
<Message Text="Test"/>
</Target>
When I use a strong name key file as indicated in the project properties, it requires that all referenced assemblies to also use such a similar signature.
But what I want is to sign using the WinDDK Signtool.exe. This I already do manually, but I also want to debug sign assemblies, and the best way of doing that is including the signature in the build, probably as a AfterBuild step.
The problem is I don't know how to create a AfterBuild step
You are mixing things up here. A strong name is not the same thing as the certificate that's added to a binary with signtool.exe. There is also no requirement that dependent assemblies have a certificate or that it needs to match. Nor does it make sense to sign a debug build, only your customer is interested in it. You already know that you can trust yourself.
Running sn.exe to give an assembly a strong name is already supported by msbuild.
I had to add the following lines to the *.csproj file:
<Target Name="AfterBuild">
<Exec Command="sign.bat" />
</Target>
And then I added a sign.bat file to the project root folder
I found this solution at some blog