XML saved by application installed in Program Files: where is it? - c#

I've spent the last two hours Googling on this with no results, so…
I am developing an application which uses XML files to save data. These files are supposed to exist in the same directory as the program executable. I use:
string filePath = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\xml\\filename.xml";
It works.
I've created the installation file in Inno Setup. This works as well, copying my XML files exactly where I want them to go.
I open my application directly from the installation folder, from the Start menu icon, from a desktop shortcut, and it works fine.
I make some changes to my program, then I close it and start it again. Everything is fine: all the saved changes are read back from the XML.
But then I open the specified XML file and there are no changes!
I wouldn't bother as at least it's working, but:
When I uninstall the application then install it again to the same directory, changes made to the previously installed file are still there!
I'm very curious to know what's happening.
This only happens if the program is installed to Program Files. If I install it to My Documents, changes are shown in the XML files and after reinstalling it the default settings are restored as expected.
My questions are:
Where are those XML files being stored, and how can I load it if the specified path points to Program Files and they are not there?
Obviously, how do I fix it?
EDIT
Finally found those files in C:\Users[USERNAME]\AppData\Local\VirtualStore\Program Files[APPNAME]

Check what is saved into your local application data folder (it's \Users[USERNAME]\AppData\Local\ for Windows 7).
It looks as if your app didn't have rights to save things in your ProgramFiles folder and saved it where it could, probably in this location:
String appData =
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Also you may try running your application as administrator and check if changes to your xml data still doesn't show.

Cant you print out the value of
System.IO.Path.GetDirectoryName(Application.ExecutablePath)
then you should be able to see where your xml files are stored, if it is a console application just use Console to print if it is WPF print it to a label or something

Related

Image.Save to relative path doesn't save where expected

The documentation doesn't explain the behavior when passing in a path such as "myFile_temp.jpg" but I would assume that it would save the the application directory because this is a relative path, relative to the application we are currently running.
I think that the problem can be solved by prepending the current application directory to my temp file name using
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
Sure there are lots of ways to do it, but this should work.
My issue is I'd like to know why this is happening rather than just throw a patch on it and ship it back out to the users.
Code is WPF, C# project compiled with .NET 4.0 and Visual Studio 2010 and runs on a lot of different machines. Mostly 32-bit XP,while the dev machine is a 64-bit Windows 7.
Can any one explain this behavior and why it's occuring?
Edit
The files will on occasion be saved to the directory the user selected files from to manipulate. They resize them, the program keeps track of the size percent for each of the file paths. When the user is finished they will click done and the program will go through each of the file paths, create a copy, resize the image and then save it with a _temp on the end.
Take note that it doesn't always do it and it when it does it doesn't do it for all the files they touched.
It works as s expected. You just didn't expect valid behavior. Lets assume that your app is placed in c:/superapps/myapp.exe. You opened command line and you're in C:\ which means that this your current working directory.
You can still run your app by ./superapps/myapp but your working directory is still C:\. And this will be working directory of your app in this case, not the directory you placed the binaries.
That is why it may not have permission or save data in some unexpected by you location. You should always think that your app could be run just like any other command like dir. It will be working in the place where user is currently standing (his current working dir) not in the place it's binaries are stored in

File redirection from Program data to AppData\Local\VirtualStore\ProgramData

I am using C# with .net 3.5
I am saving my program data in a file under: C:\Program Data\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 thig 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:\Program Data\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 priviliges instead of getting: "C:\Program Data\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 apparentlly there is some virtual path to the file under program data.
EDIT :
I found out that after deleting the old file in the virtual store, my application is suddenly able to find the correct file. (I didn't make any changes in the file under Program Data.
My question is:
why is it happen.
How can I prevent it from happening
Thanks in advance
Do you actually have to write to the per-system Program Data folder instead of the per-user Application Data folder(s)?
You might want to take a look at Environment.GetFolderPath and the following Environment.SpecialFolders:
Environment.SpecialFolder.ApplicationData - data folder for application data, synchronized onto domain controller if the user profile is roaming
Environment.SpecialFolder.LocalApplicationData - data folder for application data, local and not synchronized (useful for, for instance, caches)
EDIT:
Tested on Windows 7 x64, non-administrator user.
var appData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
var myFolder = Path.Combine(appData, "MyApp");
if(!Directory.Exists(myFolder)) Directory.CreateDirectory(myFolder);
File.WriteAllText(Path.Combine(myFolder, "Test.txt"), "Test.");
This does what is expected, ie. writes into C:\ProgramData\MyApp\Test.txt. As far as I can tell (Administrator mode Command Prompt), there's no UAC virtualization going on either.
Double edit:
I guess what's happened is that at some point an Administrator user has written the files into your ProgramData folder, and as such, UAC file system virtualization kicks in and redirects the non-administrator writes into the VirtualStore.
Does your uninstaller run as Administrator? If it does, you might have to check both the VirtualStore path for the user who initiates the uninstall, and the actual file system path for program data to remove. I'm not sure if there's an official way to do this, though...
I found the reason for the bug.
the application is trying to take ownership on the file and then the other file is created.
I removed that line and now everything works just fine.

How do I configure VS installer to put files in LocalApplicationData

Everything in Visual Studio seems to lead one to putting data files with the application.The app.config goes there, when I create an .XML data file, there is a Copy to Output property that will automatically copy that file to the exe folder. Howerver, it seems that under Vista and Win7 UAC doesn't want the application to be able to write data to any file in the application directory. So I'm changing my evil ways so that I use the LocalApplicationData folder for files I want to read and write. (I just read the app.config so I'm leaving it alone)
I'm using a VS2010 Visual Studio Installer project to create the installer for this app and I can't seem to find a way to target the folder for my .xml file to the LocalApplicationData folder. I can click on the file and see a Folder property but the dialog only has options for Application Folder, User's Desktop and User's Program Menu. Is there some way to do this in the installer or do I have to write code that checks for the file and copies it over from the .exe folder when it doesn't exist? I figure I'm late to this particular party and there must be a canonical way of handling this.
Also, I'm wondering about debugging, is there something similar to the copy if newer functionality in the build process that will now copy this .xml file automatically over to the LocalApplicationData folder whenever I update it?
The Setup project doesn't expose LocalApplicationData in the Special Folders list. You can use it anyway by doing this:
Add a Custom Folder and set the DefaultLocation property to [LocalAppDataFolder]

File.Copy fails when copying a DLL that is not in use

I've built a winforms app (C#) that will take a list of file paths, and copy those files (from a different VS solution) to a new location (In a folder the user specifies) in the same directory structure they currently exist on local file system.
I use the Path class, Directory class etc and everything works wonderfully...except when it reaches a file path that points to a DLL.
The DLLs I am trying to copy are a part of the other solution, and that solution is not currently open.
I have tried restarting computer to make sure visual studio isn't somehow hooking into that DLL even after the solution is closed.
The DLL in question can be copied by regular manual means (i.e. copy and paste shortcut).
So short of creating a batch file in the program, and running xcopy on that DLL path, I don't know of a way to get this to work.
From what I have found from google searches (which isn't much on this particular situation), File.Copy() should work..
Any help would be wonderful, even if it is a link to a duplicate question I may have over looked.
Thanks!
-The error message is: The process cannot access the file [insert file path] because it is being used by another process (The path is definitely correct also)
-Just downloaded and tried to search for the DLL name with Process Explorer.. I also ran a similar exe from command prompt to no avail. It claims nothing is using it. That's why I am utterly baffled by this. Also, I just checked the permissions and everything looks great (i.e. Full Control, owner effective permissions)
-It does not handle open files. It basically build the correct src and dest paths and does a File.Copy() on those. How would I go about handling open files? I'm sure I could figure out if it was open, but what would I do it it were open?
It is not complaining about the file you're trying to copy, it is complaining about the file that you're trying to overwrite with the copy. Lots of candidates for that, virus scanners always get very excited about new DLLs, for example. Or it is loaded into a process, the typical failure mode for trying to implement your own auto-updater.
You can rename the target file to make your copy succeed.
Are you in vista or win7? If so, Check your 'User Account Control Settings'. Sometimes this can interfere with .NET security options and prevent file operations that would otherwise work.
As well as Process Explorer, I would use Process Monitor also from Microsoft so you can see what is happening at the point of failure and allows you to see if anything else is accessing the dll.
Possible culprits are
the program you are running,
your antivirus package
a virus.
If the path it is complaining about is the destination path, then is is possible that the path is too long?
Also, when using Process Explorer, make sure you have enabled the option to show details for all processes and not just your own.
I just ran into this issue as well. I tried copying a .DLL from an FTP server to a local directory (replacing the existing one) and for the life of me I could not get it to work. Keeps giving me an 'Access Denied code: 5' Error.
I then realized that the .DLL on the FTP server was not marked as hidden while the .DLL I was trying to replace was marked as hidden.
Once I changed the local one to also be visible. I had no more issues.
So my solution is:
Make sure both files are visible.
Hope this helps someone

Folder and file not added to User's Application Data folder

Ladies and Gentlemen , I have been stuck with this for a few hours and do not find an answer. I have a Setup project in Visual Studio that creates an installer for my C# application. What I want is to add a folder with an XML file from which my application can read and write to the User's Application Data folder. In the File System Editor window I added the User's Application Data folder. In this folder I added a new folder (renaming it to my app's name) and then place the XML file in there. I also set the AlwaysCreate to true for the folder. The installer should create the folder in C:\Users\UserName\AppData\Local and add the file to it. However, the installer does not create the folder or the XML file my application uses. What am I missing? Is there another way to install a read/write XML file? Thanks in advance!
Ok, I found what the issue was. If a file is added to the User's Application Data folder it is installed on the target computer at C:\Users\Username\AppData\Roaming and not into AppData\Local.
Therefore, I changed my application get the file from Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) instead of Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData).
Hope it helps someone else...

Categories

Resources