GetPrivateProfileString and AppData VirtualStore directory - c

I have a program which reads GetPrivateProfileString from a file ".\abcd.ini" - i.e. it will look for the ini file in the current directory.
If it does not find the ini file, it has a default value set in the 3rd parameter to GetPrivateProfileString.
I have an installer which installs the program to c:\program files (x86)\abcd\client directory.
Initially, the installer also installed an abcd.ini file in the same directory with a particular profile string key/value pair. Post that, I changed the installer to not install any ini file.
However, the program continued taking the value from the old ini file which I had shipped even if it didn't exist in that directory.
After doing a system wide search I found a copy of abcd.ini in c:\Users\myusername\AppData\Local\VirtualStore\Program Files (x86)\abcd\Client
Once I deleted this, the program worked correctly (as if there is no ini file).
Googling it seems that the virtualstore is used because myuser does not have full permissions for c:\program files (x86). However, the program itself doesn't write to the ini file, it only reads from it.
Is this actually how it's supposed to be? Why is the ini file copied to AppData & why does the program read from there if there is no local copy?
I am on Windows 10 64 bit.

The diagnostic is that the EXE program does not contain a manifest that declares itself compatible with UAC. Not unusual for the kind of app that still uses GetPrivateProfileString().
Is this actually how it's supposed to be?
Yes, this the way modern versions of Windows (major version >= 6, Vista and up) deal with legacy programs that assume the user always has admin privileges. Redirecting the file access to the VirtualStore directory ensures that the missing access rights to Program Files directory does not cause trouble.
it only reads from it
The OS does not have a time machine to guess whether you might write to the file and did so in a previous session. So it has to check the VirtualStore directory first. To find that .ini file.
It is also important to not assume that it was your program that got the .ini file in that directory. It could have been done by another ancient program, like a text editor. Or a previous version of your program. Or the installer you use.

Yes, because the program would crash, so Windows redirects the program to the VirtualStore directory.

Related

Do you need to be specific about a file location when using os or do you still ned to write (folder/file)?

Let's say I have a file called hello.txt in the folder called coding, and I want to open that in python. I know that if I don't use os, I would have to write open("coding/hello.txt") but if I would write os.open would I still have to specify the folder like ("coding/hello.txt") or can I just write os.open("hello.txt") because I am using os?
"File" and "operating system" can mean a lot of different things, but typically operating systems have the concept of a "current" or "working" directory. Each process has its own current directory, and if you don't specify a directory for a file it uses the current directory.
Do not rely on this. Too many things can change the current directory unexpectedly, and your program will suddenly start using a different file.
Instead always specify the full file path like open("/usr/tmp/coding/hello.txt") or whatever is appropriate for your operating system; it will probably provide environment variables or something for the user's home or temporary directories.
Note that your examples "coding/hello.txt" and "hello.txt" both use the current directory, and are different files.

Where does an output file go?

If you have a program that writes to an output file in C, how do you access/see that output file? For instance, I'm trying to write a program that writes the values from a .ppm image file to another .ppm image file, but I don't know how to access the output file after I've done so. I know that's a pretty general question, but I don't have a block of code I can share just yet.
When creating a file with fopen by only specifying a file name, without specifying a path, then the file will be put in the current working directory of your program.
If you are using an integrated development environment (IDE) to launch your program, then you can probably see and set your program's initial working directory in your IDE. If you are running your program directly from a command-line shell, then the file will be placed in the current working directory of the shell.
On most operating systems, you can also determine your program's current working directory by calling a certain function provided by the operating system. For example, on POSIX-compliant operating systems, such as Linux, you can call getcwd. On Microsoft Windows, you can call _getcwd or GetCurrentDirectory. That way, you should easily be able to find out in which directory your file is being created.

Is the Windows directory a place for temporary files - GetTempPath function

