How to call devenv.com in powershell? [duplicate] - visual-studio

This question already has answers here:
How to run an EXE file in PowerShell with parameters with spaces and quotes
(21 answers)
Closed 6 years ago.
I just want to run the following two lines.
cd SomeDirectory
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com
Source\MySolution.sln /build Release /project Source\My\Setup\Project.vdproj
If I wrap everything in quotes, nothing seems to happen other than the strings printing to the console.

When quoting a path to a program to run it you need to prepend &:
& "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com" Source\MySolution.sln /build Release /project Source\My\Setup\Project.vdproj"
The reason being that PowerShell has two different parsing modes: command mode and expression mode. But the quoted string will switch to expression mode, thus you explicitly need the call operator, &.
Another thing: You may have to use a full path for the arguments because PowerShell has a different notion of a current directory, that native programs don't share.

Related

How can I use the cl command on PowerShell?

I am unable to use the cl command in PowerShell.
I tried to add the following command to my PowerShell profile to exec vcbuildtools.bat, but PowerShell does not recognize cl command on PowerShell?
&"C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
OS: Windows 10
Just to be clear I'm addressing the asker's issue that cl is not in the PATH even after running this in PowerShell
&"C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
I think this boils down to the issue that batch file can't export variables to PowerShell (also related: this question), as you've found out with vcbuildtools.bat. I think it's because PowerShell invokes a cmd.exe subshell to execute the batch file which changes the environment in the subshell but the changes don't propagate to the parent shell i.e. PowerShell.
Solution 1
One way is to use the fact that subshell inherits the environment from the parent shell. So if you run this in PowerShell, the environment set by the batch file is preserved
cmd.exe /k "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" `& powershell
Take note of `&. The character has to be escaped because it has a special meaning in PowerShell.
Solution 2
The Pscx module has an Import-VisualStudioVars function which imports environment variables for Visual Studio. An example usage is
Import-VisualStudioVars 2015 amd64
if you're using VS/BuildTools 2015 and compiling 64-bit programs. You can use Pop-EnvironmentBlock to revert the changes. See man Import-VisualStudioVars -full for more information.
Alternatively, Pscx also has an Invoke-BatchFile function that retains environment changes by a batch file. An example usage
Invoke-BatchFile "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
See man Invoke-Batchfile -full for more information.
Notes
To download the up-to-date version of Pscx from PowerShell gallery, you will need PowerShellGet which is shipped with PowerShell 5 and is available as a downloadable installer for PowerShell 3 and 4.
For those with PowerShell 1 and 2, older versions of Pscx is available on Codeplex.
You can use the following function to invoke a cmd.exe shell script (batch file) and persist its environment variables:
function Invoke-CmdScript {
param(
[String] $scriptName
)
$cmdLine = """$scriptName"" $args & set"
& $env:SystemRoot\system32\cmd.exe /c $cmdLine |
Select-String '^([^=]*)=(.*)$' | ForEach-Object {
$varName = $_.Matches[0].Groups[1].Value
$varValue = $_.Matches[0].Groups[2].Value
Set-Item Env:$varName $varValue
}
}
Add this function to your PowerShell profile, and run the batch file using the function:
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat"
Fortunately, VS 2019 Community now has a Developer PowerShell for VS 2019 command.
The actual command, if you want to see the properties for the shortcut, is rather verbose.
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -noe -c "&{Import-Module """C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"""; Enter-VsDevShell 14bbfab9}"
Anyway, I am using this and it adds the right cl.exe to my path, but there is an odd message after running it:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\ostream(750): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
.\hey.cpp(4): note: see reference to function template instantiation 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' being compiled
Another option from PowerShell gallery:
posh-vs
Makes Visual Studio command line tools available in PowerShell. Supports Visual Studio 2017 and 2015.
I also encountered the same problem, type cmd.exe and you'll change control to command line.
PowerShell example
If you want to go back to PowerShell, no problem. Just write exit. As simple as it sounds

How to expand command-line arguments when debugging in Visual Studio?

Is there a way to make Visual Studio expand * in file names (and directory names) before invoking the debugger? When I write, e.g., *.txt as the command line arguments, the args[] variable will contain just one entry ("*.txt"), rather than one entry for each matching file. Do I have to write my own code to do this expansion?
If you are invoking visual studio as such:
devenv /debugexe 'myprogram' *.txt
then yes, args[] will contain '*.txt' and you will need to parse and respond to that in your program. (Just the same as if you'd launched the program without the debugger).

Why does quote location matter in running devenv.com from the windows command line?

I've been putting together a batch script (windows command line), and noticed some strange behavior with quoting paths containing spaces.
To reference locations with spaces (eg c:\Program Files), quotes must be used ("c:\Program Files"). For example, calling MSTest.exe, you would use:
"c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe"
If you were going to also reference other programs in that location, you might do something like:
set VSDIR="c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"
%VSDIR%\MSTest.exe
The expanded call to MSTest.exe would look like this:
"c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"\MSTest.exe
This works as expected. The quotes are stripped, and the system loads MSTest.exe. Great. Now, if I do the same thing for devenv.com:
set VSDIR="c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"
%VSDIR%\devenv.com
The system silently does nothing. No output is sent to standard out or error, and the error level remains at zero. Moving the quote after devenv.com loads the process as normal.
Anyone know why I'd see this behavior? Is it because devenv.com runs in real mode, or is it something about the process itself?

bat script only runs first line?

When I copy/paste the lines below into a cmd window it executes without a problem.
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
msbuild proj\projsln /p:Configuration=Debug
proj\proj\bin\Debug\proj.exe my args
However when I save it as DoStuff.bat I get the message below (which is the text from executing vcvars32.bat), then nothing else. It does not build my project and obviously doesn't run the newly built executable.
Why doesn't it and how do I have it run all three commands?
>"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
Use CALL to call another batch file.
Well, there has to be a reason it isn't continuing. Is it that the command is waiting for some input? Thats all that I can think of. Try re-directing the output of the batch file to a log and see what is going on.
Alternatively, split the batch file into separate batch files and put a CALL before each call to the batch file.

Calling batch files with make and making changes persistent

I'm programming with Visual C++ Express on the command line using makefiles (GNU Make).
For this to work, I have to call the Visual Studio batch file vsvars32.bat to set up the environment. This has to be done everytime I open a new cmd.exe, before using make.
When I try to call the batch file from my makefile, it obviously executes the batch file as
an own process, because the environment is the same afterwards.
So my question: is there a way to execute scripts in cmd.exe like the built-in source command of the Linux/Unix bash? Apart from installing bash on Windows, of course.
Edit after posting my own answer:
The above question is not quite right, it should be like this:
Is it possible to call an environment-changing batch file from within a makefile, so that the changed environment persists for the other programs called in the makefile?
The answer to the original question is yes: you can use the built-in call command of cmd.exe. But since call is a built-in command and not a real program, it doesn't work in a makefile, only if you call a batch file from another batch file.
Answer compiled from the previous answers:
I made a batch file called make.bat which contains the following:
call "%VS90COMNTOOLS%vsvars32.bat"
call make.exe %*
This does the job.
But calling an environment-changing batch file from within a makefile, so that the changed environment persists for the other programs called in the makefile, seems to be impossible.
Edit: After overflowing my PATH variable by repeatedly calling vsvars32.bat, I made the following changes:
if not "%VISUALCVARS%" == "TRUE" (
set VISUALCVARS=TRUE
call "%VS90COMNTOOLS%vsvars32.bat"
)
call make.exe %*
use 'Call':
#echo off
pushd.
call "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars3235.bat"
msbuild LinqSupportClassesSDKBuild.csproj /t:rebuild /p:Configuration=Release /nologo /v:q /clp:ErrorsOnly;
popd
this is the cmd file we use to build our linq provider.
At least in my install of Visual Studio (albeit somewhat ancient VS .NET 2003), one of the links in the VS start menu group is to open a cmd.exe instance with the environment already setup. You might find these helpful:
How to Add Visual Studio Command Prompt (VSCP) to your IDE as a tool?
Running the command prompt from visual studio tools menu
Shortcut: Launch Visual Studio Command Prompt from Visual Studio
They are more geared toward launching the command prompt from the IDE, but they do include information on launching it with the appropriate environment as well which you may find helpful for your purposes.
How do you launch your console? If you are just launching 'cmd' then instead, create a shortcut that executes (%comspec% resolves to c:\windows\cmd.exe or whatever is relevent on your system)
%comspec% /k ""C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"" x86
Obviously, change the path to point to the proper installation folder.
More generally, as the above poster pointed out, if a .cmd file needs to process another .cmd file rather than launch it as a seperate process, use the 'call' batch command.
Wrap GNU make in a script (mmake.bat). Put the script in the path somewhere.
The script itself should run the vsvars32.bat and then make, like this
vsvars32.bat
make %*
As far as I remember, invoking a script from another script like this is done within the same shell (similar to Bash "." command).
I have found three solutions to this problem:
1) If the environment variables being set by the batch file are static (that is, they are always the same values), set those values for your entire user profile. Right-click on My Computer, click Properties-->Advanced-->Environment Variables. Add the variables from the batch file to the User Variables or System Variables section (User variables are only visible by you, System variables are visible by all users of that computer).
2) Write a wrapper batch file that calls the environment setup script then calls the Makefile.
3) Instead of using the SET command to set environment variables in the batch file, use the SETX command (requires the Windows Resource Kit). SETX is similar to SET, except it makes its changes to the master environment in the registry and will take effect in all command prompts launched in the future (but not the current one).

Resources