MSBuild: changing project references to file binary references - visual-studio-2010

I have a few .net / C# projects that I'm building with MSBuild.
In the project I'm building, there are some project references to other C# projects.
I'm only building individual projects, so I'd like to repoint the project references to actual binaries in a folder during the build.
I'm already setting "BuildProjectReferences" to False for my MSBuild step.
So essentially I want to have MSBuild ignore the project refs and look for those binaries in a new directory.
Is this possible to do? Is this possible without having to dynamically modify the project file prior to build?
** Update 1 **
More info might help...I'm actually building each binary via Ant/AntDotNet/MSBuild and uploading to Artifactory. I'm basically using Ivy's dependency management with .Net binaries.
Right now I have the uploads and downloads of dependencies working fine.
The only part I'm missing is getting MSBuild to look for the binaries as file dependencies instead of the project references that it has in the project file.
** Update 2 **
It looks like MSBuild supports editing the csproj file using XMLPoke and XMLPeek.
So in my case I'd need to change the following in my project file:
<ProjectReference Include="..\MyReferencedProject\MyReferencedProject.csproj">
<Project>{MyReferencedProjectGUID}</Project>
<Name>MyReferencedProject</Name>
<Private>False</Private>
</ProjectReference>
to this
<Reference Include="MyReferencedProject">
</Reference>
Can anyone give me any pointers on that?

Answer on Update2:
Your question is related/duplicate to this question. There is no easy way to convert it. You should write MSBuild custom task for it to update MSBuild project files before build.

I ended up using Ant combined with the xmltask addon.
<target name="convert" description="convert project references to file references">
<echo>Converting the following Project references :: ${Project.ItemGroup.ProjectReference.Name}</echo>
<xmltask source="MyParentProject.csproj" dest="MyParentProject.csproj">
<rename path="/:Project/:ItemGroup/:ProjectReference/:Name" to="BinaryName"/>
</xmltask>
<replace file="MyParentProject.csproj" token="<BinaryName>" value="<Reference Include=""/>
<replace file="MyParentProject.csproj" token="</BinaryName>" value=""></Reference>"/>
<xmltask source="MyParentProject.csproj" dest="MyParentProject.csproj">
<copy path="/:Project/:ItemGroup/:ProjectReference/:Reference" buffer="refbuffer" append="true"/>
<paste path="/:Project/:ItemGroup[1]" buffer="refbuffer"/>
<remove path="/:Project/:ItemGroup/:ProjectReference" />
</xmltask>
<echo>Conversion complete.</echo>
</target>
In the first xmltask we are setting the "Name" element to "BinaryName" so we can find it.
Next we have two Ant Replace tasks that change something like
"<BinaryName>MyReferencedProject</BinaryName>"
to
"<Reference Include="MyReferencedProject"></Reference>"
And in the last xmltask moves our project references we converted into file references into the upper ItemGroup that normally has the file references.
Then finally we delete the ProjectReferences section.

Related

Similar to PipelineCopyAllFilesToOneFolderForMsdeployDependsOn for UWP packaging

ITNOA
As you can see in Web Deployment Tool (MSDeploy) : Build Package including extra files or excluding specific files and Adding Custom Files to an MSDeploy Package msbuild desired target has property event that name is PipelineCopyAllFilesToOneFolderForMsdeployDependsOn for handling copy desired files into process.
I need something similar for UWP, to add custom file copy to AppX folder during packaging and f5 click in Visual Studio in .csproj file.
thanks
After many working I found solution, AppX Packaging is coordinate from Microsoft.AppxPackage.Targets that exists in Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\AppxPackage and all important target for packaging and running (f5 in Visual Studio) exists here.
As you can see in this file, Microsoft create some blank target between important target in build and packaging pipeline, so you can use override these blank targets very cleanly to control procedure of building and packaging AppX, for example you can override blow targets
<!-- Override to specify actions to happen before generating project PRI file. -->
<Target Name="BeforeGenerateProjectPriFile" />
or
<!-- Override to specify actions to happen after generating project PRI file. -->
<Target Name="AfterGenerateProjectPriFile" />
or ...
So for adding custom files into packaging I override BeforeGenerateProjectPriFile target and for adding file, I used PackagingOutputs ItemGroup for adding my file like below
<Target Name="BeforeGenerateProjectPriFile">
<ItemGroup>
<PackagingOutputs Include="$(MSBuildProjectDirectory)\$(OutputPath)$(AssemblyName).exe.config">
<OutputGroup>ContentFilesProjectOutputGroup</OutputGroup>
<TargetPath>$(AssemblyName).exe.config</TargetPath>
<ProjectName>$(ProjectName)</ProjectName>
</PackagingOutputs>
</ItemGroup>
</Target>
If you want this approach in practice, I used this technique in linphone-windows10

How do I set some project references to CopyLocal = false based on metadata?

I have two solutions. The first solution outputs assemblies to /bin/Debug. The second solution references the assemblies in that folder and when it builds, outputs to /bin/Debug/AddOn.
How do I prevent the projects in the second solution from copying the assemblies it references in /bin/Debug into /bin/Debug/Addon without editing every single project file to set CopyLocal to False?
I'm trying to solve this problem using a Directory.Build.props that applies to projects within the second solution.
<Project>
<ItemDefinitionGroup>
<Reference Condition="$([System.String]::new('%(Reference.FullPath)').Contains('bin/Debug'))">
<Private>false</Private>
</Reference>
</ItemDefinitionGroup>
</Project>
MSBuild evaluates $(Reference.FullPath) and a few other metadata to "", which means the assemblies get copied anyway.
GitHub Repo
You can add a target which executes after ResolveAssemblyReferences target into AddOn.csproj like this:
<Target Name="ClearReferenceCopyLocalPaths" AfterTargets="ResolveAssemblyReferences">
<ItemGroup>
<FilesToExclude Include="#(ReferenceCopyLocalPaths)" Condition="$([System.String]::new('%(ReferenceCopyLocalPaths.FullPath)').Contains('bin\Debug'))"/>
<ReferenceCopyLocalPaths Remove="#(FilesToExclude)" />
</ItemGroup>
</Target>
The ReferenceCopyLocalPaths Item is what you need I think. Get some hints from Don’t copy my referenced assemblies and this blog. And since you want this script to apply to all projects in the solution, you can add this target script into Directory.Build.props and place this file in the solution folder.
In addition: In your script, I think you should use bin\Debug instead of bin/Debug in that situation. (Once I use bin\Debug in contains function it works well, but not work with bin/Debug after my test)
Hope it helps :)

