UnauthorizedAccessException when trying to write to text file in C# - c#

I'm trying to write a blank text file which is included within my installer but i'm getting the following error;
System.UnauthorizedAccessException: Access to the path 'C:\Program Files (x86)\Hex Technologies\wamplocation.txt' is denied.
It seems to be the permissions of the file once it's installed through my installer, but how can I set the file to be fully modifiable once the file installed?! Can this be done through C#?!
EDITTED;
wamp_url = openFileDialog1.FileName.ToString();
String EnviromentPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
StreamWriter outfile = new StreamWriter(EnviromentPath + #"\Hex Technologies\wamplocation.txt");
outfile.Write(wamp_url);
outfile.Close();

You should not store your modifyable data files in the Program Files path. Use Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) or Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
The Program Files\... path is protected against modification by normal users on Win7+. It would be a bad idea to try to circumvent that protection.

The likleyhood is the UAC is getting in your way.
Ideally your program shouldn't be writing to this location, it this modification file is to be modified during an install process and nowhere else you need to make sure that you are running elevated.
If this file is to be modified at run time you should consider the use of either %appdata% for user data or %programdata% for program data instead of program files.

Related

How to get the path of the uploaded file within the AppBundle?

We are using Autodesk Forge's Design Automation API. We have an AppBundle ready and we put an .rfa file into the same folder which contains the .dll file. When the AppBundle is unzipped on the Forge servers, which path can lead to our .rfa file? (how can we access it?) Our goal is to place the attached Family file's contents into the input file which is being uploaded with the API, and the result should be a new file which contains the additions from the file which we uploaded within the AppBundle. The process works when testing with Revit locally, but it doesn't work with the API. In the report we are retrieving it's obviously pointing out that the attached file cannot be found:
Autodesk.Revit.Exceptions.FileNotFoundException: T:\Aces\Jobs\ced628d35ecf4412b68c024e2cec098b\something.rfa
On the code side, we are trying to access the .rfa file via this path:
static string currentDir = Environment.CurrentDirectory;
static string path_input = currentDir+#"\something.rfa";
This seemed as a logical path, but as it turned out, it's not..
Is there a way to access the .rfa file inside the uploaded AppBundle?
I took a look at the Restrictions but reading the file from the AppBundle is not mentioned as restricted or not approachable. Am I missing something?
A .NET assembly knows its own path. You can call System.Reflection.Assembly.GetExecutingAssembly().Location within it to find the current path of the dll. You can then compute the path of the .rfa file relative to the folder of the dll and use it / open it. Thus you should be able to open any file you package along with your addin in your appbundle.
You can simply modify your code to:
static string assemblyLocation = Assembly.GetExecutingAssembly().Location;
static string assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
static string path_input = assemblyDirectory+#"\something.rfa";
One thing to note however, is that you only have readonly access to files in appbundle. If your code relies on modifying these during execution, then you may simply copy the source rfa file to the current working folder and then work with the copied file instead.
Also see more details in blog for similar ideas.
We have a blog post on how you can either pass in the app bundle path in the commandLine parameter or find the path via the location of the add-in dll:
https://forge.autodesk.com/blog/store-template-documents-appbundle

Access denied error when writing a text file into the ftproot folder based on file type

I have a c# .Net web page that writes a .csv file into the inetpub\ftproot folder on a Windows 2019 server.
string fileName = #"d:\inetpub\ftproot\competencies.csv";
using (System.IO.TextWriter w = new StreamWriter(fileName, false, Encoding.ASCII))
When I try to create the file, I get an access denied error.
System.UnauthorizedAccessException
HResult=0x80070005
Message=Access to the path 'd:\inetpub\ftproot\competencies.csv' is denied.
I changed the file permissions to "Everyone" with "Full Control" on folder and subfolders to see if permissions were the issue, same error. I changed the connection in IIS basic settings to use an Administrator to see if that would fix it. It didn't. I checked to make sure file didn't already exist. It doesn't.
Finally, I changed the file extension to .txt rather than .csv and it worked! It wrote the text file fine. So, what about the .csv extension would cause the access denied error?
EDIT:
Procmon showed the following:
7:38:46.0371899 AM w3wp.exe 23216 CreateFile D:\inetpub\ftproot\Competencies.csv IS DIRECTORY Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Open No Recall, Attributes: n/a, ShareMode: Read, AllocationSize: 0
Caius was actually very close to the answer! There were no programs that had the file open but somehow in the initial application creation, I created a hidden file with the same name. When I turned on hidden files, I saw it.

