0

The following problem appears only on Windows 10 and not on Windows 7.

I have an app (C++, Visual studio 2017), that requires administrator rights (flag /level='requireAdministrator' on the Linker). Here, I try to get environment variable RESOURCES:

Sample

  int main() {
  const char* buf;
  buf = getenv("RESOURCES");
  if (buf)
      cout << buf << endl;
  else
      cout << 0 << endl;

  system("pause");

  return 0;
}

On Windows 7, I used the following batch file without running it as administrator:

@echo off

set WORKING_DIR=%~dp0
set APP=%WORKING_DIR%\ConsoleApplicationTest.exe
set RESOURCES=%WORKING_DIR%\resources

start "" "%APP%"

As a result - on Windows 10 RESOURCES variable in the c++ code is empty, on the Windows 7 - correct path to the resources. Is the only solution on Windows 10 to launch the batch file as admin always?

  • Here we go again. Everyday. DON'T USE `START`. What is wrong with `set resources=%~dp0\resources` then `%~dp0\consoleapplicationtest.exe` If they contain spaces enclose with quotes. – CatCat Nov 21 '18 at 08:07
  • @CatCat, Thanks for addition, but can you explain, why don't use start? I can't google it. Related to the topic - it doesn't solve a problem. – N. Zolotavin Nov 21 '18 at 09:03
  • Well, you specify very specifically that you require Administrator rights to run it, then you ask if you require administrator rights. Are you not answering your own question?? – Gerhard Nov 21 '18 at 09:22
  • @CatCat Not good are `%~dp0\resources` and `%~dp0\consoleapplicationtest.exe` because of drive and path string referenced with `%~dp0` __always__ ends with a backlash. So concatenating this dynamic path string with an additional ``\`` and a file or folder name results in having finally two backslashes in series in full qualified file/folder name. The Windows kernel functions for file/folder accesses automatically correct this small error, but it is nevertheless better using `%~dp0resources` and `%~dp0consoleapplicationtest.exe` although not so good readable, but being in real 100% right. – Mofi Nov 21 '18 at 09:36
  • @GerhardBarnard, difference is in use cases. When you doubleclicked .exe that requires Administrator rights the popup window is appears. But if you run the batch file you should do some extra actions: right click - then run as Admin. – N. Zolotavin Nov 21 '18 at 09:49
  • So then regardless, you asked if you would need Admin rights permanently, the answer is yes. – Gerhard Nov 21 '18 at 09:54
  • 1
    @N.Zolotavin Please take a look on [What is the reason for '...' is not recognized as an internal or external command, operable program or batch file?](https://stackoverflow.com/a/41461002/3074564) It explains in detail and with an example how Windows manages environment variables. Why does your application depend on environment variables set before by another application. Why do you not pass the resources path as command line argument to your application? Of course that would require changing `int main()` to `int main(int argc, *argv[])` and making use of argument count and argument values. – Mofi Nov 21 '18 at 09:54
  • @N.Zolotavin Why do you use in a C++ application `system("pause");`? The library [stdio](http://www.cplusplus.com/reference/cstdio/) (standard input and output) included in a C++ application with `#include ` has all functions to clear __stdin__ handle, output a string to __stdout__ and wait for one more character from __stdin__. You make already implicit use of this standard library by using `cout` and `cin`. – Mofi Nov 21 '18 at 10:02
  • @N.Zolotavin So you should use them also for waiting on a key pressed by user instead of starting a separate `cmd` process using `ComSpec` environment variable which just outputs a message to __stdout__ and waits for a key press before `cmd` process terminates resulting in continue of your application. – Mofi Nov 21 '18 at 10:05
  • @N.Zolotavin It looks like `resources` is a subdirectory of the directory containing your C++ coded application `ConsoleApplicationTest.exe`. So all you need is the path of your application/executable. Visual C++ offers __GetModuleFileName__ and __GetModuleFileNameEx__ to get full qualified path of an application independent on how this application was started, i.e. what is `argv[0]` as this string can be also just file name of executable without file extension and any path. See for example [Get path of executable](https://stackoverflow.com/questions/1528298/). So batch file is not needed. – Mofi Nov 21 '18 at 10:17
  • @Mofi, Thank you for your suggestions, I think I will look this way. For now it's just example code, main application is much bigger and I can't change this legacy batch-launching of the app. – N. Zolotavin Nov 21 '18 at 10:33

1 Answers1

1

Your problem is that if the cmd instance running the batch file is not elevated, but your executable file requires elevation then the Application Information Service/UAC processes will handle the new process creation and will not transfer the cmd environment block (more here and here).

So, without changing the program code you only have two options: execute the cmd instance as administrator or set the variable as a system environment variable (yes, that requires an elevated process)

MC ND
  • 69,615
  • 8
  • 84
  • 126