Modifying Visual Studio solution and project files with PowerShell - visual-studio-2010

We are currently reorganizing our source code, moving stuff around in a new directory
structure. This impacts our Visual Studio solution and project files, where things like assembly references, possibly output directories, pre and post build events, and so on ... must be updated to reflect our changes.
Since we have many solutions and projects, my hope was to partly automate the process using PowerShell, with something like a PowerShell "provider" for VS:
In an ideal world, I would be able to do something like:
$MySolution.Projects["MyProject"].PostBuildEvent = "copy <this> to <that>"
I know about PowerConsole (which I haven't fully explored yet) for scripting Visual Studio. However, the documentation is scarce and I'm not sure it really covers my needs.
Anything else for easily manipulating solution and project files? Preferably in PowerShell, but I'm open to other suggestions.

In my experience, the easiest way to manipulate Visual Studio solutions using PowerShell (from within or outside of Visual Studio) is to load the project file as XML and use PowerShell to manipulate it.
$proj = [xml](get-content Path\To\MyProject.csproj)
$proj.GetElementsByTagName("PostBuildEvent") | foreach {
$_."#text" = 'echo "Hello, World!"'
}
$proj.Save("Path\To\MyProject.csproj")
If you're running your script in the NuGet Package Manager Console, you can get the paths to all of the project files like so:
PM> get-project -all | select -expand FileName
C:\Users\Me\Documents\Visual Studio 10\Projects\MyProject\MyProject.csproj
C:\Users\Me\Documents\Visual Studio 10\Projects\MyProject\MyProjectTests.csproj
PM>

Editing solution files from PowerShell is very picky about the characters you use in whitespace, making it a pain to automate with text replacements.
If you're editing VS Solution files with PowerShell, there's a good chance you've also got access to the dotnet CLI. I recommend invoking the dotnet CLI from PowerShell instead and using the built-in sln command:
Usage example:
# Create a solution, a console app, and two class libraries.
dotnet new sln -n mysolution
dotnet new console -o myapp
dotnet new classlib -o mylib1
dotnet new classlib -o mylib2
# Add the projects to the solution
# Use --solution-folder to organize the class libraries into a solution folder.
dotnet sln mysolution.sln add myapp\myapp.csproj
dotnet sln mysolution.sln add mylib1\mylib1.csproj --solution-folder mylibs
dotnet sln mysolution.sln add mylib2\mylib2.csproj --solution-folder mylibs
When invoked from PowerShell, you can even use Glob patterns:
dotnet sln todo.sln add (ls -r **/*.csproj)
Docs & examples:
https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-sln

Related

Visual Studio: How can I find corresponding CLI command for a GUI build operation?

I've been a linux/make guy and recently I'm learning to build UE5 engine from VS 2022. I need to figure out a CLI way to build it.
For example, I right click on one of the modules (not sure if it's the most proper name) and choose 'Build' then the build will start. I want to automate the procedure using CLI.
How can I find the corresponding CLI command for this manual operation?
I don't have access to the Unreal Engine source code and I don't know if Epic has done anything highly unconventional.
From your start menu launch the "Developer Command Prompt for VS2022". This is a shortcut file for launching the Windows command line with a batch file run to set up the PATH and other environment variables for the Visual Studio development tools.
Visual Studio project files (.csproj for C# and .vcxproj for C++ for example) are MSBuild files. (MSBuild was inspired by Ant, if that helps.)
Solution files (.sln) are a completely different format but MSBuild can build a solution file.
From the screenshot in the question I can see that the solution is UE5 which will be UE5.sln. I can also see that you want to build a C++ project. I'm guessing the project may be named BenchmarkTest (BenchmarkTest.vcxproj)?
MSBuild has a notion of targets. A target always has a name and it groups a set of tasks to be performed. (It's like a makefile rule in some respects but it's not the same.)
Solutions and projects created with Visual Studio support some standard targets. The 'Build', 'Rebuild', and 'Clean' menu items map directly to some of these targets.
Visual Studio solutions and projects support Configurations and Platforms. The standard Configurations are Debug and Release. The screenshot shows a non-standard configuration of Develop. The screenshot also shows a platform of Win64.
In the Developer Command Prompt, msbuild should be in the PATH. Try the following command:
msbuild --version
To build the solution with the default target (which is 'build') and the default configuration and platform:
msbuild UE5.sln
To run a 'clean':
msbuild UE5.sln -target:clean
The target switch can be shortened to -t.
The configuration and platform are passed as properties using the -property switch. The short form is -p. Multiple property switches can be provided and multiple properties, delimited by ';', can be provided in one property switch.
msbuild UE5.sln -t:rebuild -p:Configuration=Develop -p:Platform=Win64
or
msbuild UE5.sln -t:rebuild -p:Configuration=Develop;Platform=Win64
To build the BenchmarkTest project, specify the project file:
msbuild BenchmarkTest.vcxproj -t:build -p:Configuration=Develop;Platform=Win64

Build specific Visual studio project under project solution using Msbuild and devenv

I have Visual studio project solution which has multiple .csproj. Each .csproj has some reference libraries.The project settings are made in such a way the reference libraries are built first and then .csproj is built. This works as expected when i run it in visual studio IDE. But when i try to execute using msbuild i'm getting an error saying target doesn't exist. Gone through many posts related to this issue ,tried possible things.But didn't built.Looks like i might be doing something silly or missing something in the settings.
Also tried using devenv from commandline. With this option i dont see any error but at same time the project doesnt build.I dont see any message after execution of command.Im using visual studio 2015
Here is my project structure
Poject.sln
ProjectA
porjectB
projectC
Libraries
libA
libB
msbuild "project.sln" target:"D:\Projects\Source\Demo\ProjectA\ProjectA.csproj" /t:build
"/p:Configuration=Debug" "/p:platform=x86"
I see the below error
"D:\project.sln" (D:\Projects\Source\Demo\ProjectA\;build target) (1) ->
D:\project.sln.metaproj : error MSB4057: The target "D:\Projects\Source\Demo\ProjectA" does not exist in the project. [D:\project.sln]
Here is the command used using devenv
devenv.exe "project.sln" /build Debug /project `"D:\Projects\source\Demo\Applications\ProjectA\ProjectA.csproj" /projectconfig Debug
After executing the above its doesnt build and i dont see any error too.
error MSB4057: The target "D:\Projects\Source\Demo\ProjectA" does not
exist in the project.
The error indicates your path in command is not valid and project.sln can't recognize the path. So you actually meet one path-related issue. And you should pass the ProjectA to the targets argument instead of ProjectA.csproj! More details see tip3 in For MSBuild.
For MSBuild:
1.If you're only trying to build ProjectA and its reference libraries.
Navigate(cd) to path where ProjectA.csproj exists, and then use command msbuild ProjectA.csproj /t:build /p:Configuration=Debug /p:platform=x86
Also you can directly use command msbuild AbsolutePath\ProjectA.csproj /t:build /p:Configuration=Debug /p:platform=x86. It's not necessary to use " to cover the path and arguments.
(ProjectA.csproj file should have definitions about the reference to those two library projects, so msbuild ProjectA.csproj will build those two projects first. You don't need to specify the xx.sln in your command.)
2.If you're trying to build whole solution(all the projects):
msbuild project.sln /t:build /p:Configuration=xxx /p:platform=xxx
Navigate to solution folder when you run above command, or use absolutepath\project.sln with that command.
3.When you want to build specific projects(more than one) in solution:
Check How to: Build Specific Targets in Solutions By Using MSBuild.exe. Since you're only build ProjectA, you don't need to use this format. For example: Only when you need to build both ProjectA and ProjectB, but not build ProjectC... You can use command like:
msbuild xxx.sln /t:NotInSlnfolder:Build;NewFolder\InSolutionFolder:Build
Pay attention to the path when you use this format. Whether your project is in solution folder can affect the build result a lot ! And, the direct cause of your issue, this command's targets argument needs one ProjectName as input instead of ProjectName.csproj.
For Devenv command:
1.I always use VS2017 and VS2019,so I'm not certainly sure if VS2015's devenv related command has big difference from VS2017's or VS2019's. But according to details from this VS2017 document:
Commands that begin with devenv are handled by the devenv.com utility, which delivers output through standard system streams, such as stdout and stderr.
Alternatively, commands that begin with devenv.exe can use the same switches, but the devenv.com utility is bypassed. Using devenv.exe directly prevents output from appearing on the console.
I think that's why you don't see any message after execution of command. You should use devenv.com command to see the output in console. And it's by design that devenv.exe will prevents output from appearing on the console.
2.The following command builds the project CSharpWinApp, using the Debug project build configuration within MySolution.
devenv "%USERPROFILE%\source\repos\MySolution.sln" /build Debug /project "CSharpWinApp\CSharpWinApp.csproj" /projectconfig Debug
More details about devenv reference please check this document.
In addition:
1.Looks like you have one strange project structure. I checked your error message above and it seems your several projects(xx.csproj) are not under Solution(xx.sln) folder. Just a suggestion, the normal folder structure for VS2015 is always:
Solution folder
xx.sln
ProjectA folder
ProjectA.csproj
ProjectB folder
ProjectB.csproj
2.For most of the projects, build using msbuild is more powerful and convenient than build using devenv. So if you don't have special reason, I recommend using Msbuild, the build engine of VS.
Hope all above helps to resolve your issue and puzzle. Let me know if your issue persists:)
File "/Users/morel893/Desktop/env/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "projects_project" does not exist
LINE 1: ...ct"."technology", "projects_project"."image" FROM "projects_...

Explanation on specific differences between my click once publish when done via command line and from Visual Studio

I am trying to understand why is my WindowsForm app publish behaving differently, when done via command line and via Visual Studio's Publish.
The differences are:
In my command line publish, a copy of the .exe is placed in the top-directory publish folder, while it is not there, when published via VS
In my command line publish, the .application file is missing in the [Application Files] folder, while it is there when published via VS
A screen shot illustrating the exposed above:
Anyone has any idea why does this happen ? I have tried playing with the publish settings, but still without success.
Below is what my command line statement looks like (ran via Jenkins):
Explanation on specific differences between my click once publish when done via command line and from Visual Studio
That because some features are done by Visual-Studio and not by the MSBuild command line. So the click-once-deployment behaves differently when it's executed from the command-line.
When you publish via command line, only Project.exe and Setup.exe are copied to the deployment folder. You can switch the deployment folder by property PublishDir:
msbuild "ProjectName.csproj" /target:publish /p:Configuration=Release;PublishDir=D:\TestPublishFolder
When you publish from Visual Studio, Visual Studio will do some more features, including Application Files folder and .application file into deployment folder.
If you want to have the same publish result as Visual Studio when you publish via command line, you can custom target to achieve it.
See ApplicationFiles folder missing when ClickOnce publish with command line for more detailed info.
Hope this helps.

What is the default location for MSBuild logs?

I am using Visual Studio Express 2012. Where is the location of the log file? I have searched in the folder where my solution and projects are stored, but cannot find any .log file.
This is the configuration for logging:
Log file from Visual Studio is only supported for C++ projects. You just have to work with the output window for others.
See this similar thread: VS2010: minimal build log in output and detailed log in log file
And in case you happen to do this for a C++ project, the file is at:
... build log in the intermediate files directory
... The path and name of the build log is represented by the MSBuild macro
expression, $(IntDir)\$(MSBuildProjectName).log.
Use build output instead of logging to file. Instead of copy/paste, simply click somewhere in the output and press CTRL + S to save. Visual Studio will prompt you for a location (tested with Visual Studio 2017, but I'm assuming this works in earlier versions too).
The msdn documentation is pretty clear about this (And you ain't gonna like it!):
https://msdn.microsoft.com/en-us/library/jj651643.aspx
Where it says:
To create a build log file for a managed-code project On the menu bar,
choose Build, Build Solution.
In the Output window, highlight the
information from the build, and then copy it to the Clipboard.
Open a
text editor, such as Notepad, paste the information into the file, and
then save it.
While it's true that VS doesn't allow this directly, it is still possible to build with MSBuild "inside" VS2015 and get both the build window output and the log file, as follows: (Arguably this is a bit of a hack.)
In your VS Managed solution, add a new project (Let's call it 'Make').
a. The project type you want is Visual C++/NMake project.
Define the MSBuild commands you need on the command line (see below).
Change the solution configuration to build the NMake project instead of the normal managed projects.
This will create a project that has Build, Rebuild, and Clean command lines where you can execute MSBuild directly. For example:
Rebuild: MSBuild.exe /ds /v:diag /property:Configuration=Debug ..\BuildTest\BuildTest.csproj /t:Clean,Build
Build: MSBuild.exe /ds /v:diag /property:Configuration=Debug ..\BuildTest\BuildTest.csproj /t:Build
Clean: MSBuild.exe /ds /v:diag /property:Configuration=Debug ..\BuildTest\BuildTest.csproj /t:Clean
You can also specify multiple MSBuild.EXE command lines in order to build multiple projects. For the usual build-the-entire-solution outcome you can target only the final end assemblies and let the dependency graph generate the individual targets.
This will produce a .log file, where NAME is the name of the NMake project you used. In the example above, the log would be make.log.
A working example is available on GitHub:
https://github.com/bitblitz/VS_MsbuildExample
(Tested with VS2015)
Note that building individual projects directly will still build with the normal VS behavior, but you can build the full solution inside VS and get the build logs.

Build one project inside a solution from the command line

I am working on a large C++ solution in Visual Studio 2005. I want to log all of the output from the build of one project within that solution. The output window in VS seems to be malfunctioning. I suspect there is too much output for it to handle. I can't copy the output and I can't even save it to disk.
My idea is to build the project on the command line and just redirect the output to a file. I'm not sure what command I have to execute in order to build a project in the context of a solution. I tried to just vcbuild the project, but I think it's missing data inherited from the solution.
Any ideas?
Use DevEnv from the command line:
DevEnv /Build Debug /Project ProjectName %SOLUTION_FILE%
where %SOLUTION_FILE% is an environment variable holding the full
path to the solution file and ProjectName is the name of the project.
The output will go to standard output.
The entire solution can be rebuild with:
DevEnv /Rebuild Debug %SOLUTION_FILE%
Example; for an (installer) project named MSQuantSetup:
set SOLUTION_FILE=D:\dproj\MSQall\MSQuant\MSQuant.sln
DevEnv /Build Debug /Project MSQuantSetup %SOLUTION_FILE%
Or directly without the environment variable:
DevEnv /Build Debug /Project MSQuantSetup D:\dproj\MSQall\MSQuant\MSQuant.sln
Take a look at this page, I think this is what you are looking for. Don't forget the /Project parameter if you want to build only one project.
C# version with MSBuild (put the below code in a .bat file)
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v2.0.50727
call %msBuildDir%\msbuild ".\SomeFolder\MyCSharpProject.csproj" /p:Configuration=Release /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_ReleaseVersion_One_Project_CSharp_LOG.log
set msBuildDir=
Or for C++:
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v2.0.50727
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
call %msBuildDir%\msbuild ".\Project1\Project1\Project1.vcxproj" /p:Configuration=Release /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_ReleaseVersion_One_Project_C_Plus_Plus_LOG.log
set msBuildDir=
You'll need to pick your framework (2.0 or 4.0 (or other??), where I have
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\vA.BCDEF
Just comment out or remove the framework version you do not want.
I had a solution with five (sub) projects. I built the "bottom most" project. And it only built this (single) assembly.
Keep in mind if the project you pick has dependencies, it'll build those as well. AKA, if you pick the "top most" assembly, it will build everything it needs.

Resources