Use Visual Studio csproj file as input for MsBuild [duplicate] - c#

This question already has answers here:
Path to MSBuild
(22 answers)
Closed 2 months ago.
I created a C# console application with Visual Studio 2022 that just prints a hello world on the console for testing purposes. Now I am trying to build the project using MSBuild directly on the command line.
As far as I understood, Visual Studio uses MSBuild as well, so at first I tried to just execute:
"c:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" LeoBuildToolsTest.sln
which reports an error regarding wrong XML namespace. After I fixed that, there's a problem regarding missing targets, which is obvious, as there are none:
<Project Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
</Project>
I was able to get the project build by MSBuild but only with my manually written testproject.proj file. So I want to ask whether there is a way to automatically generate a MSBuild proj file by VS that be used directly as input? Or do I always have to write it by myself?

To locate the proper msbuild.exe, you could use:
for /f "usebackq tokens=1* delims=: " %%i in (`vswhere -latest -requires Microsoft.Component.MSBuild`) do (
if /i "%%i"=="installationPath" set InstallDir=%%j
)
:: https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019
echo InstallDir=%InstallDir%
if exist "%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" (
"%InstallDir%\MSBuild\Current\Bin\MSBuild.exe" -nologo -verbosity:normal yourSolution.sln -property:Configuration=Release
) else (
echo.
echo MSBuild not found!
echo expected in "%InstallDir%\MSBuild\Current\Bin\MSBuild.exe"
echo.
)
Path to vswhere.exe on my system is
"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"

Related

PublishSingleFile does not produce a single executable

I have a .Net Core 3 console application that i'm trying to publish as a self contained single executable. I've been able to do this in the past but to my suprise it no longer works. The project structure is a console application with two assemblies, all in Core 3.
If i use dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true i expect the output to be a single executable of several mb's in size. However the publish folder contains the executable (few hundred kb) and a .dll file together with .cache files and the pdb.
The config for my console app is as follows:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
If i publish the app directly from Visual Studio i get the same results as above.
So my question boils down to: Why doesnt this configuration or publish statement result in a self contained single executable?
I can get my 3.1 console app to publish with the following:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>..\..\Binaries\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>False</PublishReadyToRun>
<DebugType>None</DebugType>
</PropertyGroup>
</Project>
If I set PublishReadyToRun to True (or add PublishTrimmed as True) it fails. Adding DebugType None prevents it publishing the pdb file for the exe.
UPDATE: removing the SelfContained tag stops it creating the 'dotnetcoreapp3.1' folder.
According to the command line release, I tested successfully. A single executable file was generated. If you have always failed to publish, I suggest you use VS to publish.The publishing process is as follows:
1.Right click on the project->publish
2.Change configuration
3.Save the configuration and click Publish

How to run current open file with 'dotnet run' command in VS CODE?

I have a project in VS Code with multiple .cs files. Executing 'dotnet run' returns an error saying there is more than 1 entry point(main() method).
I am trying to find a way to only run the currently selected/opened file when I execute 'dotnet run' from the terminal. The only solution I found was to hardcode the name of the [Namespace.ClassName] into StartupObject property in the .csproj file.
I need a more abstract approach to tell VS Code that the StartupObject should be Namespace.${fileBasenameNoExtension}
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>C__SQL</RootNamespace>
<StartupObject>Csharp_SQL.${fileBasenameNoExtension}</StartupObject>
</PropertyGroup>
I am trying to implement something similar to the above code

Unable to find MSBuild 15 while building a C# project, Unable to find "Microsoft.Common.props"

I'm currently attempting to build a C# project, but MSBuild fails with:
C:\Program Files\dotnet\sdk\2.1.401\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props(33,11): error MSB4226: The imported project "C:\Program Files\MSBuild\15.0\Microsoft.Common.props" was not found. Also, tried to find "15.0
\Microsoft.Common.props" in the fallback search path(s) for $(MSBuildExtensionsPath) - "C:\Program Files (x86)\MSBuild" . These search paths are defined in "C:\Program Files\Mono\lib\mono\msbuild\15.0\bin\MSBuild.d
ll.config". Confirm that the path in the <Import> declaration is correct, and that the file exists on disk in one of the search paths.
My .csproj looks like:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<AssemblyName>MyProj</AssemblyName>
<PackageId>MyProj</PackageId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
</Project>
I had similar problem while using Visual code installed in CentOS. I tried everything but issue wasn't fixing out. What I did just located the my dotnet sdk path and then try to find "Microsoft.Common.Props" within the folder. In my case sdK folder was:
/usr/share/dotnet/sdk
And surprisingly, I found this file within /usr/share/dotnet/sdk/2.2.203/Current folder instead of /usr/share/dotnet/sdk//2.2.203/15.0/. So, what I did is just copying and pasted the file to the /usr/share/dotnet/sdk//2.2.203/15.0/ location and problem was gone immediately!

How can I get the clickonce build script used by visual studio to publish my application

