Cannot create files on Android with Xamarin - c#

I have a Xamarin-Studio App for Android and I simply want to download files and save them locally. But when I try to create a file in the files folder I get an exception:
File.Create("data/data/com.company.app/files/newFile.png");
gives me:
System.UnauthorizedAccessException
Access to the path 'data/data/com.company.app/files/newFile.png' is denied.
What am I doing wrong?

You should use Environment or IsolatedStorage. For example:
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var filename = Path.Combine(path, "newFile.png");

I am coding Xamarin with VS2013. I had the access denied error for a directory created with the application I am writing. My application creates a directory called /storage/emulated/0/POIApp by concatenating via:
System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "POIApp");
I found that I had to use VS2013 to edit the "properties" of my application (POIApp), i.e., right-click the project icon in the solution explorer; choose properties from the pop-up menu. A new tab appears in the main VS2013 window. On the left there are a few choices, e.g., Application, Android Manifest, Android Options, Build, etc. Choose "Android Manifest". At the bottom of the main panel is a section "required permissions". My problem was solved when I checked "READ_EXTERNAL_STORAGE" and "WRITE_EXTERNAL_STORAGE".

Add the following permission to Android.Manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

I finally realized that File.create() was not the problem. I had code like this:
string tmpFilePath = FilesDir.AbsolutePath.stringByAppendingPath (f.Path);
Java.IO.File tmpFile = new Java.IO.File( tmpFilePath);
tmpFile.Mkdirs ();
Yet, Mkdirs() does not only create all intermediate directories – as I had assumed – but also creates a directory at the file path itself. So the file could not be created because there already was a directory with the same name.
The correct way is:
string tmpFile = FilesDir.AbsolutePath.stringByAppendingPath (f.Path);
Java.IO.File tmpParentFolder = new Java.IO.File(tmpFile).getParentFile();
tmpParentFolder.Mkdirs ();
In my defense, an FileExistsAndIsDirectory exception would have been much more helpful than the UnauthorizedAccessException

Using Mono, I think must be the same as in Xamarin Studio.
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
File.Create(path + "newFile.png");

Related

a file cannot be deleted and copy and move do not work in C# VS2013

I am trying to copy a file in same folder from C# VS2013 on win7.
string myFile = #"C:\Temp\MyFile.txt"
if (File.Exists(myFile))
{
File.Delete(myFile);
}
File.Move(myFileSource, myFile);
I got error:
Additional information: Cannot create a file when that file already exists.
I checked the folder and found that the file "myFile.txt" is still there after deleting.
If i used:
File.Copy(myFileSource, myFile, true);
Error:
Additional information: Access to the path 'C:\Temp\myFile.txt' is denied.
Why ? thanks
Run visual studio as administrator. It's likely a security issue related to UAC.
You may also want to consider writing the file to somewhere where is will work for all such as:
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

Setting image source to application folder

