In Windows is any folder alternative to ProgramData? - windows

I'm writing a desktop app and need a folder which...
Exists in Windows 7 and Vista
Is common to all users (for store config data).
Application can save data on it, without Admin privileges (not like "ProgramData").
is standard (I don't want to create another app specific folder in "C:", the Desktop or other place alike.)
"Program Files" is not an option, of course.
Can you suggest an appropriate folder, or better use the Registry?

The recommended way to do this is to create a folder at install time, dedicated to your application, underneath "ProgramData" (i.e. CSIDL_COMMON_APPDATA/FOLDERID_ProgramData).
As you already know, the CSIDL_COMMON_APPDATA folder is read only for standard users. So your install program needs to give the folder that it creates an ACL that permits the access that you require.
This is the solution that meets all the criteria laid out in your bullet points.
You mention the registry. There is no area of the registry that is shared between all users and yet writeable by standard users. Whilst you can use ACLs to grant more permissive access rights to the registry, it is really not the done thing. Please forget that I even mentioned this possibility!

IF your app is .NET then use CommonApplicationData - you can get the real location by calling GetFolderPath.
EDIT - as per comments:
You need to setup ACL correctly - for sample source code on how to do this see http://www.codeproject.com/Tips/61987/Allow-write-modify-access-to-CommonApplicationData

What about Public User directories? For Example: C:\Users\Public\Libraries or C:\Users\Public\Documents
I've noticed these folder on several of my Windows 7 machines. I'm not sure if it is always there, but might be an option. I was hoping for something like an %appdata% for the Public User, but the closest thing I found was Public\Libraries.
(As a side note, it appears C:\Users\Public\Desktop does require admin to write to.)

what about using %APPDATA%/Company/Product for the directory?

Related

How to prevent file redirection to VirtualStore for read/write files?

I am using C# with .net 2.0
I am saving my program data in a file under: C:\ProgramData\MyProgramName\fileName.xml
After installing and running my application one time I uninstalled it (during uninstallation I'm removing all the files from "program data") and then I reinstall the application, and ran it.
The strange thing is that my application started as if the files in program data existed - means, I had old data in my app even though the data file was deleted.
When running:
File.Exists("C:\ProgramData\MyProgramName\fileName.xml")
I got "true" even though I knew for sure that the file does not exist.
The thing became stranger when I ran the application as admin and then the file didn't exist.
After a research, I found out that when running my application with no admin privileges instead of getting:
C:\ProgramData\MyProgramName\fileName.xml
I get
C:\Users\userName\AppData\Local\VirtualStore\ProgramData\MyProgramName\fileName.xml
and indeed there was a file that existed from the previous installation (that I obviously didn't delete, because I didn't know it existed).
So just guide me how could I stop this when apps running with no admin right.
I do not want to create any file automatically in VirtualStore folder. Please discuss all the possible ways to stop this.
First, ask yourself, do this need to be globally saved for all users?
If it doesn't have to be, save the file in Application Data instead, you can get the path with Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), it should always reliably expand to C:\Users\Username\AppData\Roaming\. Do note that this path is unique for each user though.
If you have to, you're out of luck. There is no reliable way to store application data for all users without admin rights (or UAC) on any Windows post-XP that's not extremely hacky, like storing your data in the Public user (which may or may not be possible, I can't check right now).
An approach to solving this is to use the Environment.SpecialFolder.CommonApplicationData location, but with some very important caveats & setup.
CommonApplicationData is
The directory that serves as a common repository for
application-specific data that is used by all users.
This location is described further here and here.
Important requirements and restrictions are given in another SO answer: https://stackoverflow.com/a/22107884/3195477
which said in part:
The recommended solution is for your installer to create a sub
directory of C:\ProgramData for your shared storage. And that sub
directory must be given a permissive ACL by the installation program.
That is what grants the desired access to all standard users.
Otherwise the program running with standard user permission will still not be all equally able to read/write files in that location for all users.
I found a work around for this issue when transferring a very old win32 app to windows 7 & 10. The program wrote to a database on C:\Program Files... but the OS auto changed the path to virtual store. However the database was required globally. By changing compatablilty mode to Windows 95 or XP SP2 and always running as administrator the database was worked on directly in C:\Program Files\etc.
There are security implications for this and the box was removed from all networks and adapters disabled etc.

How to create user with access only to one given folder?

I need to make "sandbox" to run scripts and applications (PHP, Perl, exe files, Ruby, and so on). But interpreters needs to be accesible to run and only one folder can be accessible to be changed. Also it will be great to allow application to be launched with quotas on hard drive. What do I need to use in this case?
I need solution in C#
You could just setup windows Security to allow this, select the folder you wish the user to access to and set permissions on it (right click, properties, security). The problem with this approach is you need to find all other folders and revoke access to them if you don't want the user using them (ie EVERYONE and USERS access).
Alternativly have a peek at the WinJail package which does as you require. (CHROOT/JAIL implimentation for windows).
You might need to create some sort of virtual drive.
Look at this
creating virtual hard Drive
and a csharp library to play with virtual drives
http://dokan-dev.net/en/
Hope this help
You can set a filesystem filter on all file operations and control them this way, but such wide filter will slowdown operations significantly, especially if checks are done in user mode (via callbacks). You can test our CallbackFilter product, which lets you do the above in C#, but be ready for slowness.

Correct way to design around Windows UAC limitations?

I found out an application I wrote does not work properly under Windows Vista/7 if UAC is enabled at any level, because it writes files to the install directory of the program, defaults to "C:\Program Files\MyProgram." If UAC is disabled (or on any other version of Windows) it works properly - I read that UAC denies applications write access to the Program Files directory by default.
My question is, well, how should I write my application so that it can be used without any "rights" needed at all. I don't want users to have to run it with elevated privileges or as administrator. I just want it to work. Are there certain directories that any app has write access to under UAC where it might be better to write my files? They are mostly config files that are dynamically created/destroyed/updated.
Thanks for you help!
Per-user application specific data should be written in the AppData folder.
You should use SHGetKnownFolderPath with FOLDERID_LocalAppData.
In managed code, you should use System.Environment.GetFolderPath with System.Environment.SpecialFolder.LocalApplicationData.
Yes, there are specific locations. Consider this msdn article as a first reference. It mentions the locations:
CSIDL_APPDATA
CSIDL_LOCAL_APPDATA
CSIDL_COMMON_APPDATA
In native code, the method SHGetKnownFolderPath should prove useful.
In managed code you can use Environment.GetFolderPath(). If you're in a specific application framework, such as windows forms, you can get even easier access via direct properties, such as Application.LocalUserAppDataPath (which is my personal favorite technique). The framework path will include app-specific qualifiers on the path it returns to distinguish between (e.g.) different versions of your app.

Suggested file location that will be editable by all windows users?

I'm building a product that involves
a windows service caching data on the local machine,
user processes reading that data and writing their own data,
the service in turn writing back that data to a server.
Where should I put the data files for this, such that they'll be shared by all users and read/writable? The software will operate in a corporate environment where desktops are sometimes pretty locked-down, so for instance some users won't have write rights to C:\Program Files.
I don't think C:\Documents And Settings\All Users\Application Data\ is a good candidate - I think by default only Admins & Power Users have write access here.
I could use each user's Application Data folder, but this would be a bit of a pain as different people could use each machine ... so it'd be simpler if there was just one shared location.
I'm developing in C# .net 2005, but that's probably not too relevant.
Unfortunately you have no real choice. You must (you really must) call SHGetSpecialFolderLocation to get the path to c:\users\public\AppData (which is the name of the folder you linked above, but on Vista and possibly Windows 7)
Then you MUST create your own app folder therein. And then, you MUST, use the security APIs to modify the ACL of the created folder.
There is NO folder on the system with a default ACL that allows multiple non administrator users to read AND write the same files.
c:\users\public\AppData is the closest. Modifying the ACL of a application folder here seems the best approach. Of course, once one has resorted to ACL modification, the folder really could be created anywhere at all. But that could surprise system administrators and result in weired security holes.

How do you set directory permissions in NSIS?

I'm trying to build a Windows installer using Nullsoft Install System that requires installation by an Administrator. The installer makes a "logs" directory. Since regular users can run this application, that directory needs to be writable by regular users. How do I specify that all users should have permission to have write access to that directory in the NSIS script language?
I admit that this sounds a like a sort of bad idea, but the application is just an internal app used by only a few people on a private network. I just need the log files saved so that I can see why the app is broken if something bad happens. The users can't be made administrator.
Use the AccessControl plugin and then add this to the script, where the "logs" directory is in the install directory.
AccessControl::GrantOnFile "$INSTDIR\logs" "(BU)" "FullAccess"
That gives full access to the folder for all users.
AccessControl::GrantOnFile "<folder>" "(BU)" "FullAccess" didn't work for me on a Windows Server 2008 machine. Instead I had to use this one:
AccessControl::GrantOnFile "<folder>" "(S-1-5-32-545)" "FullAccess"
S-1-5-32-545 is equivalent to "Users" according to Microsoft Support: Well-known security identifiers in Windows operating systems.
Instead of changing the permissions on directories under Program Files, why not put the logs in a location that is writeable by all users.
See the 4.9.7.7 SetShellVarContext section in your NSIS documentation. You can use it with $APPDATA to get the application data folder that is writeable for all users.
It's an old issue now but as suggested by Sören APPDATA directory is a nice way to do what you want, the thing is :
Don't take user's personnal APPDATA but the "All Users" APPDATA dir!
This way anyone will be able to access the log file ;-)
Also, I read somewhere that using (BU) on the GrantOnFile is not working well with some systems (Win 7 x64 if I remember well), maybe you should use the SID "(S-1-5-32-545)" instead (it's the All Users' SID, this value is a constant on each Windows OS)
One way: call the shell, and use cacls or xcacls.
Why not create a log-directory in the user's %APPDATA% directory? Do you really need to put all the logs in the install directory? Why?

Resources