How to check if application runs from \program files\ - c#

Is there a reliable method to check if an application is run from somewhere beneath program files?
If the user installs the application to program files on local machine, we need to put writable files somewhere else to avoid virtualization on Vista and Win7. When installed to a network disk, though, we want to keep these files with the installation for shared access among users.
Today we do an string comparison between startup path and CSIDL_PROGRAM_FILES, but something tells me this is a very unreliable method.
Any smart solution out there?
Is there a 'IsRunningFromProtectedFolder( )'-api that I do not know about?
Are there any other folders giving the same problems as program files do?

This is not a terribly good idea, as a user can install it wherever they want to, and then the check might fail. Instead have a checkbox when the user installs the app, deciding if it is installed locally or on a server.

As you I also found problems dealing with UAC folder virtualization.I suggest a workaround, it seems that it should work.
It comes from the assumption that elevated processes always use original copies and not the virtualized ones (CMIIW). Also I assume that you setup processed was executed elevated
The idea is to create a "general" process (non-elevated, legacy), that your main installer should run. This process will create a file name in the user chosen folder with a name and contents that both your programs know (for example, test73819704.bin). If the folder virtualized, this file should appear in the user VirtualStore and SHOULD NOT in the original one (from the point of view and privileges of the installer).
So for chosen C:\Program_Files_But_Not_Necessarily and Process-1 (elevated)
Process-1 ensures there's no file C:\Program_Files_But_Not_Necessarily\test73819704.bin
It launches Process-2 with no elevation
Process-2 creates C:\Program_Files_But_Not_Necessarily\test73819704.bin and checks whether it really exists. If exists it would return with a good return code, otherwise with a "failed" one.
Process-1 waits for Process-2 and analize the result. If good, checks for C:\Program_Files_But_Not_Necessarily\test73819704.bin, if it exists, go for "Bingo! No virtualization occured", if doesn't exist, "Bad, let's find some other storage place". If the code from the Process-2 is "failed" one, show the user some error message.
Unfortunately I could not test it right now, but I guess it should work and there's a logic behind this, with Process-2 you just emulate the behavior of your main program )

We allow our users to install anywhere...
If the user has taken the default, and is installed in Program Files, we make the assumption that we need to write to Documents and Settings/Users. Otherwise, we write our data to a folder under the directory the software is in. This of course can still cause problems, and the install does indeed allow people to choose a different data location if they choose to not go for the default.
On top of that, it's a simple ini file change and a copy to move the data.
On start up we detect if we are in the Program Files directory by comparing the value we obtain from SHGetFolderPath(CSIDL_PROGRAM_FILES) with the start of the path the executable is in.

Related

Auto Updating Winform Application Used Over Remote Desktop

We have an app we wrote deployed onto our terminal servers at work, and keeping it up-to-date is a bit of a pain.
What update mechanisms do people use for app on terminal servers? At the moment we manually copy the new exe + dependencies on witch is just rubbish.
I'm a bit concerned about files being locked by users when trying to update, i cant really just kill the process in case someone is in the middle of doing something. We would like to be able to handle the odd fat client update as well.
Ideally we'd plug something into teamcity/octopus but are open to suggestions
Create a script that copies the exe file to a user specific temp folder, then launches the copied exe. To make the script more efficient, you can have it check the dates of the files. If they are different, then you copy the file over the old one located in the temp folder, else you just launch it.

How would I find an exe's path just by knowing its name?