UWP StorageFile.OpenAsync Access Denied Issue

I'm running into an issue where I can read from a file in the app install directory but can't write to it.
In the below code, I open a file for reading, do stuff, dispose of my stream pointers, then try to open the file for writing.
//Open file for reading
var SocStorageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///LastSoc.txt"));
var SocInputStream = await SocStorageFile.OpenReadAsync();
var SocClassicStream = SocInputStream.AsStreamForRead();
var SocStream = new StreamReader(SocClassicStream);
<do stuff with file read>
.....
SocInputStream.Dispose();
SocClassicStream.Dispose();
SocStream.Dispose();
//Open record file for writing
var RandomAccessStream = await
SocStorageFile.OpenAsync(FileAccessMode.ReadWrite);
When I try the last line to enable write access, I get:
System.UnauthorizedAccessException: 'Access is denied. (Exception from
HRESULT: 0x80070005 (E_ACCESSDENIED))'
Worried that my Dispose() methods didn't completely clean it up, I tried commenting out all my read accesses. Same error. (Yeah I know, i should use 'using' but I don't think that's the problem here)
I'm not sure why I can't obtain write access. Advice appreciated thanks!
From the path specified in your code, it looks like you are attempting to write to a file that is part of your app's package. This file exists in the installation folder of your app which you only have read only access to.
Simply put, you can read application files in the installation directory but you can't write to files in that directory. This is also true for creating new files in the app installation directory.
Have a look at this doc from Microsoft explaining file access in UWP: https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions
From the doc linked above, the important part is:
The app's install directory is a read-only location. You can't gain access to the install directory through the file picker.
Now, if you are planning on updating this file's content, you should move it to the Application Data folder ( ApplicationData.Current.LocalFolder ). UWP apps are allowed to read and write (and create new files) in that directory.

Set XML file to startup path

I have C# windows application with XML file. After installing the set up file I need to edit the XML file time to time. But my XML file not going to the path where the executable is located.
So that is giving error.
With in a program I'm getting XML path like this.
private string PATH = Path.Combine(Application.StartupPath, "XMLFile1.xml");
Please some one can suggest a way to do.
If you have installed your application on Windows Vista, 7, or 8, it's quite possible that you get security exceptions. Since you haven't told what kind of errors you get I have to ask my crystal ball to think with me.
He thinks that because you are trying to write in a protected folder you get an exception.
He suggest you move the XML to %appdata% or %localappdata%
Use Application.ExecutablePath, the Application.StartupPath property will change if your app is started from desktop shortcut or any other shortcuts.
private string PATH = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "XMLFile1.xml");
You have to include it in project. Here's a helpful link: How to include XML file while creating setup file for windows application
while your application starts copy your XML file to a common folder path, if it is not exist in the path. Do your edit on the xml file in the common folder.
better to use common folder as Local application Data Folder
Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Your application name")

Read the xml files from the installed path

I've created an setup files for my winform. When I run this setup file, the application will be install into the location specified by the user. The installation will also copy some xml files into that location. Right after the user run the application, it will read some settings from the xml files.
What I want to know is, because the location of the xml file is flexible (user specified), how do we know which location to read? How do we specified in the winform coding that it should read from the installed location?
Have you looked at Application.ExecutablePath for the path where your exe was when it ran, so this would be the base directory of your install.
String startingdir = Path.GetDirectoryName(Application.ExecutablePath);
foreach(String Filename in Directory.GetFiles(startingdir,"*.xml")
{
// process
}
Are the XML files copied to the same location as your executable? In that case, you can use Application.ExecutablePath from your WinForms app to get the location of the executable, and from there create the path to your XML files.
I've tried this
reader = new XmlTextReader(Application.StartupPath + "\\MyFile.xml");
And it work fine!!
The way i would suggest is you create a step in your installer where the user can set the location of the file. Put that in the registry . And get your application to read it from registry
If the files are copied to the working folder of your exe, then you can address them with relative paths (no need for absolute paths).
Edit: Here's an example
XmlDocument document = new XmlDocument();
document.Load("filename.xml");
this piece of code will try to read the file filename.xml which is in the same folder that contains your exe file.
XmlDocument document = new XmlDocument();
document.Load("somefolder/filename.xml");
and this one will try to read the file filename.xml from the folder somefolder that is located in the folder that contains your exe

Categories

Resources