MSbuild Update all assembly file in a solution with svn build revision

Is there a way using msbuild community task, to update all the assemblyInfo.cs in a solution with the SVN build number. There is a a lot of solution out there using FileUpdate but the source is one file and not all the files.
<FileUpdate Files="version.txt"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$1.$2.$3.123" />
I want dynamically to go through all the projects and change it version without knowing the projects file name in the solution
It could look for all assemblyinfo.cs files by using wildcards. For example:
<ItemGroup>
<AssemblyInfoFiles Include="..\**\AssemblyInfo.cs"/>
</ItemGroup>
<Target Name="AfterBuild">
<FileUpdate Files="#(AssemblyInfoFiles)"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$1.$2.$3.123" />
</Target>
Then as stijn said that, you can add a project which all others depend on if you want update all assemblyinfo.cs files before build.
If you want to update all asseblyinfo.cs files after build, you need to add other projects' reference to this project.

Can you include a generated file to a WiX project without adding it as an existing file

We use HEAT to build a file for our web project installer. I want to know if there is a way that I can have the file included in the compilation, but not included in the project.
The reason I need this is I would like to not check the file in on our source control, but have it build when we build the wixproj. Otherwise we have to hijack/checkout the file in order to reliably build the project.
If you are using MSBuild and a .wixproj to build your .MSI then you will need to get the output from HEAT to be listed in a Compile item in the .wixproj. If the file is not included it will not get compiled into the final .MSI.
Fortunately, MSBuild provides quite a few options to dynamically include items. For example, you could have a custom target in your .wixproj that runs HEAT and adds the output
<Target Name='RunHeat'>
<Exec Command='heat.exe param param param -o path\to\output.wxs' />
<ItemGroup>
<Compile Include='path\to\output.wxs' />
</ItemGroup>
</Target>
Now if you get the RunHeat target to run before the Compile target in wix.targets then the Compile item generated in RunHeat will be included in the Compile target. Given the flexibility of MSBuild there are probably a dozen other ways you could accomplish this task.
Hope that helps and good luck!

SlowCheetah executes after post-build events

I use SlowCheetah to transform my app.configs. I have a multi-project solution where one of the projects executes a post-build event where the output of the bin is copied elsewhere. I've found that SlowCheetah does it's transforms after the post-build event, so the app.config I'm copying is the pre-transformed version.
Does anyone have a suggestion of how I can execute my copy after the SlowCheetah transforms? Is this going to require that I write a custom build task?
If you are using msbuild 4.0 for building your projects - you can hook to slowcheetah targets with new AfterTargets BeforeTargets attributes.
I dont know what exactly target name you want to hook after but this code could gave you base concept how to do this
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Some_Target_Name" AfterTargets="TransformAllFiles" >
<Message Text="= Script here will run after SlowCheetah TransformAllFiles ="/>
</Target>
<Project>
Edited: I installed SlowCheetah and found that AfterTargets attribute should be "TransformAllFiles".
Just set up your target dependency AfterTargets="TransformAllFiles"
Alexey's answer leads to the correct solution but here it is in full:
Right-click your project and select Unload Project
Now right-click the project and select Edit [your project name].csproj
Scroll to the bottom and uncomment the target named AfterBuild and add this attribute AfterTargets="TransformAllFiles"
Move your post build actions into this target using the Exec command:
An example:
<Target Name="AfterBuild" AfterTargets="TransformAllFiles">
<Exec Command="ECHO Hello PostBuild World!" />
</Target>
I have bumped into this problem too... decided to update to latest version of SlowCheetah (current 2.5.8), and this problem appears to have been fixed! No more problems using post-build events to deploy a project with transformed XML!
After the NuGet package upgrade process, I had a strange issue, though... transforms were no longer happening. Editing the project like Naeem Sarfraz suggested, I have found that the SlowCheetah's PropertyGroup section was placed at the end of the .csproj.
It was just a matter of moving it to the top, near the other PropertyGroup sections, and now it works like a charm!
If you need to copy/move other .config files (other than web.config) around after the build before publishing here is how it can be done with Visual Studio 2013 (I didn't test it on earlier versions). This section can be added at the end of the .csproj file right before the closing tag </Project> and it'll be fired just before MSDeploy starts the Publishing process.
<Target Name="MoveConfigFile" BeforeTargets="MSDeployPublish">
<Move
SourceFiles="$(IntermediateOutputPath)Package\PackageTmp\ThirdPartyApp.config"
DestinationFolder="$(IntermediateOutputPath)Package\PackageTmp\bin"
OverwriteReadOnlyFiles="true"
/>
</Target>
The company I work for purchased a third party product that needs to have a .config files in the bin folder along with its assembly in order to work.
At the same time we need to process the product's .config file and be able to move it to the bin folder after transformations.
The $(IntermediateOutputPath)Package\PackageTmp folder contains the whole application that will be copied over the target server.

Resources