I have a pretty large multi-project solution. I currently build it in Visual Studio, and then publish using the right-click=> publish option. This works very well.
I am now in the position where I need to automate at least the clickonce publishing beyond what I can do in Visual Studio. I have successfully created a publish.xml file which I can use with msbuild and mage to create something that looks like a clickonce. However, there is a lot of complexity in the config I have in the visual studio interface that I would like to simply be able to copy into my publish.xml file.
Is it possible to get visual studio to generate a file that provides the properties used by MSBuild and/or Mage when visual studio publishes from the right click=> publish process?
Basically, I would like a configuration file that I could use to do something like msbuild publish.xml (or similar) and get exactly the publish result that visual studio makes.
I currently use VS2017. The application is winforms using c#
Here is my publish.xml. It is not supposed to be anything beyond a test
<Project>
<PropertyGroup>
<OutputPathBuild>C:\Users\d_000\Documents\Visual Studio 2017\Projects\CP\CP.UI.Winforms\bin\x86\Debug</OutputPathBuild>
<Version>1.0.0.0</Version>
<OutputPathDeployment>C:\Users\d_000\Documents\CP Deploy\test</OutputPathDeployment>
<Mage>C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\mage.EXE</Mage>
</PropertyGroup>
<Target Name="Deployment">
<Error Condition="'$(Version)'==''" Text="The Version property must be defined in order to build the Deployment task."/>
<ItemGroup>
<DeploySource Include="$(OutputPathBuild)\**"/>
</ItemGroup>
<Copy SourceFiles="#(DeploySource)" DestinationFolder="$(OutputPathDeployment)\v$(Version)\%(RecursiveDir)"/>
<Exec Command='"$(Mage)" -New Application -ToFile "$(OutputPathDeployment)\v$(Version)\MyApp.manifest" -Name MyApp -Version $(Version) -Processor X86 -FromDirectory "$(OutputPathDeployment)\v$(Version)" -IconFile Resources\CPIcon.ico'/>
<Exec Command='"$(Mage)" -New Deployment -ToFile "$(OutputPathDeployment)\MyApp.application" -Name MyApp -Version $(Version) -Processor X86 -AppManifest "$(OutputPathDeployment)\v$(Version)\MyApp.manifest" -IncludeProviderURL true -ProviderURL "http://example.com/download/MyApp/MyApp.application" -Install true'/>
<!-- Grr... Mage tool has a bug whereby -MinVersion only works in Update mode... -->
<Exec Command='"$(Mage)" -Update "$(OutputPathDeployment)\MyApp.application" -MinVersion $(Version)'/>
<Copy SourceFiles="$(OutputPathDeployment)\MyApp.application" DestinationFiles="$(OutputPathDeployment)\MyApp.v$(Version).application"/>
</Target>
</Project>
EDIT:
I need to customize what is in the publish process, so I am looking to find out what Visual Studio is doing. Essentially I want to get the commands run in visual studio, copy them and tweak them so I can automate several different builds with different delpoy URLs and update URLs
The work of k7 helped me get to my solution - so I marked it as the answer, but this gives details of how I solved it in the end.
So, it turns out that all the information to run a publish is included in the project file, and you can almost just run this through msbuild (line breaks added for clarity). For those new to the architecture of the csProj file, it contains lots of properties for the project used in building, publishing and configuring generally, and also a set of targets, which are kind of like different jobs you can run. You run them by specifying the /t: option using msbuild. Targets not specified aren't executed.
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
"C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj" /t:publish
The gotchas are that;
if you refer to the project in the build command instead of the solution, then you also need to specify the solution folder
unless you specify rebuild before publish, any updates you make to your project config will not be reflected in the output - which is an issue if you are publishing under multiple configurations
Specify where to deploy
You likely also want to specify platform and config
In this case, my command became
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
"C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj"
/:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\"
/t:rebuild /t:publish
/p:PlatformTarget=x86 /p:Configuration=Release
/p:PublishDir="C:\Users\me\Documents\Deploy\web\\
At this point I am just rebuilding and publishing my project, just like I can in visual studio.
When I wanted to customize, I just added the additional information into the command line to override;
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
"C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj"
/:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\"
/t:rebuild /t:publish
/p:PlatformTarget=x86 /p:Configuration=Release
/p:PublishDir="C:\Users\me\Documents\Deploy\web\\
/p:UpdateUrl=http://example.com/
/p:ExcludeDeploymentUrl=false
I wanted to take this a bit further and cut down some of the commands, so I modified myProj.csProj - but I wanted to keep the code separate. I did this by adding an import directly after my publish info in the project file (this is the property group with members likePublishURL and UpdateEnabled). This goes straight after the relevant tag
<Import Project="CustomBuild.targets" />
The CustomBuild.targets file contained by different configs.
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishType>none</PublishType>
</PropertyGroup>
<Choose>
<When Condition="'$(PublishType)' == 'web'">
<PropertyGroup>
<PublishDir>C:\Users\me\Documents\Deploy\Web\</PublishDir>
<PublishUrl>C:\Users\me\Documents\Deploy\Web\</PublishUrl>
<MapFileExtensions>false</MapFileExtensions>
<UpdateUrl>http://www.example.com/myAppUpdate</UpdateUrl>
<ExcludeDeploymentUrl>false</ExcludeDeploymentUrl>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
</PropertyGroup>
</When>
<When Condition=" '$(PublishType)' == 'network' ">
<PropertyGroup>
<PublishDir>C:\Users\me\Documents\Deploy\Network\</PublishDir>
<PublishUrl>C:\Users\me\Documents\Deploy\Network\</PublishUrl>
<MapFileExtensions>false</MapFileExtensions>
<UpdateUrl>\\DummyServer\Share\</UpdateUrl>
<ExcludeDeploymentUrl>true</ExcludeDeploymentUrl>
</PropertyGroup>
</When>
</Choose>
</Project>
This code provides me with two configs (web and network) that I can use from the command line with a simple switch (in my case PublishType) like this;
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
"C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj"
/:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\"
/t:rebuild /t:publish
/p:PlatformTarget=x86 /p:Configuration=Release /p:PublishType=web
My code does not specify autoincrementing of the build because it is not relevant to me, but this is relatively easy to do with a bit of research into the msbuild tool and targets - or using the info from k7 above.
If you want to create ClickOnce for different stages you have to manipulate the proj file before you call MSBuild.
1) Read your .proj file
$projFilePath = Get-ChildItem $sourceRootDirectory -Filter $ProjectFileName -Recurse
$XmlDocument = [xml] (Get-Content -Path $projFilePath.FullName -Encoding UTF8)
2) You have to update this attributes in your proj files:
$ClickOnceForStages.Split("Dev", "Test", "UAT", "Prod") | Foreach {
$XmlDocument.project.PropertyGroup[0].ApplicationRevision = $BuildRevision
$XmlDocument.project.PropertyGroup[0].ApplicationVersion = $BuildVersion
$XmlDocument.project.PropertyGroup[0].ProductName = "MyProductName.$_"
$XmlDocument.project.PropertyGroup[0].AssemblyName = "MyAssemblyName.$_"
$XmlDocument.project.PropertyGroup[0].PublishUrl = "MyClickOnceDropUncPath_$_"
}
You have to make sure that:
$BuildRevision and $BuildVersion
have a increased version for each build.
3) Save the document without manipulating the orginal proj file.
$currentProjFilePath = $projFilePath.FullName +"_" + $_ + ".proj"
$XmlDocument.Save($clickOnceProjFilePath)
4) Call MSBuild to create a ClickOnce installer.
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
The combination of your proj file with the ClickOnce configuration and the MSBuild parameter:
"/target:publish"
creates a ClickOnce installer.
This is the full MSBuild statement which I use to create a ClickOnce installer:
"$clickOnceProjFilePath",
"/target:publish",
"/p:PublishDir=$outputDirectory",
"/p:Configuration=Release"