I'm trying to get an image from a certain path, but the path must only be referenced from the application's current folder and not from the Local C: drive.
My reason for this is because the application is going to get published soon and I can't reference the image to the same local location on my current PC, because the application is going to be used on a lot of other PC's and the path would not work on other someone else's computer.
This is the current path that works:
SetDefaultImage(new Binary(File.ReadAllBytes("C:\\Users\\mclaasse\\Desktop\\Haze Update\\Haze\\Haze\\Icons\\user6.jpg")));
And this is how I need it to be:
SetDefaultImage(new Binary(File.ReadAllBytes("Haze\\Icons\\user6.jpg")));
But i'm getting the error:
Could not find a part of the path 'C:\Haze\Icons\user6.jpg'.
Is there a simple work around for getting my path to work?
Not sure if this is exactly what you need, but provided that you have an image file user6.jpg in your Visual Studio project in a project folder named Images, and the Build Action of the image file is set to Resource, you could simply load it from a Resource File Pack URI:
var image = new BitmapImage(new Uri("pack://application:,,,/Images/user6.jpg"));
None of the references worked for me(I don't know why), but this worked:
string directory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string filePath = Path.Combine(directory, "Icons\\user6.jpg");
Then check if the file that you are looking for exists:
if (!File.Exists(filePath))
{
MessageBox.Show("The default image does not exist", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
...
}

ConfigurationManager.OpenMappedExeConfiguration problematic behaviour

I have a very strange problem with my WPF application. I am trying to open a regular config file using this method:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = ConfigurationManager.AppSettings[ PATH_TO_CONFIG ]; //which returns a valid path
s_config = ConfigurationManager.OpenMappedExeConfiguration( fileMap, ConfigurationUserLevel.None );
This works fine when you first run the application - it finds the config file in the directory the app .exe resides. - D:\MyApp\bin\Debug\MyConfigFile.conf But when you open another instance of the application by right-clicking on the running application icon in the toolbar, and from the context menu you choose to open new instance then I get a strange behaviour:
The s_config.FilePath now doesn't find my config file, because it is pointing to "C:\Windows\systems32\myConfigFile.exe.config" And this problem only reproduces when the second application is started like this.
Does anybody has an idea what might be the problem?
We didn't find the solution to the problem so we worked around it. In case the config file is not found, we used
System.Reflection.Assembly.GetExecutingAssembly().Location
to get the full path to the config file and to pass is to fileMap.ExeConfigFilename

Could not find a part of the path 'C:\Program Files (x86)\IIS Express\~\TextFiles\ActiveUsers.txt'

I tried many ways to access a text file in my Visual Studio 2012 Solution from a folder named TextFiles
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"~/TextFiles/ActiveUsers.txt", true))
{
file.WriteLine(model.UserName.ToString());
}
But it kept on throwing the error
Could not find a part of the path 'C:\Program Files (x86)\IIS
Express\~\TextFiles\ActiveUsers.txt'.
Not sure where I made a mistake
You need to use HttpServerUtility.MapPath which will turn the ~/ portion of the path in to the real location it resildes on your hard drive.
So that would change your code to (assuming you are in one of the IIS classes that expose a Server property to it's methods)
var path = Server.MapPath(#"~/TextFiles/ActiveUsers.txt");
using (System.IO.StreamWriter file = new System.IO.StreamWriter(path, true))
{
file.WriteLine(model.UserName.ToString());
}
I ran into a similar issue and ended up using
string sFileName = HttpContext.Current.Server.MapPath(#"~/dirname/readme.txt");
This is an old question but I just ran into this problem myself and wanted to add what I've just discovered, in case it's helpful to anyone else.
If you have UAC turned off but are not running with elevated permissions, and try to write to restricted files (e.g. the "Program Files" folder) you'll get the "could not find a part of the path" error, instead of the (correct) access denied error.
To eliminate the problem, run with elevated permissions as in this solution: https://stackoverflow.com/a/1885543/3838199
~ is not the "user home" or anything else in Windows. You can still set the path as relative to the working directory (where the executable is) by just not specifying a full path.
For .netcore 3.x
You should make use of IWebHostEnvironment using dependency injection.
You can then use it in your code this way
string wwwRootPath = _hostEnvironment.WebRootPath;
string path = Path.Combine(wwwRootPath, $"TextFiles{Path.PathSeparator}ActiveUsers.txt");
Ensure to use PathSeparator otherwise you might face the same error due to the variance in your hosting environment.

UnauthorizedAccessException when downloading a file using the TFS SDK

When I try to download a file from TFS version control SDK to my computer I receive an 'UnauthorizedAccessException' saying Access to the local path I'm trying to download to is denied. I included a stripped down version of the code I am using below.
var projectCollection = GetProjectCollection();
var versionControl = (VersionControlServer)projectCollection.GetService(typeof(VersionControlServer));
versionControl.DownloadFile('$/path to file', 'local path to download to');
Does anyone know how to resolve this issue?
I found the issue.
The second argument in DownloadFile() needs to be the file name it will be downloaded as and not the parent directory it will be placed in. I thought it just needed the directory name.
So instead of what I originally had
versionControl.DownloadFile("$/Readme.txt", "C:\\Temp");
it needs to be
versionControl.DownloadFile("$/Readme.txt", "C:\\Temp\\Readme.txt");
This is because the process does not have rights to the local path. Make sure the local path has the appropriate right set to the user that is running the process.

Categories