Skip to content
Latchkey

vswhere: Locate the Visual Studio Install in CI

vswhere reports installed Visual Studio and Build Tools instances; CI uses it to discover the install path and then locate msbuild.exe or vcvarsall.bat without hardcoding versions.

Hardcoding a VS path breaks when the runner image updates. vswhere (shipped under Program Files (x86)\Microsoft Visual Studio\Installer) returns the real path so your build script stays portable.

What it does

vswhere enumerates VS instances (2017+) and prints details about them. With -latest it picks the newest, -requires filters by installed workload/component, and -property installationPath prints just the folder so you can append the path to msbuild or the VC tools.

Common usage

PowerShell
:: get the newest install path including Build Tools
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ^
  -latest -products * ^
  -requires Microsoft.Component.MSBuild ^
  -property installationPath

:: PowerShell: resolve msbuild.exe from vswhere
$vs = & vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath
$msbuild = Join-Path $vs 'MSBuild\Current\Bin\MSBuild.exe'

Options

FlagWhat it does
-latestReturn only the newest matching instance
-products *Include Build Tools and all editions (not just IDE)
-requires <id>Filter to instances with a component/workload
-property <name>Print one property, e.g. installationPath
-prereleaseInclude preview installs
-format jsonEmit JSON for scripting

In CI

Always pass -products *; without it vswhere ignores the standalone Build Tools that CI agents usually have, returning nothing. Combine with -requires Microsoft.Component.MSBuild to ensure the instance can actually build, then derive the msbuild path from installationPath.

Common errors in CI

vswhere prints nothing (empty output) when no instance matches; the usual cause is omitting -products * so it skips Build Tools. A script then fails with "MSBuild.exe ... cannot be found" because $vs was empty. "vswhere is not recognized" means you did not use the full Installer path (vswhere is not on PATH by default). Requiring a component the agent lacks (-requires) also yields empty output.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →