I'm trying to create an app on the hololens that creates and writes to a text file to log inputs from the user. Currently, I'm stuck on trying to make the file and access it from the file explorer or the one drive. This is the method I have:
public void createFile()
{
#if WINDOWS_UWP
Task task = new Task(
async () =>
{
testText.text="hi";
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile textFileForWrite = await storageFolder.CreateFileAsync("Myfile.txt");
});
task.Start();
task.Wait();
#endif
}
It's basically what I found here: https://forums.hololens.com/discussion/1862/how-to-deploy-and-read-data-file-with-app, but when I try to run that method, the app on the hololens freezes for a bit then closes. Is there something wrong with the code? Any idea what is going on?
Thanks in advance
In Unity, you can use Application.persistentDataPath: https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html
In Device Portal/File Explorer, it is mapped to LocalAppData/YourApp/LocalState. The code below would write "MyFile.txt" there.
using System.IO;
string path = Path.Combine(Application.persistentDataPath, "MyFile.txt");
using (TextWriter writer = File.CreateText(path))
{
// TODO write text here
}
Related
I'm trying to add multiple files to an already created ZIP file using PickMultipleFilesAsync(). I previously created the ZIP file I want to access in the same code using FilesavePicker.PickSaveFileAsync() method. The app is running on Windows 10 Pro version 1803 in Laptop PC, and I used Visual Studio Community 2017 to create it.
The problem I get is that, after following steps described in the FileOpenPicker MSDN page, I get a System.UnauthorizedAccessException: 'Access to the path 'C:\Users\'User'\Downloads{ZIP file}' is denied.'
I created ZIP file and tried to add new files using this code:
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync.
CachedFileManager.DeferUpdates(file);
try
{
Stream stream = await file.OpenStreamForWriteAsync();
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Update))
{
// This line works fine, file is added
archive.CreateEntryFromFile(path_to_another_file, file_name_in_ZIP);
//....
var dialog = new MessageDialog("Do you want to add more files to ZIP?");
//... (dialog configuration for Yes/No options)
var result = await dialog.ShowAsync();
if(result.Label == "Yes")
{
Debug.WriteLine("Yes option was selected!");
// Include additional files
var openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add("*");
openPicker.SuggestedStartLocation = PickerLocationId.Downloads;
IReadOnlyList<StorageFile> addedFiles = await openPicker.PickMultipleFilesAsync();
if (addedFiles.Count > 0)
{
// Application now has read/write access to the picked file(s)
foreach (StorageFile addedFile in addedFiles)
{
Debug.WriteLine(addedFile.Path); // No problem here
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
}
}
else
{
// Update log file
globalLog += GetTime() + "No additional files";
}
}
}
}
}
I already added <rescap:Capability Name="broadFileSystemAccess"/> to appxmanifest just in case, but as I had access to selected files using FileOpenPicker I think that is not the problem.
As I created the ZIP file within this code I should still have access to it, right? I suspect that FileOpenPicker somehow "closes" access to ZIP file in order to give access to files to be added, or that MessageDialog prevents of accessing the ZIP file I created after I called showAsync().
Is there any other way to achieve what I'm trying?
EDIT: I can not access the file(s) I select using FileOpenPicker, despite I can show file name(s) in Debug console. ZIP file access is OK.
I just found a solution. As stated here, you can use a buffer to stream file contents to ZIP file, just replace:
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
With:
ZipArchiveEntry readmeEntry = archive.CreateEntry(#"additional files/" + addedFile.Name);
byte[] buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(addedFile));
using (Stream entryStream = readmeEntry.Open())
{
await entryStream.WriteAsync(buffer, 0, buffer.Length);
}
That way, files are added and no UnauthorizedAccessException happens. Hope this helps anyone with the same problem!
I need to save app files to plugged SD card. I'm using UWP and Windows 10.
MSDN tells how to do it with Windows Libraries.
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
await myPicsLibrary.RequestAddFolderAsync();
RequestAddFolderAsync() shows file picker, where user can choose folder to add into Pictures. In my case it's a folder, created on SD card.
Is there a way to do this thing without file picker dialog?
I'm trying to do like this:
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
// Get the logical root folder for all external storage devices.
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
// Get the first child folder, which represents the SD card.
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
var folder = await sdCard.CreateFolderAsync("MySDCardFolder");
myPicsLibrary.Folders.Insert(myDocs.Folders.Count+1, folder); // NotImplementedException: 'The method or operation is not implemented.'
myPicsLibrary.Folders.Add(folder); // NotImplementedException: 'The method or operation is not implemented.'
Or maybe I can do the same without using Windows Libraries directly working with SDCard?
Thanks a lot!
EDIT:
In the another hand my question sounds like "How to save files to plugged SD card?"
The StorageLibrary.Folders gets the folders in the current library, it return the IObservableVector of the StorageFolder. When we add the folder into the IObservableVector, it will not change the folder in files system. It will throw the "The method or operation is not implemented." exception.
We should be able to get the name of the folder, and create the folder uses that name. Then we can StorageFile.CopyAsync method to copy the file that in your folder.
For example:
public static async Task CopyFolderAsync(StorageFolder source, StorageFolder destinationContainer, string desiredName = null)
{
StorageFolder destinationFolder = null;
destinationFolder = await destinationContainer.CreateFolderAsync(
desiredName ?? source.Name, CreationCollisionOption.ReplaceExisting);
foreach (var file in await source.GetFilesAsync())
{
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
foreach (var folder in await source.GetFoldersAsync())
{
await CopyFolderAsync(folder, destinationFolder);
}
}
Then we can use the CopyFolderAsync method to copy the folder in the Picture Library.
var myPicsLibrary = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);
var myfolder = myPicsLibrary.Folders[0];
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
var folder = await sdCard.CreateFolderAsync("MySDCardFolder");
await CopyFolderAsync(folder, myfolder);
As I get from your question you need to create a Folder in PicturesLibrary .
You can use the code below to add a folder into PicturesLibrary
await Windows.Storage.KnownFolders.PicturesLibrary.CreateFolderAsync("MySDCardFolder");
if you want to make it on SD Card only Maybe KnownFolders.RemovableDevices Should be helpful . I didn't used KnownFolders.RemovableDevices yet but if you have any issue let me know to test it on my phone directly
I am trying to write a very simple program that reads a txt file when it starts. The file is in "ApplicationData.Current.LocalFolder", as it is supposed to be something I can access without explicitly telling the user. However, after I try to check the existence of and to create the file, I receive a access denied exception at 'file.OpenStreamForReadAsync()' at the 2nd line of the second method.
The StorageFile object is passed from the checking process, so that I think I am able to avoid the situation where two objects try to open the same file. However, the problem persists.
public async Task<StorageFile> checkConfig()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
if (await localFolder.TryGetItemAsync("ifthen.txt") != null)
return await localFolder.GetFileAsync("ifthen.txt");
else
return await localFolder.CreateFileAsync("ifthen.txt");
}
public async void load()
{
Windows.Storage.StorageFile file = await checkConfig();
using (var input = await file.OpenStreamForReadAsync())
using (var dataReader = new StreamReader(input))
{
...
}
}
Furthermore, the problem only occurs in Release Build. Debug Build always works fine, regardless of whether the file exists or not before launching the program.
I want to open a PDF file. If I choose PDF Reader, it works fine.
If I choose Adobe Reader, I have a message : "letter.pdf already exists. Do you want to replace that file ?"
If I click Yes, it works fine.. And if I click No, it works fine too ! So why do I have this message ?
Here's my code. At first, I tried this
// Access local storage
IStorageFolder local = ApplicationData.Current.LocalFolder;
IStorageFile storageFile = await local.CreateFileAsync("letter.pdf", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(document, 0, document.Length);
}
IStorageFile courrier = await local.GetFileAsync("letter.pdf");
// Launch
var success = await Launcher.LaunchFileAsync(courrier);
If the file already exists, I modified my code to delete it to make sure there is only one file to open.
// Access local storage
IStorageFolder local = ApplicationData.Current.LocalFolder;
if (await local.GetFileAsync("letter.pdf") != null)
{
IStorageFile tmp = await local.GetFileAsync("letter.pdf");
await tmp.DeleteAsync(StorageDeleteOption.PermanentDelete);
}
IStorageFile storageFile = await local.CreateFileAsync("letter.pdf", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(document, 0, document.Length);
}
if (storageFile!= null)
{
var success = await Launcher.LaunchFileAsync(storageFile);
return success;
}
So I have this code, but I still have the message, only with Adobe.. Can anyone explain that ?
Thank you very much !
The file is being stored on the phone, not just locally within the app. In order to read it in adobe, it automatically moves a copy into a common folder area.
Because of that, there is already a letters.pdf file there, even if you deleted it from local storage.
You can't (and shouldn't) just assume the user wants to override/delete letters.pdf from their phone, so the pop up needs to stay.
The good news is, whichever option they chose they will still read the file you want them to open
I have a small Project. I want to write a Windows Phone Application which stores a List of Items.
I tried to save the list as a XML document using Linq, that worked fine on a PC but i got a problem with the
XDoc.Save();
On PC I could use a String but on Windows Phone I need a Stream or a XML(Text) Writer but I have no idea how I can do this.
I tried to save a .txt file too, I always get the same exception and have no idea why.
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached)global::System.Diagnostics.Debugger.Break();
};
#endif
}
}
}
If someone knows a way to store the List items. Please Help me.
To save to a file under Windows Phone 8.1 you have to use a StorageFile object. Here is an example:
using System.IO; // needed for OpenStreamForWriteAsync()
....
StorageFile storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myfile.xml", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
//try XDoc.Save(stream);
}
to read a file:
StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(FILENAME);
using (Stream stream = await storageFile.OpenStreamForReadAsync())
{
var XDoc = System.Xml.Linq.XDocument.Load(stream);
}