C# Access Denied when trying to Copy and XML file - c#

c# question here. I keep getting access is denied when trying to move an xml file. I know the problem is that it is creating a temporary XML file with no admin privileges which its needs, and I have tried editing the appmanifest with the require admin = true line to no avail. I have also tried setting the permissions outside the program and running visual studio as an admin.
Link to the pastebin code.
https://pastebin.com/M7dRTXHY
I actually got an answer for this using completely different code yesterday but my teacher said I must do it this way. I have spent hours trying to debug this and am losing my mind.
It is a windows 10 phone application as well, not sure if that changes anything.
I realise there is a million and one other questions similar to this but I cannot get anything to work.
This is the exact tutorial I was following taken straight from my course.

Use the StorageFile for the move/copy/delete etc operations:
private async void Grid_Loading(FrameworkElement sender, object args)
{
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
StorageFolder installedLocation = package.InstalledLocation;
StorageFolder targetLocation = ApplicationData.Current.LocalFolder;
var targetFile = await installedLocation.GetFileAsync("Contacts.xml");
await targetFile.MoveAsync(targetLocation);
TARGETFILEPATH = ApplicationData.Current.LocalFolder.Path.ToString() + "\\Contacts.xml";
loadContacts();
}
more on StorageFiles here.

Related

How do you actually use FolderPicker in a UWP to grant IO access

I'm trying to do some generic database stuff with a UWP at a directory the user specifies, but I am having a nightmare with the access rights.
I've read everything I can find about the folder picker and I'm still not getting gifted access. My understanding was once the user picked a folder I could use that folder as I pleased, but it doesn't seem to be the case.
Is it as simple as I can't use Directory commands from a UWP?
Is there any documentation to show how to use FolderPicker Queries?
Am I going to have the same nightmare when I try an SQL connection?
private Windows.Storage.StorageFolder _fileAccess = null;
private async void Btn_Browse_Click(object sender, RoutedEventArgs e)
{
FolderPicker picker = new FolderPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.ComputerFolder
};
picker.FileTypeFilter.Add("*");
_fileAccess = await picker.PickSingleFolderAsync();
if (_fileAccess == null)
{
return;
}
Tbx_Directory.Text = _fileAccess.Path;
StorageApplicationPermissions.FutureAccessList.
AddOrReplace("PickedFolderToken", _fileAccess);
string[] dataBases = Directory.GetFiles(_fileAccess.Path, #"*.db");
foreach (string file in dataBases ?? Enumerable.Empty<string>())
{
LBxV_Databases.Items.Add(file);
}
}
I get the access violation on the Directory use.
You are using FutureAccessList, this is a great choice, but there is a problem with the way you use it.
Here is the way to get the saved StorageFolder:
public async Task<StorageFolder> GetFolderFromAccessList(string tokenName)
{
var folder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(tokenName);
return folder;
}
With the FolderPicker, you can get the StorageFolder object. But saving this object to the FutureAccessList does not allow you to access the folder with the path. You can only get the saved folder object by the Token which save in the FutureAccessList.
Because the UWP application is a sandbox application, when you access the database, I recommend that you save the database file in the application's local directory, such as ApplicationData.LocalFolder. You can't directly access the external file without adding special Capability.
You can find an official application example provided by Microsoft here, which demonstrates how to access files/folders persistently.
Best regards.

UWP StorageFile.CopyAsync() Throwing Error: "Value does not fall within the expected range."

I am trying to overwrite a file with a new version inside of an AppData sub-directory.
Current process is that the user has to select the File to overwrite, and the folder directory it sits in separately so that I can add them to the future access list. Later on the user can select from a collection of images, and it's at that point that it needs to copy and overwrite the destination file. The code I've tried to do this is as follows:
// lets try to copy file to wallpaper default location.
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
var faToken = localSettings.Values["WallpaperStorageFileFAToken"] as string;
var faTokenFolder = localSettings.Values["WallpaperStorageFolderFAToken"] as string;
var destinationFile = await LoadExistingFileSelection(faToken);
var destinationFolder = await LoadExistingFolderSelection(faTokenFolder);
StorageFile movedFile = null;
try
{
movedFile = await imageFile.CopyAsync(destinationFolder, destinationFile.Name, NameCollisionOption.ReplaceExisting);
}
catch (Exception genEx)
{
//
}
The Fa tokens are taken after an FileOpenPicker is used by the User to get the StorageFile and a FolderPicker used to get the StorageFolder for the directory of the destination.
LoadExistingFolderSelection and LoadExistingFileSelection use the following bits of code to get the StorageFiles and StorageFolder
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(faToken);
and
await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(faFolderToken);
The issue is that this line:
imageFile.CopyAsync(destinationFolder, destinationFile.Name, NameCollisionOption.ReplaceExisting);
Throws this error:
"Value does not fall within the expected range."
and that's it, literally nothing else, any thoughts would be great.
Backslashes... Honestly this is one of those moments in you're development career where you just sit there and sigh, because it's just so dumb.
So I could happily retrieve the image I wanted to copy absolutely fine into a StorageFile object, with a path that contained 1 additional backslash that the Windows OS File Explorer wouldn't have batted an eye lid about.
No problem so far, great proceed to then run a copy operation against that, and suddenly you get the
“Value does not fall within the expected range.”
exception, argue-ably one of the least helpful exceptions relating to a problem with a file path that I've seen.
So there you have it, backslashes, really carefully examine the Path property. Hindsight. Normally I would just remove that question because this answer isn't particularly any kind of great revelation. But I figure it can stay as a warning about the fearsome backslash and UWP's Storage API.

