What is the significance of the ProgramData folder in Windows? - windows

What is the importance of the ProgramData folder in Windows?
I have noticed that many installed programs store files in a subdirectory of the ProgramData folder. Is there a specific reason for that?
I have to create an installer for my application. Should I store user-level files under ProgramData or under Users?

The documentation describes the expected use of this folder like this (emphasis mine):
The file system directory that contains application data for all users. A typical path is C:\Documents and Settings\All Users\Application Data. This folder is used for application data that is not user specific. For example, an application can store a spell-check dictionary, a database of clip art, or a log file in the CSIDL_COMMON_APPDATA folder. This information will not roam and is available to anyone using the computer.
Note that this documentation refers to the typical path as per older versions of Windows. In modern versions of Windows it is located in %SystemDrive%\ProgramData.
Rather disappointgly, the above quote is from the now legacy CSIDL documentation. But the documentation for the replacement KNOWNFOLDERID omits the useful descriptions of what you are intended to do with these special folders. So, in order to get to the bottom of questions like this you need to refer to both topics, so far as I can tell.

Related

What are the Python 3 os commands to establish "writable data files and C-Drive paths" for a typical Windows 10 Application

What are the Python 3 os commands to establish "writable data files and C-Drive paths" for a typical Windows 10 Application. There are several parts to this question:
My Python 3 program creates (multiple) data files as part of it's purpose. When my MSI installer installs into /Programs, my Python executable does not have permission to create and write data files. Thus, the first part of my question is: Do I need to change my Python 3 program to create data files in a specific directory (using the os capabilities) and could you give me an example.
The second part of my question is simply: What os command options can assist me in discovering the windows 10 directories of a general Windows 10 PC (e.g. the home path, the AppData path, etc).
Note that I am cx_Freezing to an MSI installer, so everything must be automated for a typical remote install from a cloud (google drive or GitHub) by the MSI installer, so keep that in mind when answering 1 and 2 above.
Attention: Here is the MSI Installer for this program:
New WINDOWS 10 Contact Management Application.
https://drive.google.com/drive/folders/0Bz98wvqqw-1QRUNFcUJLU21yT1k
Thanks in advance for your programming knowledge and experience.
I appreciate your technical assistance and clarification.
I suggest that you avoid storing files and directories directly in the user's profile folder (i.e. the UserProfile environment variable) or home folder (i.e. "%HomeDrive%%HomePath%"). This differs from the common practice in Unix for a home directory (if we're ignoring the XDG base-directory spec), but when in Redmond, do as the Microsofties do.
Create a folder that's uniquely named for the application in one or more of the following locations: the local data folder (per-user), the roaming data folder (per-user), or the program data folder (per-machine). Note that these folders are hidden by default since generally users aren't meant to access them directly.
Use a local data folder for caches. Use a roaming data folder for stateful user data and configuration. Use a program data folder for data and caches that aren't specific to a user. For example, a program like pip could use the program data folder to cache downloaded packages. (In practice, pip caches packages per user, but in principle it could cache per machine.)
If your application uses a program data folder, make sure the folder grants all users permission to add and modify subfolders and files. If you create the folder lazily, you can add the permissions manually. See this answer for an example of how to modify file security.
The environment variables for the local, roaming, and program data folders are, respectively, LocalAppData, AppData and ProgramData. In Windows XP the latter is "%AllUsersProfile%\Application Data", and maybe "Application Data" is localized. Generally you shouldn't use these environment variables in an application.
Since most known/special folders are easily relocatable in Explorer, it's best to ask the shell for the current path by calling SHGetFolderPath or the newer SHGetKnownFolderPath function instead of using environment variables and default locations. You can use ctypes for this if you need to stay within Python's standard library. But it's easier to use PyWin32, which can be pip installed as the "pypiwin32" package.
Here are some Known Folder GUIDs for data, documents, and media files:
User System
ProgramData FOLDERID_ProgramData
Local FOLDERID_LocalAppData
Roaming FOLDERID_RoamingAppData
Desktop FOLDERID_Desktop FOLDERID_PublicDesktop
Documents FOLDERID_Documents FOLDERID_PublicDocuments
Downloads FOLDERID_Downloads FOLDERID_PublicDownloads
Music FOLDERID_Music FOLDERID_PublicMusic
Pictures FOLDERID_Pictures FOLDERID_PublicPictures
Videos FOLDERID_Videos FOLDERID_PublicVideos
Here are the corresponding CSIDL constants, except there isn't one for "Downloads":
User System
ProgramData CSIDL_COMMON_APPDATA
Local CSIDL_LOCAL_APPDATA
Roaming CSIDL_APPDATA
Desktop CSIDL_DESKTOP CSIDL_COMMON_DESKTOPDIRECTORY
Documents CSIDL_PERSONAL CSIDL_COMMON_DOCUMENTS
Music CSIDL_MYMUSIC CSIDL_COMMON_MUSIC
Pictures CSIDL_MYPICTURES CSIDL_COMMON_PICTURES
Videos CSIDL_MYVIDEO CSIDL_COMMON_VIDEO
SHGetKnownFolderPath isn't wrapped by PyWin32. I have another answer that calls it via ctypes. Alternatively, you can use PyWin32 to create a KnownFolderManager instance. For example:
import pythoncom
from win32com.shell import shell
kf_mgr = pythoncom.CoCreateInstance(shell.CLSID_KnownFolderManager, None,
pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IKnownFolderManager)
downloads_path = kf_mgr.GetFolder(shell.FOLDERID_Downloads).GetPath()
Or call the legacy SHGetFolderPath function with a CSIDL constant. For example:
from win32com.shell import shell, shellcon
SHGFP_TYPE_CURRENT = 0
SHGFP_TYPE_DEFAULT = 1
local_data_path = shell.SHGetFolderPath(None, shellcon.CSIDL_LOCAL_APPDATA,
None, SHGFP_TYPE_CURRENT)

