I have a WPF desktop app and I want to use the UWP FolderPicker API to pick a directory. My app uses the UWP packaging project so it is built and ran as an appx. I've added in the Windows and WindowsBase references and my project builds and runs. However I get a runtime error when trying to use the folder picker. My code is as follows:
private async void OnGetDirectory(object parameter)
{
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
folderPicker.FileTypeFilter.Add("*");
Windows.Storage.StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
// Application now has read/write access to all contents in the picked folder
// (including other sub-folder contents)
Windows.Storage.AccessCache.StorageApplicationPermissions.
FutureAccessList.AddOrReplace("PickedFolderToken", folder);
}
else
{
}
}
The error I get is on the line System.Exception: await folderPicker.PickSingleFolderAsync(); and the error 'Invalid window handle. (Exception from HRESULT: 0x80070578)'
What am I missing or is it even possible to use the FolderPicker from a WPF app?
Instead of UWP FolderPicker you can just use a normal Windows Forms folder dialog - FolderBrowserDialog in System.Windows.Forms namespace (see this question for an example).
If you want to work with StorageFolder, you can call StorageFolder.GetFolderFromPathAsync method or you can use the classic folder APIs like System.IO.Directory or System.IO.DirectoryInfo.
According to UWP APIs available to a packaged desktop app (Desktop Bridge) article, some feature areas are not yet fully tested or currently functioning as intended. The "File and folder pickers" feature that you used just in the list. The detail description for this feature is as follows:
Packaged apps have full file system access and do not need UWP pickers.
So that FolderPicker may not completed supported in your UWP packing project. Please try to use the file relative APIs that supported in WPF itself.
More details please reference this document.
Related
I'm trying to save a file without a filepicker under my desktop or somewhere else, but I always get the error "Access to path [...] is denied"
This is my code:
private async void SaveFile(string Path)
{
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(Path);
StorageFile sampleFile = await folder.CreateFileAsync("sample.txt", Windows.Storage.CreationCollisionOption.ReplaceExisting);
}
I tried the same code but with the Localfoder and it worked.
Is there any way to get access to the path without a filepicker?
Using FilePicker gets permission from the user to access file locations. File system access is a restricted capability in UWP. You can enable Broad Filesystem Access in your package manifest to get this permission when the app is installed. It's not recommended for apps published to the Microsoft Store, because it makes it less likely for you app to be approved. See the App capability declarations documentation.
Alternatively, you could run your app from a folder that contains the desktop in one of its subfolders by using the AppExecutionAlias extension mention under Accessing additional locations in File Access Permissions. Underneath that section there is also an explanation of Broad Filesystem Access as well.
I have developed a UWP app in C# which contains a Windows Runtime Component C++ project. the app allows the user to choose an mp4 file and passes this file to the c++ code, which then utilizes ffmpeg libraries to retrieve the presentation time stamps of a video file and output them to a file.
the issue i'm facing is that the c++ code is not able to open the mp4 file when using the avformat_open_input function:
int PTSExtraction::parse_file(Platform::String^ filename)
{
int ret = 0;
AVPacket pkt = { 0 };
std::wstring fileNameW(filename->Begin());
std::string fileNameA(fileNameW.begin(), fileNameW.end());
const wchar_t* w_chars = fileNameW.c_str();
src_filename = fileNameA.c_str();
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
fprintf(stderr, "Could not open source file %s\n", src_filename);
return 1;
}
// rest of code
}
the error received by avformat_open_input is Permission Denied. I cannot even open a random text file in this function by doing:
ofstream output;
output.open("output.txt");
I realize there are file system permissions that are blocking the C++ component of my uwp app from opening files. here are the things i have tried so far:
i have enabled broadFileSystemAccess in the Package.appxmanifest (https://blogs.windows.com/windowsdeveloper/2018/05/18/console-uwp-applications-and-file-system-access/) - in the Capabilities section of the Package.appxmanifest file I've allowed access to Location, Pictures Library, and Videos Library.
I've checked the File System Privacy Settings on my computer and enabled my app to access the File System.
I've tried moving the mp4 file to various locations (Documents, Pictures Library, Videos Library) to see if the C++ component has access to these locations.
I've tried the solution from this post: Qt WinRT App cannot access file permission denied.
None of these allow the C++ component to open any files. i would really appreciate if anyone has a solution for this problem.
The broadFileSystemAccess capability gives you access to the full file system, but not for all APIs, only for the UWP's Windows.Storage API. This means you have to use StorageFolder and StorageFile to access the file. For example, you can then retrieve the file from a given path with StorageFile.GetFileFromPathAsync.
The Windows Runtime Componnet C++ project is a Universal Windows project(UWP project). You could see the characters (Universal Windows) in the left of your component project name in the Solution Explorer.
For a UWP project(including Windows Runtime Componnet C++ project), you could access certain file system locations by default such as application install directory, application data locations, user’s downloads folder, or access libraries by declaring capabilities, or let the user pick files and folders by calling a file picker, referring to the File access permissions document. If you need to read and write a file using a StorageFile object, you could refer to the document.
For example, if your mp4 file is in Videos library, you could use the following code to get a file:
Add the Videos capability in your C# UWP project’s manifest.
Check the code as a sample:
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Search.h>
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::Storage::Search;
……
auto lib =co_await Windows::Storage::StorageLibrary::GetLibraryAsync(Windows::Storage::KnownLibraryId::Videos);
auto folder = lib.Folders().GetAt(0);
StorageFile myMp4 =co_await folder.GetFileAsync(L"test.mp4");
If you need the C++ code of other ways such as accessing the default locations or access files by calling pickers, please feel free to contact me.
it's not because of the file you picked from the user.
this error can happen because of the following 2 Case
since FFmpeg Api Uses Syncronus file Access system and uwp Does not Support that in the file system except the Apps Local Directory, so you can do that by first copying the file picked by the user to Local Folder and then using a copied file to access the file.
due to the dll required to access API during runtime, so you have to Add All Dll to the main folder where you have App.xaml and then set the property to content and copy always to all dll
i.e.avcodec,avdevice,avfilter,avformat,avresample,avutil,postproc,swresample,swscale
read this: "Windows Store Certification, File I/O, and Other Details" - at http://trac.ffmpeg.org/wiki/CompilationGuide/WinRT
I am trying to edit a existing Word document using the UWP app (Universal Windows). But for some reason I am getting "File does not exist" error.
I have tried using the below code to access the word document:
using(WordprocessingDocument wordDoc = WordprocessingDocument.Open("C:\\Users\\Public\\Desktop\\Doc1.docx", true))
{
}
System.IO.FileNotFoundException: 'Could not find document'
Based on further clarification in the comments section, please see the following instructions.
Add your .DOCX file to the Assets folder within your project and set the build action to "Content".
In order to write any changes to the file, we'll need to copy it to the packages LocalFolder and then access it from there.
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/doc1.docx"));
if (file != null)
{
//Copy .docx file to LocalFolder so we can write to it
await file.CopyAsync(ApplicationData.Current.LocalFolder);
String newFile = ApplicationData.Current.LocalFolder.Path + "/doc1.docx";
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(newFile, true))
{
//Your code here
}
}
You'll need to expand on this somewhat to make sure the file is only copied to the LocalFolder once etc, but you get the basic idea.
By default, the UWP doesn't allow to access the files outside the app container. But from windows 10 build 17134, a new capability broadFileSystemAccess has been introduced. It allows apps to get the same access to the file system as the user who is currently running the app without any additional file-picker style prompts during runtime.
So, please check if you have declare this capability in the 'Package.appxmanifest' file.
Please see File access permissions and broadFileSystemAccess entry in App capability declarations for more information.
If you still face this issue when you add the broadFileSystemAccess capability, then, the issue should be in 'WordprocessingDocument.Open' API. You need to note that 'File access permissions' document has mentioned:
This broadFileSystemAccess capability works for APIs in the Windows.Storage namespace.
This means that the 'WordprocessingDocument.Open' may not use the Windows.Storage APIs to access the files. If so, you need to report this issue to Open-XML-SDK.
When converting an app to a Windows Store app, we add the files as mentioned here. But now - how do we access them? What's their path?
They're not in the special folder created for the package.
You can create a folder structure in your project where you can include the files and then since you are already crossing the Centennial Bridge, you can start using the Windows.Storage.StorageFile WinRT API to interact with files.
For example, you can use: StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///folderUnderYourAppRoot/image.bmp")); to get the file which is under the "folderUnderYourAppRoot". This is the generic guidance: https://msdn.microsoft.com/en-us/windows/uwp/files/quickstart-reading-and-writing-files, so you can review it further...
I have universal app and shared assets in it. These are pictures I use both in the mobile and in the desktop app. But, obviously installation folder is not accessible in code-behind. Is there way how to achieve that or I have to add pictures to both platform-wise projects?
But, obviously installation folder is not accessible in code-behind.
No, it is accessible.
Is there way how to achieve that or I have to add pictures to both platform-wise projects?
We can use Package.InstalledLocation to access the folders or files in the installed location for example like this:
var assetsfolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
And we don't need to add pictures to both platform projects. You can create a folder for example named "ShareAssets" in the [ProjectName].Shared like this:
And I put a image under this folder, so will both the windows 8.1 project and windows phone 8.1 project be able to access this folder:
<Image Source="ShareAssets/miao4.jpg" />
As the method I provided, we can also access this folder in the code behind from both platform:
var shareassetsfolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("ShareAssets");