Windows 10 UWP App XElement.Save() "Access is denied" exception

I'm writing a Windows 10 UWP App, and I'm hitting a snag. I have a Settings.xml in the root of the app folder that I will use to store the DB connection information, as well as a few ancillary settings. I can load the XML fine, and my function to edit works (I can extract the XML through debug and see the changes). My problem comes when trying to write the edited file. I understand that I don't have direct access to the file system with UWP, however I've tried several different methods I've found online to work within my constraints and still can't find one that works. I always come back with an "Access is denied" error in some form or another. Here is a snippet of what my Save function looks like right now. Any help would be greatly appreciated.
try
{
XElement xmlSettings = XElement.Load(uri: "Settings.xml");
XElement xmlNode;
//Do Stuff (clipped for brevity).
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync(desiredName: "Settings.xml", options: CreationCollisionOption.ReplaceExisting);
Stream stream = await file.OpenStreamForWriteAsync();
xmlSettings.Save(stream);
Error = "";
}
catch (Exception e)
{
Error = "SaveSettings";
}
I added an xml file to my solution (in the root) and copy pasted your code.
It runs the first time, but gets the exception the second time. The reason is that your stream is not closed. You should use it with using:
using (Stream stream = await file.OpenStreamForWriteAsync())
{
xmlSettings.Save(stream);
}
With this change the code worked even the second time.

Access to path denied but the file has no restrictions

I'm new to C# and not an expert at programming in general, but I can't seem to figure out what is causing this problem. I am letting the user pick a XML file and then I want to read it's contents. This is in C# making a universal windows 10 app
This is the error I'm getting:
An exception of type 'System.UnauthorizedAccessException' occurred in
mscorlib.ni.dll but was not handled in user code
Additional information: Access to the path 'C:\temp\file.xml' is
denied.
public async static void pickFile()
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.List;
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".xml");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var t = Task.Run(() => { reset(file.Path); });
}
}
then
private static void reset(string path)
{
String LocationDatafilename = path;
XmlReaderSettings settings = new XmlReaderSettings();
XmlReader reader = XmlReader.Create(LocationDatafilename, settings);
XmlDocument LocationDataXml = new XmlDocument();
LocationDataXml.Load(Globals.reader);
}
When I get to XmlReader.Create that's when I'm getting the error. When I look for the cause, the only thing I find is due to permissions, but that isn't the case. Any help would be appreciated. Thanks.
You need to operate on the StorageFile directly, since your app doesn't have permissions to directly read the user's files. You can either use the WinRT XML API or you can keep using the .NET API and use the stream-based Create function instead of the one that takes a file name.
Run sysinternal's ProcMon app, and at the same time run your application. Find the file in the procmon capture, and in the CreateFile entry, you'll find the creation Disposition. This will give you a clue why the creation failed. Also, select the "User" column to show the user performing the operation.
While Peter Torr's answer is correct and is the way Microsoft wants these things to be done, it is possible to make (at least parts of) the OP's code work as well. The reset method will work, if the path is to one of the directories you have permission for. To get these you can use ApplicationData.Current. This object contains properties like LocalFolder, LocalCacheFolder or (what could be interesting for your use case) SharedFolder.

FileIO with Windows Rt and C#

Wow, is this way more complicated than it needs to be. Can someone explain to me why the following code works:
string stringToWrite = "SomeStuff";
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
var files = await installedLocation.GetFilesAsync();
foreach (Windows.Storage.StorageFile sf in files)
{
if (sf.Name.Equals("log.txt"))
{
await FileIO.AppendTextAsync(sf, stringToWrite);
}
}
And yet the following fails with AccessDenied:
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
var log = await installedLocation.GetFileAsync("log.txt");
await FileIO.AppendTextAsync(log, stringToWrite);
The only difference is looping through the files returned by the GetFilesAsync method vs getting the file by name. By the way, getting the file by name works because if I misspell log.txt in GetFileAsync, I get an exception.
Very confusing....
You should not be using your installed location to write any files. It is supposed to be read-only as per MSDN: File Access/Permissions in Windows Store Apps:
The app's install directory is a read-only location. You can’t gain access to the install directory through the file picker.
You should be using either the Local, Roaming, or Temporary storage locations.
See this link: MSDN: Quickstart Local Application Data

Categories