Difference between Program Files and ProgramData?

How do I decide which of my application's files go in Program Files (FOLDERID_ProgramFilesX64) and which go in ProgramData? (FOLDERID_ProgramData)? I don't understand what the reason is for splitting up my application's fixed files into these two categories or how I should decide which file goes in what.
For example - image files which my application displays, are they "program" or "data"?
Is there any problem with just putting everything under one or the other?
The application is installed for All Users and has no user-specific configuration files or data.
Program Files is for executables and other static files that came as part of the installation. ProgramData is for user-agnostic data generated during execution such as shared cache, shared databases, shared settings, shared preferences, etc. User-specific data goes in the AppData folder. Note that these are for non-user-visible data. User-visible data belongs in the documents folder (or music, video, custom sibling folder, etc.).
Please see Special Folders and Custom Folders for a detailed explanation. Note that the terminology used varies slightly between the name used in the documentation here, the name of the folder, and the name used by various enumerations used to get these paths from the system.

Default installation location

The default installation location of our applications is c:\Program Files folder. Due to virtulization, this is not a good location to install our applications in 'Program Files' folder in Windows 7. What is the preferred default installation location in Windows 7..
Does microsoft say specify anything on this?
Where can I get more information on this?
Our application can create projects which are kept in c:\Program Files\PolyCd\Projects folder. User can copy these files to other machines to use the project files. We also don't want to run the application as administrator to avoid prompting whenever the application starts. This enables virtualizations. And hence the user won't be able to see the project files he created in c:\Program Files\PolyCd\Projects folder
I have one more question. What is the preferred location of keeping the application specific data such as the project information I mentioned earlier
Ah, thanks for the clarification. Your problem is where you are storing the data. Generally, settings and the likes should be stored in the folder specified by the environment variable AppData. Project data, documents, etc however should generally be stored in the user's "Documents" folder.
'Program Files' or 'Program Files (x86)' for 32-bit software on 64-bit Windows. But you would usually use a variable like $PROGRAMFILES so Windows finds the folder itself.
Since you asked specifically "does Microsoft say anything on this?" let me show you the Windows logo requirements from Microsoft. After you download that document, you can read guidance that includes what folder to install to (Program Files) and where to keep the user's data and settings (ProgramData or AppData). If you follow these guidelines, not only will your application behave as users expect, you will find it easy to get the Windows Logo for your application, which is a shortcut into the partner program. Many of my clients save tends of thousands of dollars on software by being in the partner program, so don't dismiss the value of the logo. But the immediate value to you is clear direction about where to put your app and where to put the user's data.

Where you you store your setting.xml?