Build only the VS Setup project via command line

I have a solution that contains many projects and a setup project (.vdproj).
I want to be able to build ONLY the setup project via command line.
I tried to use
devenv /build Debug "C:\\MySolution\MySolution.sln" /project "CSharpWinApp\CSharpWinApp.vdproj" /projectconfig Debug
but it also built the rest of my solution projects and I want to avoid it. I tried it few times in a row - no project has changed but it stil built it all. I tried to remove the .vdproj project dependencies but it didn't work. I got the message "This dependency was added by the project system and cannot be removed".
Any suggestions?
Use the following command line to build setup projects.
Note: Support for setup projects has been dropped from Visual Studio 2012.
devenv "c:\your solution file.sln" /Project "c:\your setup project file.vdproj" /Build "Release"
If you really have to use msbuild, create a msbuild project file and use the Exec task to call the command line above as demonstrated in Hassan's answer.
you can isolate your setup in a setup solution to be sure that it will not compile your application.
for building your setup project you can do this with TFSBuild 2010 as follow:
First, to automate the building of .vdproj project, you’re going to need to write your own msbuild file because they are not in msbuild format and therefore TFS Build does not know what to do with them. I found some good examples on the net on how to do this, but I updated mine a little for 2010. Here it is:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="Build">
<PropertyGroup>
<DevEnv>$(ProgramFiles)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com</DevEnv>
<SolutionFile>$(MSBuildProjectDirectory)\MySolution.sln</SolutionFile>
<ProjectFile>$(MSBuildProjectDirectory)\MySetupProject\MySetup.vdproj</ProjectFile>
<Configuration>Release</Configuration>
</PropertyGroup>
<Exec Command="$(DevEnv) $(SolutionFile) /Rebuild $(Configuration) /Project $(ProjectFile) /ProjectConfig $(Configuration) /Log" ContinueOnError="false" IgnoreExitCode="false" WorkingDirectory="$(MSBuildProjectDirectory)" />
</Target>
</Project>
thank to Leonard Woody

Categories

Resources