I'm using the Win32 function GetEnvironmentVariable to retrieve the value of a variable that I just created. I'm running Windows XP and VC++ 2005. If I run the program from within Visual Studio, it can't find the new variable. If I run it from a command-prompt, it does. I restarted VC++ but same result. I even restarted all instances of Visual Studio but still the same problem. It might get resolved if I reboot the PC but I'm curious why this is so. Here's the code that I'm using:
#define BUFSIZE 4096
#define VARNAME TEXT("MY_ENV_NAME")
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR chNewEnv[BUFSIZE];
DWORD dwEnv = ::GetEnvironmentVariable(VARNAME, chNewEnv, BUFSIZE);
if (dwEnv == 0)
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_ENVVAR_NOT_FOUND)
{
printf("Environment variable does not exist.\n");
return -1;
}
}
else
{
printf(chNewEnv);
}
return 0;
}
If I replace MY_ENV_NAME with something that must exist, such as TEMP, it works as expected. Any ideas? Thanks.
Expanding on what Anders and Martin said, environment variables are one thing that is inherited when starting an application. The new program basically gets a copy of the environment at the time it was started. When debugging, your exe is generally started by Visual Studio, so your application will have the same environment as Visual Studio. Visual Studio, is generally started by explorer. If you change the environment variables by going to System Properties->Advanced->Envronment Variables then you will have to restart Visual Studio to see the changes.
If you need to see the envronment variables that Visual Studio is seeing you can (at least for VS2005/2008) go to Tools...->options...->Projects and Solutions->VC++ Project Settings and set Show Environment in Log to 'Yes.' This will print out all the environment variables to the build log (ctrl+click on the link in your build output). You have to build to get this info, but this is the best way I know of seeing the VS environment.
If you really need to change environment variables then run and are having a hard time debugging, you can build your debug exe and have a call to DebugBreak() somewhere near where you want to start debugging from. Then you can set your environment how you want, start the exe from explorer or the command prompt. Then (assuming you have JIT debugging enabled) you will get a popup when your code gets to the DebugBreak() call and you can attach to it with VS and debug normally from there.
Make sure you restart the application before you can read the environment variable. The same happens if you have a console window open and change the environment variables on My Computer, these are not noted in any existing console windows. You need to restart them to get a copy of the new environment variables.
It all depends on how you set the environment variable:
If you ran set MY_ENV_NAME=val in a command prompt, then you have set MY_ENV_NAME for that instance of cmd.exe and any child processes it executes in the future. The environment of existing child processes is not modified.
In this case, exiting the Visual Studio IDE and starting it from the command line (not Explorer) should cause it and its child processes to see the new environment variable.
If you used the System or Users control panel or the setx command to set MY_ENV_NAME, then you have set MY_ENV_NAME persistently, and it will be set for all processes after you reboot your computer. In addition, you may find that some processes, such as Explorer, pick up the environment variable change immediately.
This works by storing the new environment variable in the registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment or HKEY_CURRENT_USER\Environment, depending on whether you chose to set a system environment variable or a per-user environment variable. Existing processes are notified that there was an environment variable change by broadcasting the WM_SETTINGCHANGE message with lParam=="Environment". This message causes them to re-read the persistent environment variables from the registry if they know how. KB104011 has more details.
As a result, if you use the System or Users control panel to set a new environment variable, exiting the Visual Studio IDE and starting it again from Explorer (not a command prompt) should cause it and its child processes to see the new environment variable.
Thanks for all the responses. As I mentioned in my question, I tried restarting everything, short of rebooting the PC. It turns out that because my environment variable was a SYSTEM variable, VS doesn't recognize it without rebooting the PC. When I moved the env variable from SYSTEM to USER and restarted VS, it worked fine.
Related
I am trying to run the unit test cases written in go lang. While executing the test cases, i am getting error like "%1 is not a valid Win32 application".
I have already tried re-installing go, but still the problem persists.
go.exe test dir -run ^(testname)$
fork/exec C:\user\username\AppData\Local\Temp\go-build976684114\packageName.test: %1 is not a valid win32 application.
Error: Tests failed.
The above mentioned folder is not created as well. Not sure, what is happening.
if i set my GOOS to windows it is working
set GOOS=windows
If go env GOOS produces a different operating system than your own, then you can restore it to its default value by unsetting the environment variable GOOS.
The same applies for GOARCH and any plattform-specific variables, such as GOARM.
try restarting your PC!!!
I don't know exactly but this may cause because by temporary files clashing with your go instance
As I often test my binaries inside/outside Microsoft Visual Studio 2017, I want to control the behavior of my code in C/C++ console projects.
One for code for when I run .exe from within Visual Studio in Release mode.
Another when I just click my .exe from Explorer.
What flag or function should I use to know if my .exe was started from inside Visual Studio or not.
What I would like to achive is the:
#if !_RELEASE
system("pause"); // prevents auto shutdown of my .exe in Explorer
// double click
#endif
where _RELEASE is some kind of trait that triggers code in Studio launches,
but not visible in Explorer double click.
What flag or function should I use to know if my process was startded from inside Visual Studio or not.
You shouldn't do such behavior control from inside your program code. That's bad design, and clutters your program code with decisions that should be left on the caller.
I'd recommend if you need different behaviors of your program (e.g. running in background or with visible GUI), this should be controlled with e.g. configuration files or command line parameters.
You can do that for both, Visual Studio settings to specify cmd line parameters, or using a different configuration file, or even a combination of both.
As you seem to insist for a solution of your idea how to fiddle with this in the best way:
You can use the WINAPI functions to iterate through your parent process IDs and check if one of these is matching the "Visual Studio" module.
Here's a Q&A which links to the technique:
How can I reliably check whether one Windows process is the parent of another in C++?
It not exactly solution, but:
Raymond Chen(Microsoft winapi guru*) is most close in spirit to the problem I facing, helping me detect in what mode or circumstances I run my console session.
How can I tell whether my console program was launched from Explorer or from a command prompt?
printf("this process = %d\n", GetCurrentProcessId());
DWORD count = GetConsoleProcessList(nullptr, 0);
if (count == 1) {
printf("I'm the last one!\n");
Sleep(2000);
}
else {
printf("I'm not the last one! %d\n", count);
}
I want to make a console application in C++ and then when the information is displayed, close the console and run in background. Is this possible? Is another way to do that? Python maybe?
You will have to either close the console window while the process is still running, which is system dependent, or start another process, and even though the standard library offers the system function to do that, its argument is a system dependent command line.
So the upshot is: this is system dependent.
In Windows the full-version of Microsoft's Visual Studio IDE has always, as far back as I can remember, used a peculiar approach for this, with two executable files devenv.com and devenv.exe. The former is a console subsystem executable, which by default runs the latter, which is a GUI subsystem executable:
[C:\]
> where devenv
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
[C:\]
> _
The basic idea here is that for historical reasons the command interpreter's search for an executable finds the .com file first, so the command devenv just works, either for starting the IDE or just getting the help text via the /? option.
Yes, this is possible with a small variant:
fork another process. But this is heavily system dependent:
posix/linux allow to simply clone the process;
windows requires new process to be created from an executable. You then have to communicate the state. Its less trivial as explained in this article, in the paragraph on porting fork())
then exit the program (it's the only way to give back control to the console).
On Windows use ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false) to hide the console window. It will still be running in the background and is not visible on the taskbar.
However you will have to run a task manager like Taskmgr.exe to find it and shut it down.
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
cout<<"Some information is displayed.. \n\n";
Sleep(5000);
cout<<"wait.. the console is going to hide and run in background.. \n";
Sleep(5000);
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
while(true) {
// Do your hidden stuff in here
}
return 0;
}
The other answers given here overcomplicate things. The most easy way to close the console window in Windows is to simply detach from it. Once the last user of a console window datached, the console window gets closed.
If you start a program from a CLI (e.g. cmd.exe) then this CLI is also attaches to to the console and thus the console window will not close.
Anyway, detaching from a console is as simple as calling
FreeConsole();
… done!
Also you can attach to a newly created console at any time using AttachConsole, which takes a process ID. Now in a CLI situation the parent will usually be the CLI shell, so you may want to attach to the console of that.
My application downloads updates from a server. After downloading it runs updater.exe (which is set to run with administrative rights) so it can copy the update foo.exe over my application. Since you can't replace the file while it runs the helper application is necessary.
I am making the following system call to run it:
result=_execl(updaterexe,updaterstr,updateFilestr,exeFilestr,exeFilestr,NULL);
The parameters contained:
c:\program files\foo\updater.exe "c:\program files\foo\updater.exe" "c:\downloads\newfoo.exe" ""c:\program files\foo\foo.exe"
Under vista this works as expected.
Under windows 7 it returns error code 22 which is invalid parameter. I have also tried quoting the first parameter to no avail. Suspecting that maybe the old _execl was not supported on windows 7 I tried adjusting all the parameters and calling _wexecl but with no change in behaviour.
Can anyone suggest a correction to the call I'm making or suggest a different system call that will work consistently between versions of windows?
There are plenty of other alternatives, any of which would work from Windows 95 up:
CreateProcess() // Recommended Win32 API
ShellExecute ()
system ()
I am running a Windows 7 system where i want to be able to set a system environment variable and be able to see it in subsequent command prompts that i launch.
When i set the system environment variable using "setx" thins work fine, But given that i want to use the same script code for XP and Windows 7 I cannot do this on XP because XP does not come by default with setx.
So i have to resort to using WMI to set the environment variables:
I use this following code to set the variable :
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objVariable = objWMIService.Get("Win32_Environment").SpawnInstance_
objVariable.Name = "TestKey"
objVariable.UserName = "<System>"
objVariable.VariableValue = "TestValue"
objVariable.Put_
But now, when i launch a new command prompt, the environment variable does not take effect;
However if i restart the system it takes effect; And when i go to MyComputer>Properties>Advanced System Settings> Environment Variables, then i see the "TestKey" value present there; And when i hit "OK" button there and then launch a new command prompt, the "TestKey" value seems to magically appear;
Is there someway I can make the system environment variable to appear on the subsequent command prompts without resorting to clicking on OK at the environment Variables Window (in System Properties) or restarting the machine?
You can install the Windows XP Service Pack 2 Support Tools, which does include setx. We've been using it for a couple years to easily switch on development environments between different levels of Java, Weblogic, JBoss, etc because we support many different version.
Hope this helps!