For several of our applications we use an application configuration file. It usually just stores some directory paths and a few universal settings. We usually save it in the application directory (C:/Program Files/MyAppName)
One problem we see is users want to edit this (from the application) while logged in as a user that doesn't have access to write to the directory. Our applications are commonly installed and initially configured as an admin, but mostly used by (several different) limited users.
Is there a good way to make the setting.xml file read/write accessible to all users? Or a good place to put it?
C:\Documents and Settings\All Users\Application Data\<Your App> might be a decent place to consider.
Pass CSIDL_COMMON_APPDATA to SHGetSpecialFolderPath to get the writable, shared root data directory. Given that you can create a directory for your company and application.
Application data folder or moving to registry.
How important is localization? If localization isn't a high priority, you can store the files in %allusersprofile%\Application Data\ - that's the appdata folder accessible to all user accounts, and will work regardless of where things are installed, but only on English operating system installs.
If you want to store a file in the local user's directory and give each user their own, you can use %appdata% - that one will be entirely localized. But, each user will need their own copy, so it won't work if you need a common configuration.
If you need it to both be common to all users, and be 100% localized, you need to do a bit more work. I tried to find something like %allusersappdata%, and while I can find references online to that string, I can't get it to work on my own system. The workaround I found was to pull up %appdata% to find the localized text for the words Application Data, then use that to browse to that subfolder under %allusersprofile% - a bit more complicated, but it's the most bulletproof way I can find to do it. Someone please correct me if there's a direct path you can use to get to that folder.
I would try this previous question.
Which says:
System.Environment.SpecialFolder.LocalApplicationData
If you are using .NET

How can you force VB6 to use the DLLs and OCXs from the app directory?

I want to put my dependent files in the app directory.
I seem to remember that you can force VB6 to use the files in the local directory only.
Any hints?
You may also want to try setting up Reg-Free COM for your project. There's a freeware called Unattended Make My Manifest that will do most of the work for you.
Placing component libraries in the EXE folder (with or without .local files) can be deleterious to the hygiene of target machines too.
VB6 programs will register the components here via the self-reg entrypoint behind your back if they are not previously registered. Then if the application is moved or removed you leave the user with a broken reigistration - possibly fatal to subsequently installed applications using some of the same components. This is probably fine though for application specific components, i.e. your own DLL or OCX that will never be needed by another application.
The .local trick was really not meant for use with VB6 programs and if it is used your installer needs to be aware and properly install and register the components if they are not already on the machine. It was meant as a manual hack to get around DLL version compatibility problems on individual machines, not a deployment strategy.
Move up to SxS application and assembly manifests (Reg-Free COM and more) for a better solution. DLL/COM Redirection (.local) was a good try but it has many warts.
Clay Nichol's answer about the search order is not quite correct. That search order only applies to non-COM components. I.e. only some DLLs, and not OCXs. If you register your COM objects, they will be used from the directory where they are registered regardless of what's in the local directory, unless you use reg-free COM or a .local file.
EDIT:
MakeMyManifest is well spoken of as an automatic tool for creating manifests for VB6 projects, haven't tried it myself.
DirectCOM also has fans, again I haven't tried it.
EDIT The MMM website is down. I see here that the author was having trouble with their hosting and has provided another location to get Make My Manifest - download it here.
There is a semi-automatic technique to generate reg-free COM manifests. You can create the manifests with Visual Studio 2008 (you can use a free version like Visual Basic Express Edition). Then make a couple of edits by hand to make the manifests suitable for use from VB6. See this section of this MSDN article for step-by-step instructions - ignore the rest of the article which is about ClickOnce.
It can be sort of confusing because every version of windows, the rules change. Older versions of Windows search the path before the current directory.
A simple solution without manifests:
If your executable file is A.EXE, add a (0-byte, empty) file in the same directory named A.EXE.local -- for older versions of Windows this puts the app directory ahead of the path in the search order.
Found it myself:
Windows does look in the App Directory first:
If SafeDllSearchMode is enabled, the search order is as follows:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
If SafeDllSearchMode is disabled, the search order is as follows:
1. The directory from which the application loaded.
2. The current directory.
3. The system directory. Use the GetSystemDirectory function to get the path of this directory.
4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
according to : http://msdn.microsoft.com/en-us/library/ms682586.aspx
But you can redirect where it looks for .dll's using a Manifest:
http://msdn.microsoft.com/en-us/library/aa375365(VS.85).aspx

Resources