I want to parse a folder that the user can choose.
But if I understand, absolute paths are not allowed in UWP because the disks are not the same following the media (xbox, windows phone, windows desktop, ...) ?
So, I have a class called Parser that can parse the path that the user picks but now, only the current folder can be parsed.
This doesn't work :
Parser parser = new Parser(#"C:\a\b\c");
parser.createTreeView(tree);
Help me please. Thank you in advance.
EDIT : This is my Parser class =>
public TreeViewItem Parse(DirectoryInfo directoryInfo)
{
try
{
var directoryNode = new TreeViewItem { Header = directoryInfo.Name };
Convention convention = new Convention();
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Items.Add(Parse(directory));
System.Diagnostics.Debug.WriteLine("test : " + directory.Name);
}
foreach (var file in directoryInfo.GetFiles())
{
if (file.Name.Contains(EConvention.INSTALL))
{
listFiles.Add(file.FullName);
}
TreeViewItem item = new TreeViewItem
{
Header = Path.GetFileNameWithoutExtension(file.FullName),
Tag = file.FullName
};
directoryNode.Items.Add(item);
}
return directoryNode;
}
catch (System.UnauthorizedAccessException e)
{
//MessageDialog dialog = new MessageDialog(""+e.Message);
dialogAsync(e.Message);
return new TreeViewItem();
}
}
public void CreateTreeView(TreeView tree)
{
DirectoryInfo dir = new DirectoryInfo(pathToParse);
System.Diagnostics.Debug.WriteLine("dir exists ? "+dir.Exists);
if (dir.Exists)
{
System.Diagnostics.Debug.WriteLine("dir existe");
TreeViewItem root = new TreeViewItem() { Header = dir.Name };
root.Tag = dir;
tree.Items.Add(Parse(dir));
}
}
UWP apps do not have permission to access all files on the device. Apps can access certain file system locations by default. Apps can also access additional locations through the file picker, or by declaring capabilities. For more info, please see File access permissions
Although, we can use DirectoryInfo in UWP apps, but it can only work with the folders that UWP apps can access by default such as the install directory and local folder etc. Most types in the System.IO namespaces for UWP apps have the similar limitation. While dealing with files or folders in UWP, one important rule is Skip the path: stick to the StorageFile.
You can use a FolderPicker to let the user choose a folder and then add it to your app's FutureAccessList or MostRecentlyUsedList to keep track of it. You can learn more about using these lists in How to track recently-used files and folders. After this, you will be able to retrieve the StorageFolder from FutureAccessList or MostRecentlyUsedList whenever you want to use it.
Once you have the StorageFolder, you can then use GetFilesAsync() or GetFoldersAsync() method in your Parse instead of DirectoryInfo.GetDirectories or DirectoryInfo.GetFiles method.
Related
I'm writing a simple desktop application to copy files from one PC to another. Having trouble with the Windows 10 reparse points, specifically My Music. I thought was going to get away with one simple line of code:
ZipFile.CreateFromDirectory(documentsFolder, docSavePath + #"\Documents.zip", CompressionLevel.Optimal, false);
But not so, it crashes on the My Music folder. I've also tried a bunch of different ways of doing this, all with the same result - access denied. Can copying and/or zipping the Documents folder really be this hard? I doubt it, I'm just missing something. I tried elevating privileges and that didn't work, either. Anyone have an example of how to do this?
I was able figure out how to check for the ReparsePoint attribute, which was relatively easy, but then had to piece together how to loop through all the files and add them to the ZipArchive. The credit for the RecurseDirectory goes to this answer.
Then I added in what I learned about the reparse file attributes.
private void documentBackup(string docSavePath)
{
if (File.Exists(docSavePath + #"\Documents.zip")) File.Delete(docSavePath + #"\Documents.zip");
using (ZipArchive docZip = ZipFile.Open(docSavePath + "\\Documents.zip", ZipArchiveMode.Create))
{
foreach (FileInfo goodFile in RecurseDirectory(documentsFolder))
{
var destination = Path.Combine(goodFile.DirectoryName, goodFile.Name).Substring(documentsFolder.ToString().Length + 1);
docZip.CreateEntryFromFile(Path.Combine(goodFile.Directory.ToString(), goodFile.Name), destination);
}
}
}
public IEnumerable<FileInfo> RecurseDirectory(string path, List<FileInfo> currentData = null)
{
if (currentData == null)
currentData = new List<FileInfo>();
var directory = new DirectoryInfo(path);
foreach (var file in directory.GetFiles())
currentData.Add(file);
foreach (var d in directory.GetDirectories())
{
if ((d.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
{
continue;
}
else
{
RecurseDirectory(d.FullName, currentData);
}
}
return currentData;
}
It takes longer than I'd like to run - but after looking at this dang problem for days I'm just happy it works!
I have a UWP application which perform to capture and process images from a camera. This project leverage Microsoft Cognitive Services Face Recognition API and I'm exploring the application's existing functionality for awhile now. My goal is that when the image of a person is identified by the camera (through Face Recognition API service), I want to show the associated image of that person.
With that, the images are captured and stored in a local directory of my machine. I want to retrieve the image file and render it on the screen once the person is identified.
The code below shows the async Task method ProcessCameraCapture
private async Task ProcessCameraCapture(ImageAnalyzer e)
{
if (e == null)
{
this.UpdateUIForNoFacesDetected();
this.isProcessingPhoto = false;
return;
}
DateTime start = DateTime.Now;
await e.DetectFacesAsync();
if (e.DetectedFaces.Any())
{
string names;
await e.IdentifyFacesAsync();
this.greetingTextBlock.Text = this.GetGreettingFromFaces(e, out names);
if (e.IdentifiedPersons.Any())
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Symbol = Symbol.Comment;
GetSavedFilePhoto(names);
}
else
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Symbol = Symbol.View;
}
}
else
{
this.UpdateUIForNoFacesDetected();
}
TimeSpan latency = DateTime.Now - start;
this.faceLantencyDebugText.Text = string.Format("Face API latency: {0}ms", (int)latency.TotalMilliseconds);
this.isProcessingPhoto = false;
}
In GetSavedFilePhoto, I passed the string names argument once the person is identified.
Code below for the GetSavedFilePhoto method
private void GetSavedFilePhoto(string personName)
{
if (string.IsNullOrWhiteSpace(personName)) return;
var directoryPath = #"D:\PersonImages";
var directories = Directory.GetDirectories(directoryPath);
var filePaths = Directory.GetFiles(directoryPath, "*.jpg", SearchOption.AllDirectories);
}
However, in GetSavedFilePhoto method the variable directories returned an empty string of array when using directoryPath string variable. Directory "D:\PersonImages" is a valid and existing folder in my machine and, it contains subfolders with images inside. I also tried Directory.GetFiles to retrieve the jpg images but still returned an empty string.
I think it should work because I have used Directory class several times but not inside an asyncTask method. Does using async caused the files not returned when using I/O operation?
Sorry for this stupid question, but I really don't understand.
Any help is greatly appreciated.
Using Directory.GetFiles or Directory.GetDirectories method can get the folder/file in the local folder of the Application by the following code. But it could not open D:\.
var directories = Directory.GetDirectories(ApplicationData.Current.LocalFolder.Path);
In UWP app you can only access two locations at default (local folder and install folder), others need capabilities setting or file open picker.Details please reference file access permission.
If you need access to all files in D:\, the user must manually pick the D:\ drive using the FolderPicker, then you have permissions to access to files in this drive.
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
}
else
{
//do some stuff
}
I need get a list of all files in device (phone or PC) in my universal app. In wpf I did somesing like that:
class Collection {
private StringCollection seachResults;
//find all mp3 files in local storage
private void ScanDrives() {
seachResults.Clear();
string[] drives = Environment.GetLogicalDrives();
foreach (string dr in drives) {
DriveInfo di = new DriveInfo(dr);
if (!di.IsReady) {
//skip if drive not ready
continue;
}
DirectoryInfo rootDir = di.RootDirectory;
WalkDirectoryTree(rootDir);
}
}
private void WalkDirectoryTree(DirectoryInfo root) {
FileInfo[] files = null;
DirectoryInfo[] subDirs = null;
try {
files = root.GetFiles("*.mp3");
} catch (UnauthorizedAccessException e) {
} catch (DirectoryNotFoundException e) {
}
if (files != null) {
foreach (FileInfo fileInfo in files) {
seachResults.Add(fileInfo.FullName);
}
subDirs = root.GetDirectories();
foreach (DirectoryInfo dirInfo in subDirs) {
WalkDirectoryTree(dirInfo);
}
}
}
}
But when I try to migrate this into winRT app I get a few errors like unknown type Drive and unexisted method Environment.GetLogicalDrives().
Can anyone say how do that in winRT?
You won’t find a method for getting all logical drives in a WinRT app; WinRT apps exist in a sandboxed environment and will only have access to their own isolated storage or known folders (such as music) if declared as a capability in the application manifest.
For example, to get access to the user’s music folder you can do this (don’t forget to declare the capability in the app manifest):
StorageFolder folder = Windows.Storage.KnownFolders.MusicLibrary;
The only way to get access to any other part of the file system is if the user specifically grants access via a file picker:
var folderPicker = new FolderPicker();
var folder = await folderPicker.PickSingleFolderAsync();
Have you tried System.IO.Directory.GetLogicalDrives()?
I believe that Environment.GetLogicalDrives() only works for Win32/Win64. If I am not mistaken System.IO.Directory exists in mscorlib, and is widely available across Phone, RT, or Regular versions.
The MSDN reference:
https://msdn.microsoft.com/en-us/library/system.io.directory.getlogicaldrives%28v=vs.110%29.aspx
I want to get files and folders from sd from my wp8 pnone. I use the code:
private async void GetFilesAcync()
{
ExternalStorageDevice _sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();
if (_sdCard != null)
{
ExternalStorageFolder routesFolder = _sdCard.RootFolder;
IEnumerable<ExternalStorageFolder> folders = await routesFolder.GetFoldersAsync();
IEnumerable<ExternalStorageFile> files = await routesFolder.GetFilesAsync();
foreach (var file in files)
{
names.Add(file.Name);
}
foreach (var folder in folders)
{
names.Add(folder.Name);
}
MessageBox.Show(names.Count.ToString());
mainLLS.ItemsSource = names;
}
}
The problem is that I can see folders, but there are no files (they exist on sd, but don't in IEnumerable<ExternalStorageFile> files). So, when I launch the code - I can see folders, but no files. I tried to remove code which get folders, and leave only code which have to get files, but there is no result. Is there any way to solve this issue? What I'm doing wrong?
You can only access files of specific types - that is, the file type(s) your application is associated with
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj720573(v=vs.105).aspx
I am working on a simple, portable, single-form, application where the *.exe and a folder entitled UserGeneratedContent reside in the same directory. On my form I have a treeview that I want to populate with nodes corresponding to all sub-folders (if any exist) of UserGeneratedContent. The code I've pasted in below works almost the way I want it to, but it populates the treeview with UserGeneratedContent as the root node and in turn treats the sub-folders it finds as child nodes, etc.
string folder = #"UserGeneratedContent";
FolderHierachy.Nodes.Add(GetDirectoryNodes(folder));
private static TreeNode GetDirectoryNodes(string path)
{
var node = new TreeNode(Path.GetFileName(path));
var subDirs = Directory.GetDirectories(path).Select(d => GetDirectoryNodes(d)).ToArray();
node.Nodes.AddRange(subDirs);
return node;
}
At this stage I have tried just about every combination of #"UserGeneratedContent" I can think of - adding back-slashes etc, in an attempt to access the sub-folders but I'm having no luck. I know its probably something simple, but I'm stuck - what is the correct syntax to ensure that the method above looks into UserGeneratedContent to get the sub-folders?
Furthermore, I want the treeview control to allow the user to create, rename, and delete folders in any hierachy of their choice so I'm wondering what would be considered best practices in this regard?
Edit \ Update # 1 - 12.2.2012:
After a lot more trial and error I have given up on the code above - no matter what I tried I couldn't get it to work for some reason. Luckily the code below is working perfectly for me :-)
DirectoryInfo dirInfo = new DirectoryInfo(#"UserGeneratedContent");
DirectoryInfo[] subDirs = dirInfo.GetDirectories();
string pathToSubFolders = Path.Combine(#"UserGeneratedContent", subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
private void PopulateTreeView(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach(var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
return directory;
}
I need to add some error handling code to it to allow for there being no sub-folders under #"UserGeneratedContent" - as it is subDirs[0].ToString() throws an IndexOutOfRangeException if no sub-folders exist and I'm not exactly sure how to go about it so I'd be grateful for some pointers.
Edit \ Update # 2 - 12.2.2012:
For my error checking I've used a try-catch block as below:
try
{
string pathToSubFolders = Path.Combine(dirInfo.ToString(), subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
}
catch (IndexOutOfRangeException)
{
//Do Something Here
}
The above code works, but can anyone tell me if I have gone about this the right way?
Thanks for reading.
if you haven't found an other solution yet, a simple way would be:
if(subDirs.Lenght != 0) // or > 0
{
string pathToSubFolders = Path.Combine(dirInfo.ToString(), subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
}
else
{
//Do Something Here
}