How Would I find another exe's path by knowing its name in .net?
Would I add name to the OS environment variable?
Would the other application have to 'register' itself somewhere else?
I need App A to start-up App B and call some WCF services on it.
Thanks!
To answer your question: you cannot know the path simply by knowing the name. An exe can reside anywhere on the file system. There can be multiple instances of it that don't know about each other. Multiple exe files that are completely different can have the same name.
You could take one of several approaches to get round this, depending on the exe you are targetting:
get the user to browse for the exe using a normal file browse dialog
search the file system
see what traces the target exe leaves on the system (filesystem, registry, environmental variables, etc) and use those traces to locate the exe
For either of these options you save the result so you don't have to execute it again when your app is run the next time.
Searching the filesystem could take some time, you are not guaranteed to find the exe (depending upon the user level your app is running as) and you may get false positives, especially if the app is called something dumb like setup.exe.
Getting the user to locate the exe the first time you run is possibly the most reliable way of locating it, but then you have to decide what to do if your app runs but the target exe is no longer at the specified location, or the user has chosen the wrong exe.
If you have some control over App B (i.e. it is your product), then you could consider adding some info to a known spot in the registry when App B gets installed, so that App A can locate it easily. You still need to have a plan B though in case the info is missing.
Reference a path to a shortcut of the exe in the config setting, that way if the exe ever moves around the shortcut will still be up-to-date. Try it, make a shortcut to a exe, then cut and paste the exe somewhere else, then double click the shortcut and you'll see it points to the exe's new location thus will not require changes to app A if the location app B changes.
Really, just make the App B a windows service and start it up when needed.
UPDATE:
Another suggestion would be to create a hard link to the AppB's EXE:
mklink /H AppB-link.exe path_to_actual_exe
Or a symbolic link to whole directory where App B resides:
mklink /D virtual_directory path_to_actual_directory

Why can't my C# app create files in Windows 7?

