How to set config output to special folder (LocalApplicationData)? - c#

Is there a way to set my app.config for my WCF service so that it outputs to the LocalApplicationData folder without having to hardcode anything?
%LOCALAPPDATA% does not work in XP, and I need to support XP
I have found that shell:Local AppData works, but I am not sure how to put this in an app.config
The next closest I can find is %APPDATA%, but I do not believe this is not the same as LocalApplicationData
Worst case, I can (but would prefer not to) use code to do this (using the SpecialFolders directly), but I am not sure how to set this while keeping the rest of the settings configurable?

You can get it from Environment object.
string path;
path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Edit according to comment:
Now i understand. You can create your own environment variables to use as part of path in your config.
CMD:
set mylocalapplicationdata="somewhere"
or C#:
string name = "mylocalapplicationdata";
string value = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Environment.SetEnvironmentVariable(name, value);
After this you can use %mylocalapplicationdata% like other system variables.
You can set variable for one session (process), user, or machine (for machine you need admin permissions).
More information (MSDN):
http://msdn.microsoft.com/en-us/library/z46c489x.aspx
Alternatively you can use string like this:
%USERPROFILE%\Local Settings\Application Data
but this is for windows xp only.

I don't think there's a way to get the information you want using only built-in environment variables. The information is inconsistent from Windows XP to Windows Vista/7, so I think your best option is to update your config file during installation where you can determine the OS and access other Windows APIs.

Related

Denied acces to a file

I have a code which is similar this:
string file;
using (StreamReader r = new StreamReader("xml.xml"))
{
file = r.ReadToEnd();
}
XElement xml = XElement.Parse(file);
using (XmlWriter w = XmlWriter.Create("xml.xml")) //The point of problem!
{
w.WriteStartDocument();
...;
w.WriteEndDocument();
}
When I try run it like a console application is everything all right. But problems start when I want to use it in an ASP.NET application. At the using line it throws UnauthorizedAccessException exception with a description "access to the path is denied". Why?
You need to check which account your application Pool is using to access your server files/folders, for example, make one code to copy one file to application folder, check all security info, copy and paste on this problem folder, normally use this account "IIS_IURRS" give full control to test only...
If IIS/the web server is configured correctly, an account with a very limited set of permissions is used. As your path points to the application directory, it is very likely that the application pool account is not allowed to write to this location.
If you run the code in a console application, your user's permissions are applied and it is more than likely that you are allowed to write to the output folder of the project as Visual Studio writes the build output there under your account.
I would not recommend to change the application pool account or the permissions of the application folder in the file system - it is a very sensible limitation that limits the amount of trouble an attacker can possibly make.
Therefore I'd recommend to either move the file to a folder that the account can write to without changing permissions or define a special one outside of the application folder hierarchy that the account is given permissions to.
Also keep in mind that multiple users might access the file at the same time, so a database might be a better choice to store the data.

Directory.exists returns false for mapped drive in c# coding

