MSBuild: How Get AppData Local Directory? - msbuild

I need help getting the AppData Local directory for MSBuild.
File Explorer:
%LOCALAPPDATA%
C#:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData)
PowerShell:
$([System.Environment]::GetFolderPath("LocalApplicationData"))
I've tried the following four variations to get it for MSBuild:
<PropertyGroup>
<AppDataLocalDir1>$([System.Environment]::GetFolderPath([System.Environment.SpecialFolder]::LocalApplicationData))</AppDataLocalDir1>
<AppDataLocalDir2>$([System.Environment]::GetFolderPath([System.Environment.SpecialFolder.LocalApplicationData]))</AppDataLocalDir2>
<AppDataLocalDir3>([System.Environment]::GetFolderPath("LocalApplicationData"))</AppDataLocalDir3>
<AppDataLocalDir4>([System.Environment]::GetFolderPath('LocalApplicationData'))</AppDataLocalDir4>
</PropertyGroup>
I feel that my syntax must be close, as this works to get the current date:
<PropertyGroup>
<Today>$([System.DateTime]::Now.ToString('yyyy.MM.dd'))</Today>
</PropertyGroup>
I have found sources that state that MSBuild can call [System.Environment]::GetFolderPath, but I cannot find any that show the syntax for passing in an argument.
Thanks a lot in advance.

From "Property Functions: GetFolderPath" the syntax for the enum for GetFolderPath is:
<PropertyGroup>
<AppDataLocalDir>$([System.Environment]::GetFolderPath(SpecialFolder.LocalApplicationData))</AppDataLocalDir>
</PropertyGroup>

Related

Set msbuild OutputPath conditioned on project name

I'm trying to improve a build-server setup for .NET solutions. The build is done using msbuild solution.sln /p:OutputPath="$pwd/build" and an additional Directory.Solution.targets to work around a quirk of msbuild (from related question, see its content below). Now we've decided to move our tests to separate projects so that the test dlls and their dependencies don't land in the OutputPath. Usually this wouldn't be a problem, but for historical reasons every single project in the solution has its OutputPath set to ..\..\. This is why I'm overriding it when calling msbuild. But now I need to only override it for some of the projects - and I can't figure out how.
The project structure right now looks like this.
app/
sources/
Complete.sln
Proj1/
proj1.csproj
Proj1.Test/
proj1.test.csproj
Building the solution from Visual Studio by a developer results in this (only showing new files), which is fine.
app/
proj1.exe
sources/Proj1.Tests/bin/Release/
proj1.exe
proj1.tests.dll
But building it with msbuild Complete.sln /p:OutputPath="$pwd/build" /t:BuildAll results in following.
app/build/
proj1.exe
proj1.tests.dll
Is there a way without changing solution or project files to get the following?
app/build/
proj1.exe
app/tests/
proj1.exe
proj1.tests.dll
I.e. I want to set the OutputPath for every *.Tests.csproj to /tests, and for every other project to /build.
Alternatively, is there a way to call msbuild Complete.sln in such a way it builds either all the projects from that solution with names that don't end with "Tests" or only those that do?
The Directory.Solution.targets mentioned above (using it for reasons) looks like following.
<Project>
<Target Name="SetSkip">
<ItemGroup>
<ProjectReference Update="*">
<SkipNonexistentProjects>Build</SkipNonexistentProjects>
</ProjectReference>
</ItemGroup>
</Target>
<Target Name="BuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Build"/>
</Target>
</Project>
UPDATE since the number of files grows, for easier testing I've created a repository.
You could try adding the following to Directory.Build.targets (I have not tested it, but it should work):
<PropertyGroup>
<OutputPath Condition="'$(BuildOutputPath)' != ''
and !$(MSBuildProjectName.EndsWith('.Test'))">$(BuildOutputPath)</OutputPath>
<OutputPath Condition="'$(TestOutputPath)' == ''
and $(MSBuildProjectName.EndsWith('.Test'))">$(TestOutputPath)</OutputPath>
</PropertyGroup>
Then invoke msbuild like so:
msbuild Complete.sln /p:TestOutputPath="$pwd\tests" /p:BuildOutputPath="$pwd\build"
There would be other options, like putting the required build or tests paths directly in the properties.