I am creating a small library in C, for Windows only, to help me when I want to create an application.
I came across the topic of creating temp files.
I looked at the GetTempPath function documentation and I saw that it uses the first existing environment variable in this order:
The path specified by the TMP environment variable.
The path specified by the TEMP environment variable.
The path specified by the USERPROFILE environment variable.
The Windows directory.
The question is: if for some reason the first three variables don't exist and the function returns the Windows directory C:\Windows\, is this directory a place to put temporary files?
If it is not then why does the function return it?
EDIT: then where should I put the temporary files?
I don't want throw Access Denied Error or Temp Path Not Found Error
C:\Windows\, is this directory a place to put temporary files?
Definitly it is not. (This assumes C:\Windows\ is the Windows Directory as returned by GetWindowsDirectory ()).
Also on any recent Windows installation normal users won't even be able to write anything to the Windows Directory (e.g. C:\Windows\).
If none of the above three env/ var/s is set let your application create its own directory for temporary files, that is typically located somewhere in the user's home directory.
If your application investigates on this during installation it might consider setting TMP or TEMP to a reasonable directory and create the latter.
This post may not answer the question, but it can explain what is going on and how to fix potential problems:
The MSDN documentation says that GetTempPath evaluates a number of environment variables.
However, the Cygwin documentation says that the environment is stripped away from the process. A Cygwin process will therefore not have the necessary environment variables in its context. Conclusively, GetTempPath cannot catch them and defaults to the Windows directory.
Solution: There is a function which syncronizes the environment of your process with the surrounding Windows environment:
#include <sys/cygwin.h>
...
cygwin_internal (CW_SYNC_WINENV);
See the Cygwin documentation.

Fopen returns null unless explored there?

This is a very odd error.
I am using Visual Studio 2012, and in a C++ project (as a container for a C project), I am loading a file in this way:
const char* fname = "SomeFile.csv";
if(!(fp = fopen(fname, "r")))
{
printf("Error! Could not open %s!\n",fname);
return;
}
The CSV is in the same folder as the .EXE, and that is the intention for this program.
1. When I run it in debug, it fails to read the CSV.
2. When I put in the full pathname to the file, it works correctly and loads the CSV.
3. When I go to the output folder in Windows Explorer, and run the .exe, it correctly loads the CSV.
4. Now here is the weird part. When I go to another folder (anywhere else), and I then paste in the full path including the .exe into Windows Explorer, it starts up the program, as it should, but it fails to read the CSV.
As a caveat, if I have the folder loaded in explorer, but run it in the VS2012 debugger, it also fails to load the CSV.
What is going on here? Why would it only find it if I am running it while the window is open in explorer?
fopen, open, etc. will, given a bare filename with no path components, attempt to open the named file in the "current directory". Given a filename without a filesystem root it will attempt to open the file in a directory relative to the current directory. Only when given an absolute (full) path will it look exactly where you've told it.
In a command-line based system, the current directory is pretty obvious - it's the directory you are in when you issue the command.
In a Graphical User Interface the notion of a current directory is a bit more mushy:
Navigate in Windows explorer to the program (let's say WORD.EXE) and double click it - the current directory is likely to be the directory where the program is - the place to which you navigated (but there's no standard that says this has to be the case)
Navigate to your documents for your project and double click a Word document, which launches WORD.EXE automatically - what is the current directory? It's likely to be where the document is.
Launch WORD.EXE from the Start menu - what the heck is the current directory now?
Launch your program from the debugger - now what is the current directory?
This last point is why you have to tell the IDE / debugger what to use as the current directory when it launches your program.
The fileOpenDialog doesn't exactly "default" to the current directory - it open to where you last opened it, without changing the current directory for the program - when you pick a file it then passes the full path of that file to the program.

read from a file while installation in nsis but do no copy it on the destination pc

I want to display the version on the installation dialog pages of nsis, by reading the version from a text file, but i have to copy this on the destination pc where the executable is run, but i want that the text file is not copied on the user's pc but is only read from,
that is,
i want to include this file into the exe, and read text from it to display on the nsis dialog pages, but not copy it anywhere on the pc wherever the exe is run?
is this possible? or is there any other way of doing this?
In general, you can use $PLUGINSDIR constant. It is de-facto temporary directory on target system and you can put there something and use. Following code will copy the file into the temporary directory on the target machine, but whole directory will be deleted after the installation completion. (InitPluginsDir is needed somewhere before)
InitPluginsDir
File /oname=$PLUGINSDIR\blah.txt "..\myfile.txt"
But in your case, it could be better to solve it in some other way. You can define some constant containing version number and use it in the code, can't you? The !define command could be in generated file so you can automate it...

Resources