Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect prompt to install 'Microsoft Visual C++' when command prompt AutoRun registry key is set to a failing command #2214

Open
cmpotts opened this issue Jun 24, 2020 · 2 comments

Comments

@cmpotts
Copy link

cmpotts commented Jun 24, 2020

Error

The build_ext command gives an erroneous message prompting to install Microsoft Visual C++ when in fact a compatible version is installed.

error: Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for Visual Studio": https://visualstudio.microsoft.com/downloads/

Cause

This happens when the vcvarsall script is executed under command prompt via cmd /u /c. If either of the registry entries

  • HKLM\Software\Microsoft\Command Processor\AutoRun
  • HKCU\Software\Microsoft\Command Processor\AutoRun

exist and executing them returns a non-zero status code, this causes most cmd /u /c invocations to also have a non-zero status code. In particular, when setuptools calls cmd /u /c <vcvarsall_path> the command could complete successfully but still have a non-zero exit code.

Original Environment

  • Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)] on win32
  • Windows 10 Education, 10.0.18363 Build 18363
  • Microsoft Visual Studio Build Tools 2019, 16.6.2

Steps to reproduce

Set either

  • HKLM\Software\Microsoft\Command Processor\AutoRun
  • HKCU\Software\Microsoft\Command Processor\AutoRun

to a falling command (exit 1, path\to\nonexistant.exe, etc.). Then run build_ext on a project that needs to be compiled.

Potential Fix

The following python code should always pass unless something is broken.

subprocess.check_call('cmd /u /c exit %errorlevel%')

Then the above registry entries could be checked and a new error message generated.

Why should it be fixed?

Normally, I would argue this is an idiosyncrasy of Windows that the user should be responsible for. I'm raising the issue here because setuptools by default gives an incorrect description of the error. This occurred for me after uninstalling Anaconda and installing Python 3.8.3. Anaconda left an AutoRun entry pointing to a script that no longer existed. After removing the entry the project could be built again without issue.

Worth noting that if the AutoRun entry produces an error message that message will be displayed every time cmd is invoked, which is how I was able to deduce the error. However, since I use PowerShell when developing on Windows, I did not see this message. Instead after verifying my build environment was correct, I tracked down the failing command. It appeared to run successfully from PowerShell/cmd but returned a failing status code.

@jaraco
Copy link
Member

jaraco commented Jul 10, 2020

Thanks for the analysis. I agree - if reliance on cmd.exe is required, Setuptools should attempt to detect if cmd.exe execution is itself broken. I like your suggestion for that.

Even better would be to avoid reliance on cmd.exe but that may not be possible.

I welcome PRs to fix the issue. Since this issue is about error reporting in an unusual environment, a test is unnecessary. Just improving the error reporting is good enough.

@cmpotts
Copy link
Author

cmpotts commented Aug 5, 2020

The call of cmd.exe is returning the complete set of environment variables after running vcvarsall.bat. As best I can tell, only path, include, and lib are used in distutils and I can't find anywhere else the monkey patched code is being used. I don't know where to search in prior versions for additional dependencies. Setuptools could potentially use the msvc.py interface to get the appropriate values. path is only used to find cl.exe, "ink.exe, lib.exe, rc.exe, mc.exe, and mt.exe. Duplicating the logic of vcvarsall.bat might be tricky since Microsoft warns in the official documentation that it is potentially version- and machine-specific. I think it is worthwhile to remove the dependence, but it will take more effort and testing than I have time for right now.

As a first measure, I'll make a PR that simply checks if cmd.exe is broken gives the error:

cmd.exe appears broken. Try checking 'AutoRun' registry keys (more info from 'cmd.exe /?')

I don't know of any other reasons for

subprocess.check_call('cmd /u /c exit %errorlevel%')

to fail, but I hesitate to have the error say anything more authoritative. I can combine that check with

subprocess.check_call('cmd /d /u /c exit %errorlevel%')

which causes cmd.exe to ignore any AutoRun registry entries and thus succeeds. If both fail I have no idea what could be happening, so I am unsure if there is any value in doing the additional check versus just leaving it to the user to figure out. Setuptools could add the /d flag to the initial call but who knows how people use it. Anaconda uses it to configure the environment so other people/tools could be doing similar things. I'd hate to figure one use case then cause headaches for other users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants