Search code examples
azurevisual-studiopowershellvisual-studio-2017-build-tools

vs_buildtools.exe The application cannot find one of its required files, possibly because it was unable to create it in the folder


I have a Windows VM on Azure. On startup it runs powershell script:

Start-Process cmd.exe -ArgumentList "/c whoami.exe 1> c:\whoami.log 2>&1" -wait

$tempPath = "$env:TEMP"
$exePath = "$tempPath\vs_buildtools.exe"

Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_BuildTools.exe -UseBasicParsing -OutFile $exePath

Start-Process cmd.exe -ArgumentList "/c $exePath --quiet --add Microsoft.VisualStudio.Component.TestTools.BuildTools 1> c:\vs_buildtools.log 2>&1" -Wait

After creating the VM:

  1. whoami.exe works fine and writes nt authority\system to c:\whoami.log file.
  2. vs_buildtools.exe is downloaded to C:\Windows\Temp
  3. BuildTools doesn't install anything. There is no dd_* log files in temp folder.
  4. c:\vs_buildtools.log contains this error message:

The application cannot find one of its required files, possibly because it was unable to create it in the folder. Please make sure that the folder in which this application was downloaded is accessible and not read-only.

When I run the script via RDP it works fine and writes dd_* log files to temp folder.

Aslo I tried -Verb runAs. Same issue.


Solution

  • It is my fault I didn't show the whole script. I was sure that different parts of my script did not affect each other. But I was wrong. There was a piece of script which broke system paths including temp path:

    # Optional: For bash.exe, add 'C:\Program Files\Git\bin' to PATH
    [Environment]::SetEnvironmentVariable('Path', "$([Environment]::GetEnvironmentVariable('Path', 'Machine'));C:\Program Files\Git\bin", 'Machine')
    
    # Make new environment variables available in the current PowerShell session:
    foreach($level in "Machine","User") {
       [Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
          # For Path variables, append the new values, if they're not already in there
          if($_.Name -match 'Path$') { 
             $_.Value = ($((Get-Content "Env:$($_.Name)") + ";$($_.Value)") -split ';' | Select -unique) -join ';'
          }
          $_
       } | Set-Content -Path { "Env:$($_.Name)" }
    }