0

I am trying to write a simple batch file that will go through steps to either activate existing or create new virtual environments. Creating and activating the newly create virtual environment works as expected, but the problem arises when I try to activate an existing virtual environment.

Below is the code that I have so far:

@echo off
echo Do you want to create a new Python Virtual Environment?
set /p answer1= Enter y or n...
if /I "%answer1%"=="y" goto create
goto existing

:create
echo Batch Script to create Python Virtual Environment.
cd C:\Users\NewUser\AppData\Roaming\Python\Python310
set /p input1= Virtual Environment Name: 
echo Creating virtual environment: %input%
python -m venv %input1%
echo Virtual Environment %input1% Successfully Created
echo Do you want to activate %input1%?
set /p answer2= Enter y or n... 
if /I "%answer2%"=="y" goto yes
goto no

:yes
cd %input1%/Scripts
activate.bat
cls

:no
cd C:\Users\NewUser\AppData\Roaming\Python\Python310\Scripts

:existing
echo ...
echo ...
echo Select environment to activate...
cd C:\Users\NewUser\AppData\Roaming\Python\Python310
setlocal EnableDelayedExpansion
for /D %%d in (*) do (
    set show=yes
    for %%a in (Scripts site-packages) do if %%d == %%a set show=no
    if !show! == yes echo %%d
)
set /p input2= Virtual Environment Name: 
echo Activating %input2%
cd %input2%/Scripts
activate.bat
khelwood
  • 55,782
  • 14
  • 81
  • 108
blob
  • 9
  • 1
  • Are you sure `cd C:\Users\...` is not working? When you start from another drive (`D:\`, `E:\`, ...) then you need to use `cd /D C:\Users` in order to go to the C:-drive. – Dominique Nov 02 '22 at 13:48
  • Does the folder exist? `%input2%/Scripts`? Else you'd have to create it first with `mkdir` – tobifasc Nov 02 '22 at 13:52
  • The `cd C:\Users\...` is working in every section of the code except in the `:existing` code block. That is why it is so confusing to me. – blob Nov 02 '22 at 13:54
  • @tobifasc Yes the folder exists. The same code works in the `:yes` code block. – blob Nov 02 '22 at 13:57
  • Does it say `The system cannot find the path specified` or anything else? – tobifasc Nov 02 '22 at 14:09
  • @tobifasc No it gives no error at all. After some additional testing I added `echo %CD%` after the `cd %input2%/Scripts` and it returns the correct directory where the activate.bat file is located. Now that makes me think it is the line `activate.bat` that is not running properly. – blob Nov 02 '22 at 14:18
  • You are supposed to use ```Call activate.bat```, as has been answered on this site on more occasions than I have the capacity to remember. – Compo Nov 02 '22 at 14:42
  • @Compo If that is the case then why doesn't `call activate.bat` work either? https://stackoverflow.com/questions/74290214/why-does-cd-not-work-after-for-loop-in-batch-file I should be able to direct call from this batch file and it should work. I can get this to work with the `start activate.bat` method, but I don't really want to have it open and new instance of cmd. – blob Nov 02 '22 at 14:44
  • @blob, any batch file ran from another batch file, where the line/command after it, is to be run upon its completion, requires the use of `CALL`. That is a simple and extremely well known and documented fact, regardless of your reported issue, which was not the purpose of my comment. – Compo Nov 02 '22 at 14:49
  • Note that `cd c:\somewhere` changes the working directory _for drive c:_, but if a drive other than c: is active, it doesn't have an immediate effect (sorta; since win32, Windows has had a global working-directory concept, but cmd.exe pretends that it doesn't). You can use the `/D` argument to force the drive to be changed too (`cd /d c:\...`). – Charles Duffy Nov 02 '22 at 14:54

1 Answers1

0

For anybody who might stumble upon this problem.

It seems that the direct calling of batch files is sometimes executes and then exits. I believe direct calling exits after completion in certain instances, which would explain why it appeared that the code above wasn't working. I have solved this issue by replacing activate.bat with cmd /k activate.bat.

The following links helped lead me to this conclusion.

Why does cd not work after For Loop in batch file?

https://ss64.com/nt/cmd.html

blob
  • 9
  • 1
  • Everything written here is not correct and does not really answer your question. The real reason is that `setlocal EnableDelayedExpansion` pushes the current directory path on stack. When the processing of a batch file ends like in this case after prcoessing of `activate.bat` finished, there is implicit executed for every outstanding `setlocal` the command `endlocal` by `cmd.exe`. That is explained in usage help of `setlocal` output on running `setlocal /?`. The implicit or explicit execution of `endlocal` results in poping the current working directory path from stack and making it again the – Mofi Nov 02 '22 at 17:35
  • current working directory. That means in your case `cd %input2%/Scripts` results in changing the current working directory (hopefully, not guaranteed with this command) and the implicit executed `endlocal` after processing of `activate.bat` finished results in making the directory before execution of `setlocal EnableDelayedExpansion` the current working directory. I would keep from your batch file just the first two lines and would rewrite everything below as being poor coded and could fail for many reasons. – Mofi Nov 02 '22 at 17:38
  • Read [this answer](https://stackoverflow.com/a/67039507/3074564) for details about the commands __SETLOCAL__ and __ENDLOCAL__. Read [How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?](https://stackoverflow.com/a/49834019/3074564) about fail-safe and secure usage of `set /P` and `choice` which should be used nowadays for a choice prompt. Read [How to call a batch file that is one level up from the current directory?](https://stackoverflow.com/a/24725044/3074564) and of course read the usage help of every used command by running it with `/?`. – Mofi Nov 02 '22 at 17:41