I have a C# app that creates a settings file for itself to store the current state of certain visual elements. This app works just fine on any machine that isn't running Windows 7, but on those machines we get an error that the settings file can't be created because the user doesn't have permission. Now, I could fix this issue by going to each computer, logging in as the administrator and giving the user read and write access on the program folder for the application that we've installed, but there has to be a better way.
It seems like in XP, you got write access on the folders you created by default, but that isn't the case anymore. Is there a setting I need in the setup package to make this work?
The point is that you shouldn't be storing settings files in the program folder. Microsoft have advised against this for a long time, but started making things stricter with Vista IIRC.
Use Environment.SpecialFolders.ApplicationData (etc) to find the most appropriate place to put settings. Or use the .NET settings infrastructure which does this automatically for you.
are you trying to create files in the installation folder? you should be using the user data folder for data and not the installation folders. Use the Environment.SpecialFolders.ApplicationData folder to get a folder you can write to.
You're probably running as an administrator on your non-Windows 7 machine which an write anywhere. Be sure to save any per user instance data in their AppData folder (roaming if it should follow them from computer to computer, or local if its a cache or local to taht machine only). If you need to share settings between users, use the C:\ProgramData folder with the appropriate permissions.
A program shouldn't try to store settings in its installation directory.
Be sure to use the SpecialFolders along with Environment.GetFolderPath to get the right locations needed. You should never hard code paths because they can be different between versions AND languages. (I know in the German version of XP it wasn't Program Files but Programme!)
this app works just fine on any machine that isn't running Windows 7
Wrong! It only works on those machines if you run as administrator. I think you'll find your program is broken on Windows XP as well if you try to run it on just about any business computer rather than a home computer.
Instead, this kind of information needs to go in one of the special Application Data folders.
This is a security flaw in your program because your program is writing information to the program directory (which is, and should be, protected.) If it's a situation of correcting the root cause, consider using the SpecialFolder enumeration or the static members on Application like like CommonAppDataPath to write your information to a more appropriate location.
Assuming the typical approach to writing a file via a path, this is a trivial fix and there's no good "expediency" reason to not correct the root cause. If you're not sure about how to manipulate the path, consider using Path.Combine(). It does it for you.
In general, you shouldn't be writing program data to any folder underneath Program Files (even if you created the folder). You should use the Environment.GetFolderPath(...) to figure out where to put your application specific data. You can pass in one of many enums defined here -- you probably want Environtment.SpecialFolder.CommonApplicationData
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
I do not see how any of this is an actaul answer. I need to be able to write a report and have it saved the users documents folder the same folder I used to read the xml files I am writing the report from.

Allow access permission to write in Program Files of Windows 7

My application throws 'Access denied' errors when writing temporary files in the installation directory where the executable resides. However it works perfectly well in Windows XP. How to provide access rights to Program Files directory in Windows 7?
EDIT:
How to make the program ask the user to elevate rights? (ie run program with full admin rights)
Your program should not write temporary files (or anything else for that matter) to the program directory. Any program should use %TEMP% for temporary files and %APPDATA% for user specific application data. This has been true since Windows 2000/XP so you should change your aplication.
The problem is not Windows 7.
You can ask for appdata folder path:
string dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
or for TEMP path
string dir = Path.GetTempPath()
Your program has to run with Administrative Rights. You can't do this automatically with code, but you can request the user (in code) to elevate the rights of your program while it's running. There's a wiki on how to do this. Alternatively, any program can be run as administrator by right-clicking its icon and clicking "Run as administrator".
However, I wouldn't suggest doing this. It would be better to use something like this:
Environment.GetFolderPath(SpecialFolder.ApplicationData);
to get the AppData Folder path and create a folder there for your app. Then put the temp files there.
Options I can think of:
Run entire app as full admin priv. using UAC
Run a sub-process as full admin for only those things needing access
Write temporary files elsewhere
Add new item in the project: Application Manifest and save it.
Now open this file and look for <requestExecutionLevel>. It must be set to asInvoker.
Change it to highestAvailable. Now on executing your application, a prompt will appear asking for permission. Click yes!
Thats all :) now you can write and read from the system32 or any other file which requires admin right
You can verify your application by sigcheck.
sigcheck.exe -m yourapp.exe
And in the output check for element requestedExecutionLevel.
Another way round it would be to stop UAC then restart it. Create a CMD file with the following code;
Rem Stop UAC
%windir%\System32\reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
rem force reboot
Start ShutDown /R /F /T 30
You'll need to right click on the CMD file and use run as admin. once you have finished what you are doing restart UAC with the following code (no need to use run as admin this time);
%windir%\System32\reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 1 /f
rem force reboot
Start ShutDown /R /F /T 30
The down sides to using this method is have to right click and use run as admin to close UAC down and you have to reboot for it to take effect.
BTW there are several reasons why you would need to write to the forbidden areas...the first two that springs to mind would be to run a batch file to append host to prevent your browser going to dodgy sites or to copy license keys in a silent install.
You can't cause a .Net application to elevate its own rights. It's simply not allowed. The best you can do is to specify elevated rights when you spawn another process. In this case you would have a two-stage application launch.
Stage 1 does nothing but prepare an elevated spawn using the System.Diagnostics.ProcessStartInfo object and the Start() call.
Stage 2 is the application running in an elevated state.
As mentioned above, though, you very rarely want to do this. And you certainly don't want to do it just so you can write temporary files into %programfiles%. Use this method only when you need to perform administrative actions like service start/stop, etc. Write your temporary files into a better place, as indicated in other answers here.
I cannot agree with arguments, that it is better to write all files in other directories, e.g., %APPDATA%, it is only that you cannot avoid it, if you want to avoid running application as administrator on Windows 7.
It would be much cleaner to keep all application specific data (e.g. ini files) in the same folder as the application (or in sub folders) as to speed the data all over the disk (%APPDATA%, registry and who knows where else). This is just Microsoft idea of clean programming. Than of course you need registry cleaner, disk cleaner, temporary file cleaner, ... instead of e+very clean practice - removing the application folder removes all application specific data (exep user data, which is normally somewhere in My Documents or so).
In my programs I would prefer to have ini files in application directory, however, I do not have them there, only because I cannot have them there (on Windows).
I think there is an alternate solution to all these problems....
Make an two level application. As said above...
1) Launcher which will launch another Main App using code such as (VB)
Call ShellExecute(hwnd, "runas", App.Path & "\MainApp.exe", 0, 0, vbNormalFocus)
2) Main App, which is writing to protected areas, ie Program Files folder
I've successfully tried this with windows 7
I'm also developing an app which has online update feature. But it doesn't work in Vista/W7..
I agree with other peoples about Microsoft Policies and Standard Practices.
But my Question is ..
1) How to apply update to an existing application, which probably always remain in Program Files folder.
2) There might be some way to do this, otherwise how goolge updater, antivirus updater or any software updater workes?
I need answer to my questions..... :o
Prof. Rajendra Khope
(MIT, Pune, India)
If you have such a program just install it in C:\, not in Program Files. I had a lot of problems when I was installing Android SDK. My problem got solved by installing it in C:\.
I was looking for answers. I found only one.
None of these work for me. I am not trying to write temporary files, unless this is defined as nonsystem files. Although I am designated the admin on my user profile, with full admin rights indicated in the UAC, I cannot write to program files or windows. This is very irritating.
I try to save an image found online directly to the windows/web/wallpaper folder and it won't let me. Instead, I must save it to my desktop (I REFUSE to navigate to "my documents/pictures/etc" as I refuse to USE such folders, I have my own directory tree thank you) then, from the desktop, cut and paste it to the windows/web/wallpaper folder. And you are telling me I should do that and smile? As an admin user, I SHOULD be able to save directly to its destination folder. My permissions in drive properties/security and in directory properties/security say I can write, but I can't. Not to program files, program files (86) and windows.
How about saving a file I just modified for a game in Program Files (86) (name of game) folder. It won't let me. I open the file to modify it, I can't save it without first either saving it to desktop etc as above, or opening the program which is used for modifying the file first as admin, which means first navigating all the way over to another part of the directory tree where I store those user mod programs, then within the program selecting to open file and navigate again to the file I could have just clicked on to modify in the first place from my projects folder, only to discover that this won't work either! It saves the file, but the file cannot be located. It is there, but invisible. The only solution is to save to desktop as above.
I shouldn't have to do all this as an admin user. However, if I use the true admin account all works fine. But I don't want to use the real admin account. I want to use a user account with admin rights. It says I have admin rights, but I don't.
And, finally, I refuse to store my portables in %appdata%. This is not how I wish to navigate through my directory tree. My personal installations which I use as portables are stored in the directory I create as a navigation preference.
So, here is the tried and true answer I have found:
From what I have seen so far.... unless one uses the real admin account, these permissions just aren't ever really available to any other user with admin privileges in the Windows Vista and Windows 7 OS's. While it was simple to set admin privileges in Windows XP, later versions have taken this away for all but those who can comfortably hack around.
While M$ "best practices" is to not write data into the %programfiles% folder; I sometimes do. I do not think it wise to write temporary files into such a folder; as the TEMP environment variable might e.g. point to a nice, fast, RAM drive.
I do not like to write data into %APPDATA% however. If windows gets so badly messed up that one needs to e.g. wipe it and reinstall totally, perhaps to a different drive, you might lose all your settings for nearly all your programs. I know. I've done it many times. If it is stored in %programfiles%, 1) it doesn't get lost if I e.g. have to re-install Windows on another drive, since a user can simply run the program from its directory, 2) it makes it portable, and 3) keeps programs and their data files together.
I got write access by having my installer, Inno Setup, create an empty file for my INI file, and gave it the users-modify setting in the [Files] section. I can now write it at will.
I am working on a program that saves its data properly to %APPDATA%, but sometimes, there are system-wide settings that affect all users. So in these situations, it HAS to write to the programs installation directory.
And as far as I have read now, it's impossible to temporarily get write access to one directory. You can only run the whole application as administrator (which should be out of the question) or not be able to save that file. (all or nothing)
I guess, I will just write the file to %APPDATA% and launch an external program that copies the file into the installation folder and have THAT program demand admin privileges... dumb idea, but seems to be the only practical solution...
You can add an access to IIS User for folders of Website or Web Application that you want write or rewrite in it.
It would be neater to create a folder named "c:\programs writable\" and put you app below that one. That way a jungle of low c-folders can be avoided.
The underlying trade-off is security versus ease-of-use. If you know what you are doing you want to be god on you own pc. If you must maintain healthy systems for your local anarchistic society, you may want to add some security.

(C#) How do you check if a path is a protected path in Windows that requires elevation to modify?

We have a folder where our app will be potentially reading, writing and creating/deleting files on, and while we can default to a safe location, we allow the user to select a different directory. How can we check if the directory they select is "safe"?
We'd like to not require admin elevation at runtime, and this path will be used for subsequent launches of the app, so it is not enough that we check whether our process is currently able to write to that location because it could be that the app is launched with admin privileges the first time (actually it does when launched by the installer because the installer runs elevated) and if they select a protected location, the next time they try to run the app, they won't have access to the directory. Potentially GB's of Persistent data is stored in this location so asking for a new location and moving the files isn't an ideal solution.
Not only can any folder have any permissions, but they can change at any time, including between when you check a file and when you use it. So really, the only thing you can do is just use a file and handle the exception when it fails.
Since any folder can have permissions set however the administrator sees fit, the only real way to find out is to know what user it will be running as (currently logged in user?) and then do an access check to see if that user has the appropriate access to that directory.
The other advice about permissions changing at anytime is valid, but checking at install time is still better than not checking at all.
Since the first run will be elevated, what you probably want to do is launch a seperate non-elevated process to test the location, and then the original instance can proceed knowing that the location will work unless/until someone else changes the permissions.

Categories