I am using Directory.Exists() in my windows service (that is programmed in C#, 3.5 framework)to check to see whether a particular directory exists in the drive. When I run in local machine it works fine, meaning I am able to access the directory.
But when I deploy the windows service on a Virtual Machine, and start the service, it is not able to find the directory even though the directory exists. The directory is mapped on as
Q: drive, Q:\\temp\\local\\ folder
But the windows services always returns false for the Directory.Exists().
However when I give C:\ drive in place of Q:\ it works, but does not work for a mapped drive. I have tried with the UNC path, and I have made sure the mapped drive have the administrative rights and infact the read, write and execute permission. But it still returns false.
Can anyone please tell me why? And how to resolve?
Make sure the drive is mapped under the same user as the Service is running. If you map the drive as user A, it is not automatically mapped for anyone else too.
Mapped drives are only restored during interactive login which services generally do not perform:
Map a network drive to be used by a service
Short version: You can't do it, use the full UNC path instead.
This is most probably a problem with privileges. Your Windows service is probably running under an account which doesn´t have enough privileges to access the network path.
This is a possible duplicate: Accessing mapped folder from a Windows Service written in C#
Another possible solution is to use impersonation, check it out:
http://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.90).aspx
UPDATE
Came to think of it;
Try changing the identity of the application pool to a user with the same rights as your user.
As #Sriram pointed out the Directory.Exists() method will fail if any error occurs. What sort of exception do you get if you try to access the path?
Eg (for both mapped and UNC in case there is something going on there):
DirectoryInfo diMapped = new DirectoryInfo(#"Q:\temp\local\folder");
DirectoryInfo diUNC = new DirectoryInfo(#"\\servername\fnsw\tmp\126");
Note: Assuming that the white space before 'folder' in your path is a typo?
Steps to troubleshoot
Try accessing the network path manually in "Run" [WindowKey + R]
Try to access your map drive i.e.: M:\
Make sure you are the account owner of the mapping (mapping should be done under your account)
Go to Property and see if "Run As Administrator" is unchecked.
Remove mapping and re-add the mapping.
Make sure available offline (or sync offline) is turned off and folder is available from another computer.
Hope this helps!

Access to the path .... is denied

I have created a .msi by using VS2008 setup project. My application frequently writes some value in a .txt file in the application directory (C:\Program Files\MyApp\MyFile.txt). After insalling it in Win7, it raises an exception "Access to the path .... is denied."
But whenever I run it as administrator, no such exception occurs. Here is my sscce
string FilePath=Application.StartupPath + #"\AppSettings\CurrentUserName.inf";
using (StreamWriter writer=new StreamWriter(FilePath,false))
{
writer.Write(txtLoginName.Text.Trim());
}
MainForm.ProcessLogIn();
this.DialogResult = DialogResult.OK;
I don't know how to solve this problem. Any suggestion?
Move your file out of Program Files directory. In Win7 is readonly for normal users.
You could move the file in the ProgramData directory.
Your installer should create a directory for your application there.
Then inside your code you could retrieve the correct full pathname using these lines of code
string dataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
string appFile = Path.Combine(dataPath, "MyAppDir", "MyFile.txt");
usually (on Win7) this result in a path like this
c:\programdata\MyAppDir\MyFile.txt
but using the SpecialFolder enum you are guaranteed to use a folder available in readwrite to your application not depending on the current operating system.
The only way to solve this problem is to not write to that folder. You are not allowed to write to that folder by convention, unfortunately, older versions of Windows did not hold you to this.
Instead, you can use Environment.SpecialFolder to help you find where you need to go:
// your application data for just that User running the app
var perUserAppData = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
// your application data for ALL users running the app
var allUsersAppData = Environment.GetFolderPath(
Environment.SpecialFolder.CommonApplicationData);
// better!
var path = Path.Combine(perUserAppData, #"MyApp\MyFile.txt");
Basically, Windows 7 is telling you that you're going to have to stop driving on the sidewalks and use the street as was intended.
As a short-term fix, you can use ICACLS to grant write access to the file. Note: NOT the whole directory.
As a longer term fix, you should NOT write to the program directory if you are running as unprivileged users, but instead somewhere like %LOCALAPPDATA% or %APPDATA%.

C# difference between Environment.SpecialFolders and Application folders

What is the difference between the magic paths in these namespaces:
Environment.SpecialFolder.LocalApplicationData
versus
Application.LocalUserAppDataPath
And
Environment.SpecialFolder.ApplicationData
versus
Application.CommonAppDataPath
etc...
They are not the same. The Application version of them is aware of ClickOnce deployment, adjusting the paths accordingly to keep them isolated.
On Windows 7:
Environment.SpecialFolder.LocalApplicationData = C:\Users\username\AppData\Local
Application.LocalUserAppDataPath = C:\Users\username\AppData\Local
Environment.SpecialFolder.ApplicationData = C:\Users\username\AppData\Roaming
Application.CommonAppDataPath = C:\Users\username\AppData\Roaming
Local is only ever stored on the local machine. Roaming is copied to the domain server (when in a domain) and is then loaded back onto other machines in that domain when you log on.
To add to the answer for anyone in the future who lands on this page, for all special folder related questions see the Microsoft's documentation which lists all the folder types:
Environment.SpecialFolder Enum

How to add text file in my project so that it is not visible to user..?

Sir,
I am developing an application in which i am to save some information in text file. During execution, I wish to read/write data from/to the file(.txt file). I dont want the file to be visible to user. Or if it is visible then it must be in programfile folder of the system and user could not delete the data of the file. What should i do? I tried to add the file in Resource file but could not read and write the file. PLease help me to read/write OR provide some other way to implement the same(described above).
Thanks in advance....
Don't use ProgramFiles (installation) folder:
1. File will be visible for user
2. If user won't have admin rights your app will fail on modifying the file.
Windows System folder is also question of rights. I'd advice to use system registry or appdata folder: you can get it Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData). You'll be able to write to that location without admin rights. You should create some special subfolder there (not needed, but would be convinient).
Or in registry case:
writing to registry:
string myEncrStringToSave;
Microsoft.Win32.RegistryKey key;
key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("Software\\Your_Cpecial_Key");
key.SetValue("Software\\Your_Cpecial_Key", myEncrStringToSave);
key.Close();
reading from registry:
Microsoft.Win32.RegistryKey key;
key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("Software\\Your_Cpecial_Key");
object value = key.GetValue("Software\\Your_Cpecial_Key");
if (value!=null)
string myEncryptedString = value.ToString();
key.Close();
Your_Cpecial_Key here is some identifier (like in hashtable) that allows you to get access to your data.
you could use IsolatedStorage, it's not fully hidden but at least not easily discoverable as well.
Put the file in the Windows System folder and use it from there.
You can access it without giving full path by using Environment.SpecialFolder.System.
This way user will have to work hard in order to find the file, but in case he does find you can't really prevent him from changing it as it's the same user running your program.
I am not sure if this might help you.
You may make the text file as an Embedded resource and get the same via
Assembly assm = Assembly.GetExecutingAssembly();
StreamReader aread = new StreamReader(assm.GetManifestResourceStream("Namespace.TextFile1.txt"));
So this is not accessible to the user nor available in the deployed location

Categories

Resources