= Run builds without the Visual Studio GUI =
Sometimes you can get away with just calling MSBuild against a solution or project file. For convenience, here's some example paths:
```
lang=sh
# Visual Studio 2008
"C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe"
# Visual Studio 2015 32-bit and 64-bit
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
"C:\Program Files (x86)\MSBuild\14.0\Bin\amd64\MSBuild.exe"
# Visual Studio 2017
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe"
# Visual Studio 2019
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
# Visual Studio 2022
"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe"
# If you have a new enough version, this should locate it and describe it
"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
```
You may need to run the .bat file to initialize the environment:
```
# Visual Studio 2017
"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/Common7/Tools/vsdevcmd"
```
= Have multiple builds run without killing eachother =
If you're running more than one build at once (especially with MSBuild, maybe also true of Visual Studio itself?) you may run into
(IMPORTANT) LINK : fatal error LNK1318: Unexpected PDB error; RPC (23) '(0x000006BA)'
This is because the build process fires up an instance of PDBServe if one doesn't exist but uses existing ones if one is running, and then terminates that once the build is done. Which means if you start a second build while another build is running, well . . .
See https://github.com/rust-lang/rust/issues/33145#issuecomment-214577593 and https://codereview.chromium.org/83803003, which details that there's a secret undocumented environment variable to control what PDBServe instance is being used: `_MSPDBSRV_ENDPOINT_`. This led @keithzg to solve things in Jenkins builds like this:
```
lang=groovy
_MSPDBSRV_ENDPOINT_ = UUID.randomUUID()
}
```
= Redistribute the right DLLs =
The official Microsoft tools for building software in C/C++ for Windows naturally results in binaries that, on their own, will not necessarily run on any given Windows installation, another win [[ https://bonkersworld.net/organizational-charts | for Microsoft's org chart]].
https://learn.microsoft.com/en-us/cpp/windows/determining-which-dlls-to-redistribute documents three ways to distribute the necessary libraries.
# Redistribute the installer for that version of Visual Studio's redistributable DLLs and have it automatically run by //your// installer or something. This is Microsoft's recommended method.
# Something called merge modules that I don't know about and Microsoft says you shouldn't use.
# Just shipping the DLLs in the same folder as your software, which Microsoft admits you can do but really doesn't want you to do.
For years now, the only officially cited location for these DLLs has been this paragraph with the same typo:
> The individual Redistributable DLLs are also included in your installation of Visual Studio. By default, they're installed in the Visual the %VCToolsRedistDir%\debug_nonredist\[architecture]\Microsoft.[toolset].[library] folders, where [architecture] represents the target architecture, [toolset] represents the toolset version, and [library] is the Debug library that has the debug DLLs.
In terms of figuring out which ones you need to include, Microsoft's docs also kinda leave this as an exercise for the reader:
> To determine which DLLs you have to redistribute with your application, collect a list of the DLLs that your application depends on. These DLLs are normally listed as import library inputs to the linker. Certain libraries, such as vcruntime and the Universal C Runtime Library (UCRT), are included by default. If your app or one of its dependencies uses LoadLibrary to dynamically load a DLL, that DLL may not be listed in the inputs to the linker. One way to collect the list of dynamically loaded DLLs is to run Dependency Walker (depends.exe) on your app, as described in [[ https://learn.microsoft.com/en-us/cpp/windows/understanding-the-dependencies-of-a-visual-cpp-application | Understanding the Dependencies of a Visual C++ Application]]. Unfortunately, this tool is outdated and may report that it can't find certain DLLs.
Thanks, Microsoft!
For the mentioned UCRT DLLs: https://learn.microsoft.com/en-us/cpp/porting/upgrade-your-code-to-the-universal-crt