I have a UWP C# app, with a unit testing project. In these unit test, I want to be able to write to a text file in order to make something like snapshots in Jest.
Directory.GetCurrentDirectory() returns C:\path\to\project\bin\x64\Debug\AppX, so I made a folder in the project directory and am navigating to it, then attempting to create a file there.
[TestMethod]
public void Test()
{
var folder = Path.Combine(Directory.GetCurrentDirectory(), "../../../../Snapshots");
string data = "example data";
string filename = Path.Combine(folder, "Test.snap");
File.WriteAllText(filename, json);
}
However, this test produces a System.UnauthorizedAccessException. I went into the folder in windows and gave Everyone read/write permissions, but that didn't make any difference.
I don't want to have to run Visual Studio as an administrator. Is this possible?
I use Path.GetTempPath() to create temporary directories and files in unit tests that require physical disk access. The unit tests can run from an unknown context/location, so I found using the temp directory as a guaranteed way to create disposable files.
[TestMethod]
public void Test()
{
var folder = Path.Combine(Path.GetTempPath(), "Snapshots");
string data = "example data";
string filename = Path.Combine(folder, "Test.snap");
File.WriteAllText(filename, json);
}
Please have a look at Rob's blog here:
https://blogs.msdn.microsoft.com/wsdevsol/2012/12/04/skip-the-path-stick-to-the-storagefile/
Here is the answer from Rob:
Windows Store apps run sandboxed and have very limited access to the
file system. For the most part, they can directly access only their
install folder and their application data folder. They do not have
permission to access the file system elsewhere (see File access and
permissions for more details).
Access to other locations is available only through a broker process.
This broker process runs with the user’s full privileges, and it can
use these privileges on the app’s behalf for locations the app has
requested via capabilities, locations requested by the user via file
pickers, etc. The StorageItem encapsulates this brokerage procedure so
the app doesn’t need to deal with it directly."
In a UWP app we do not recommend path anymore. There are permission problems so broker is required when access some paths. I'm not familar with Unit Test. But if you are still using UWP function you should consider using StorageFile related API instead.
How about checking if you gave permissions to the right folder?
var folder = Path.Combine(Directory.GetCurrentDirectory(), "../../../../Snapshots");
string data = "example data";
// this variable will contain the actual folder; add a watch
// or bookmark it to check it
var actualPath = Path.GetFullPath(folder);
string filename = Path.Combine(folder, "Test.snap");
File.WriteAllText(filename, data);
Just in case, add the line below too (before File.WriteAllText); perhaps your file already exists as, I don't know, read-only:
File.SetAttributes(filename, FileAttributes.Temporary);
Related
I have a UWP project, and wrote this code:
foreach (var foldertype in (Environment.SpecialFolder[])Enum.GetValues(typeof(Environment.SpecialFolder)))
{
//string d = Environment.CurrentDirectory;
var path = Environment.GetFolderPath(foldertype);
var folder = await StorageFolder.GetFolderFromPathAsync(path);
StorageApplicationPermissions.FutureAccessList.Add(folder, folder.Path);
Debug.WriteLine($"Opened the folder: {folder.DisplayName}");
this.MenuFolderItems.Add(new MenuFolderItem(folder));
}
It is supposed to enumerate all the special folders, and get their folder. However, while debugging, this is what happens:
foldertype = Desktop
path = "C:\\Users\\cuent\\AppData\\Local\\Packages\\402b6149-1adf-4994-abc9-504111b3b972_a5s740xv383r0\\LocalState\\Desktop"
folder = [ERROR] System.IO.FileNotFoundException: 'The system cannot find the file specified. (Exception from HRESULT: 0x80070002)'
I do not know what is happening here, it seems to be appending the path to the installed location of the app. How do I fix this?
Expected output of GetFolderPath() is wherever the Desktop is, not the weird path.
UWP apps are different from desktop applications when accessing the file system. UWP apps are running in the sandbox so there are limitations for UWP apps when trying to access the file system. You could check this document: File access permissions. The document lists all the locations that UWP apps have permission to access.
Back to your scenario, what you need first is a broadFileSystemAccess restricted capability. This capability enables your app could use the StorageFolder.GetFolderFromPathAsync() API with a Path parameter. This is mentioned in the last part of the document I posted above.
Then the second issue is the Environment.GetFolderPath API. It looks like the API will return a Path that points to a local folder inside the app's local folder. But there is no such desktop folder inside the app's local folder so you will get the FileNotFoundException. You might need to set the correct path by yourself like C:\Users\your user name\Desktop. After that, your code should be able to work correctly.
I have been looking for a little while now and am not finding much help via MSDN resources and others.
My predicament is simple: my app needs a base directory to the Downloads folder. I am aware of the DownloadsFolder class however that is not suiting my needs currently.
How do I get the current user's Download folder path in a Windows Universal App?
Use Windows.Storage.UserDataPaths to get the path of user's download folder.
string downloadsPath = UserDataPaths.GetDefault().Downloads;
This method is introduced in build 16232, so clients with RS3(1709) or later will be able to run it.
You shouldn't obtain downloads folder path using LocalFolder, which might result in wrong folder when the user changed the default location for it.
System.Environment.ExpandEnvironmentVariables("%userprofile%/downloads/")
Is that what you need?
string localfolder = ApplicationData.Current.LocalFolder.Path;
var array = localfolder.Split('\\');
var username = array[2];
string downloads = #"C:\Users\" + username + #"\Downloads";
This will result
C:\Users\username\Downloads
The DownloadsFolder for an app now defaults to a folder withing the user's Downloads directory named after the app name (in actual fact the app name folder is simply a link to a folder named after the Package Family Name)
To get the folder name, I used the following hack (vb) to first create a dummy file in the UWP app's DownloadsFolder then using .NET code to get the directory name, and finally deleting the dummy file.
Dim o As StorageFile = Await DownloadsFolder.CreateFileAsync("dummy.txt", CreationCollisionOption.GenerateUniqueName)
Dim dirName Ss String = Path.GetDirectoryName(o.Path)
Await o.DeleteAsync(StorageDeleteOption.PermanentDelete)
I have created simple UWP application, where I simply want to store serialized data to a file, which can be accessed later (when user reopens the application after a while).
The place, where I want to store the file is the current installed location and my serialization code looks like following:
private void SerializeData()
{
XmlSerializer ser = new XmlSerializer(typeof(ObservableCollection<MyTask>));
Windows.Storage.StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
using (var writer = new StreamWriter(File.Open(Path.Combine(installedLocation.Path,sFileName), FileMode.OpenOrCreate)))
{
try
{
ser.Serialize(writer, sData);
}
catch (Exception ex) { }
}
}
This is MyTask model:
public class MyTask:ViewModelBase
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
}
The error that I've been getting is UnauthorizedAccessException. I remember that when I was creating my regular Windows 7 apps under WPF, I had no problem with permission. This is my first UWP app, and therefore I might have forgotten to do something with permissions.
The questions is - is it possible to store simple file in installed directory, or do I need to store all my data files under some Shared location?
Package.InstalledLocation is a place where your app is installed and it's read-only - so you cannot write files there. Use ApplicationData.LocalFolder instead - this is the folder where your app should store local data. For more info how to store (and where), please take a look at MSDN.
Apps can access certain file system locations by default. Apps can also access additional locations through the file picker, or by declaring capabilities.
The locations that all apps can access
When you create a new app, you can access the following file system locations by default:
Application install directory. The folder where your app is installed on the user’s system.
There are two primary ways to access files and folders in your app’s install directory:
You can retrieve a StorageFolder that represents your app's install directory, like this:
Windows.Storage.StorageFolder installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
You can retrieve a file directly from your app's install directory by using an app URI, like this:
using Windows.Storage;
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync("ms-appx:///file.txt");
The app's install directory is a read-only location. You can’t gain access to the install directory through the file picker.
Application data locations. The folders where your app can store data. These folders (local, roaming and temporary) are created when your app is installed.
There are two primary ways to access files and folders from your app’s data locations:
Use ApplicationData properties to retrieve an app data folder.
For example, you can use ApplicationData.LocalFolder to retrieve a StorageFolder that represents your app's local folder like this:
using Windows.Storage;
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
you can retrieve a file directly from your app's local folder by using an app URI, like this:
using Windows.Storage;
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync("ms-appdata:///local/file.txt");
User’s Downloads folder:
using Windows.Storage;
StorageFile newFile = await DownloadsFolder.CreateFileAsync("file.txt");
and much much more ... for further reference goto dev.windows.com and you will get a ton of resources.
I'm trying to save a file that I upload from my page but I'm getting an access denied error:
public void SaveFile(Item item, HttpPostedFileBase file)
{
var dir = string.Format(#"{0}\NSN\{1}", ConfigurationManager.AppSettings["ContentLocation"].ToString(), item.Id.ToString());
if (!System.IO.Directory.Exists(dir))
System.IO.Directory.CreateDirectory(dir);
Array.ForEach(Directory.GetFiles(dir), File.Delete);
file.SaveAs(dir);
}
I'm running this site from the local host from visual studio so no app pool is involved. I've given the Network Service (and Everyone as a test) full control of the folder and it's subfolders. Strange thing is it creates the folder if it needs to and also deletes any files in an existing folder. Only when I call the SaveAs function do I get the error.
You call file.SaveAs with path to directory instead of path to file
Here, give this a try:
string saveAsPath = Path.Combine(dir, file);
file.SaveAs(saveAsPath);
Replace file.SaveAs(dir) with the above.
I'm trying to write an xml file and attach it to an email. It works great if I give it a path to my personal documents folder(i.e. C:\users\myname\Documents\Test.xml), but if I try to change it to something like C:\\Test.xml, I get the following error message:
UnauthorizedAccessException was Unhandled Access to the path
'C:\Test.xml' is denied.
(I can't post pictures apparently)
What would be a good workaround for this?
To get the directory in which the application is launched you could use AppDomain.CurrentDomain.BaseDirectory
On Admin privileges:
Check if the user has launched the application using Run as Administrator.
In this case user should have admin privileges to write..Here is sample code..
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
if (principal.IsInRole(WindowsBuiltInRole.Administrator))
{
//Application is Running as ADMIN
}
You could always write it to you TEMP or LOCAL APP DATA folder..
var temp = Path.GetTempPath();
//e.g: C:\Users\UserName\AppData\Local\Temp\test.xml
var testFilePath = Path.Combine(temp, "test.xml");
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
see How can I get the application's path in a .NET console application?
Program folder is not always allowed to write, use %TEMP% folder instead.