Can wixproj file reference an environment variable?

Using wix 3.10.2.
I would like to reference an environment variable within a .wixproj file.
I have tried (exerpt from my .wixproj):
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<JavaDocsBaseDir>$(env.JAVADOCS)</JavaDocsBaseDir>
but I am getting the error:
error MSB4184: The expression """.JAVADOCS" cannot be evaluated. Method 'System.String.JAVADOCS' not found.
Tried removing the "env." with no luck. Also tried using the windows env var format %JAVADOCS%, also with no luck. What am I doing wrong?
I am calling the build via
msbuild ClientSetup.sln /p:Configuration=Release
So, I have the ability to pass the data via commandline as well, if that is an option.
The syntax $(env.JAVADOCS) or %JAVADOCS% is for use in the wix source (.wxs/.wxi) files. For the project you should use normal MSBuild syntax, not Wix syntax. Try $(JAVADOCS)
You should use $(JAVADOCS).
Take a look at Microsoft documentation:
https://msdn.microsoft.com/en-us/library/ms171459.aspx

MSBuild + Scope of property

I am defining a property in the .csproj file
<PropertyGroup>
<ProjectGuid>{3099AE33-98E7-4018-B0C3-4C3A37A6D56E}</ProjectGuid>
<OutputType>Exe</OutputType>
<!-- Property for CASI Dev Build location -->
<AppRoot>$(INETROOT)\target\distrib\$(BuildType)\$(BuildArchitecture)\CASI_Dev</AppRoot>
<DeploymentBranch>Dev</DeploymentBranch>
I also have a referenced project: say
<ItemGroup>
<ProjectReference Include="$(INETROOT)\refproj.csproj">
<Project>{F73278A5-AB7E-4FFD-8592-F135E7DB06F2}</Project>
<Name>RemoteProj</Name>
</ProjectReference>
Is there some way to access the property $(DeploymentBranch) or $(AppRoot) in the referenced project i.e in file refproj.csproj.
If i try to access them now the value is blank
Based on what I know about MsBuild this is not possible by "standard" way. But here are the options you can achieve it:
1) Pass property values in MSBuild command line for building your root solution:
msbuild mySolution.sln /t:Build /p:Configuration=...;Platform=...;DeploymentBranch=...;AppRoot=...
2) In your refproj.csproj, you can import main.csproj . but keep in mind the "relativeness" of your paths and that main.csproj might override your refproj.csproj properties and targets.
See more information here

Is there a way not to let MsBuild run static contract analysis with code contracts?

In my project, static checking is disabled, but still, when I run msbuild.exe with cmd, it starts static checking for each project... Is there a way, with parameters, to disable this?
This might be a 'little' late, but since I just encountered the same problem and /p:RunCodeAnalysis=false doesn't work for me:
Try msbuild ... /p:CodeContractsRunCodeAnalysis=false.
That works as of Feb. 2011 according to the code contracts documentation and my experience.
The following should do it:
MSBuild ... /p:RunCodeAnalysis=false
If you don't want to pass parameters to msbuild or you are building from Visual Studio, there is a way to suppress static code contracts check and code analysis.
Notice: each *.csproj file contains this: <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />.
For .Net 4.0 msbuild.exe and Microsoft.CSharp.targets path is "C:\Windows\Microsoft.NET\Framework\v4.0.30319\"
Open Microsoft.CSharp.targets
Add new PropertyGroup inside Project like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup>
<CodeContractsRunCodeAnalysis>false</CodeContractsRunCodeAnalysis>
<RunCodeAnalysis>Never</RunCodeAnalysis>
<CodeContractsReferenceAssembly>DoNotBuild</CodeContractsReferenceAssembly>
</PropertyGroup>
...
<!-- a lot of stuff -->
...
</Project>
Doing so will emulate msbuild command line arguments (i.e /p:CodeContractsRunCodeAnalysis=false,RunCodeAnalysis=Never,CodeContractsReferenceAssembly=DoNotBuild
All your builds now on your pc (either from MSBuild and Visual Studio) will skip code and static code contracts analysis, so you don't need to pass args from Command Line.

How do I import the msbuildcommunitytasks project from another msbuild project with a relative file path?

Please go easy I am new to msbuild and msbuildtasks!
How can I set a property which represents a relative file path to a targets file which I want to import? I need relative references so it will work on all dev machines. But the target for import is trying to use the relative file path internally, which won't work as it is re-evaluated relative to the imported target!
Effectively I am trying to work around the documented behaviour of imported projects:
All relative paths in imported
projects are interpreted relative to
the directory of the imported project.
Therefore, if a project file is
imported into several project files in
different locations, the relative
paths in the imported project file
will be interpreted differently for
each imported project.
There was a similar question at Is it possible to use MSBuild Extension Pack without installation?. That question was how to do the same with the MSBuild Extension Pack, both of which are similar in this aspect. For the Extension Pack you have to declare the property ExtensionTasksPath,and for the Community tasks you have to declare a similar property named MSBuildCommunityTasksLib. So in your case it should look like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksLib Condition="'$(MSBuildCommunityTasksLib)' == ''">E:\Data\Development\My Code\Community\MSBuild\CommunityTasks\</MSBuildCommunityTasksLib>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksLib)MSBuild.Community.Tasks.Targets"/>
<Target Name="Demo">
<!-- Use the tasks here -->
</Target>
</Project>
Ok, I've found the answer. Essentially you have to set the property MSBuildCommunityTasksPath as a relative path back to the original containing directory.
For example, given a folder structure like this:
Root---project---Build---{My msbuild project}
|
|-Tools---MSBuildCommunityTasks---{Binaries and Targets}
Where :
{My msbuild project} is in Root\Project\Build\
{MSbuildCommunityTasks} is in Root\Project\Tools\MsBuildCommunityTasks
To get the targets project to reference its binaries via the property MSBuildCommunityTasksPath, it will find the tasks file like this:
<PropertyGroup>
<MSBuildCommunityTasksPath>..\MSBuildCommunityTasks\</MSBuildCommunityTasksPath> <!--Relative path back to yourself-->
</PropertyGroup>
Then you can import the targets file with another relative file reference :
<Import Project="..\..\Tools\MSBuildCommunityTasks\MsBuild.Community.Tasks.Targets"/>
#Sayed Ibrahim Hashimi
Talkin about MSBuild4
Just declaring the MSBuildCommunityTasksLib wont suffice cause if u check the MSBuild.Community.Tasks.Targets file the properties are declared as follows
<PropertyGroup>
<MSBuildCommunityTasksPath Condition="'$(MSBuildCommunityTasksPath)' == ''">$(MSBuildExtensionsPath)\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<MSBuildCommunityTasksLib>$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll</MSBuildCommunityTasksLib>
</PropertyGroup>
So if U only over ride the MSBuildCommunityTasksLib it will again get over ridden in the MSBuild.Community.Tasks.Targets file as it is not conditional
So u HAVE TO ALSO OVERRIDE MSBuildCommunityTasksPath so that its proerty is NOT SET FROM MSBuildExtensionsPath but from ur custom path.
Correst me if I m wrong
This appears to be one answer:
http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/feb782e3-72ae-4476-9011-617796f217b6
But this (if I understand it correctly) appears to be a ridiculous solution. To get the paths to work I need to change the imported project references? What would happen if I wanted to reference the imported project from third project in another folder?!?
I'm a noob at msbuild if I'm quite honest however I've just solved my own problem I had with this. I was turning one of the targets into its own project and it wasn't finding the paths for the msbuild community paths. If you look at your original project you may find something like this
<PropertyGroup>
<ExtensionTasksPath>./</ExtensionTasksPath>
<MSBuildCommunityTasksPath>./</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="MSBuildExtensionPack\MSBuild.ExtensionPack.tasks"/>
<Import Project="MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
Copy this code into your new project and it should work.
I just wanted to add, since i cannot comment (rep), that to do a path to your particular project you can use $(SolutionDir) on your property group like so:
$(SolutionDir)\My Code\Community\MSBuild\CommunityTasks\
This way its not tied down to a specific drive and can be based off of the location of the project relative to your solutions directory structure.
Also thanks for the answer above it helped me in my project with the addition above.