UWP C# and Windows Runtime Component C++ Permission Denied error when opening file

Surya Solanki 41 Reputation points
2020-12-27T03:07:41.673+00:00

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:

None of these allow the C++ component to open any files. i would really appreciate if anyone has a solution for this problem.

Universal Windows Platform (UWP)
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,527 questions
0 comments No comments
{count} votes

Accepted answer
  1. Yan Gu - MSFT 2,676 Reputation points
    2020-12-28T05:56:26.887+00:00

    Hello,

    Welcome to Microsoft Q&A.

    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:

    1. Add the Videos capability in your C# UWP project’s manifest.
    2. 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.

    Update:

    You need to add a header file(#include <winrt/Windows.Foundation.h>) to use the IAsyncAction interface as the return type of a method, which means the asynchronous method does not have a result object and don’t report ongoing progress. If you want a method with a asynchronous return object or with ongoing progress, you could refer to the Concurrency and asynchronous operations with C++/WinRT and More advanced concurrency and asynchrony with C++/WinRT.

    In your scenario, you could use IAsyncAction as the return type, like this:

    Class.h file

    #include <winrt/Windows.Foundation.h>  
    #include <winrt/Windows.Storage.h>  
    #include <winrt/Windows.Storage.Search.h>  
      
    using namespace winrt::Windows::Foundation;  
    using namespace winrt::Windows::Storage;  
    using namespace winrt::Windows::Storage::Search;  
    ......  
    //Declare the method in Class.h file  
    IAsyncAction YourMethod();  
    

    Class.cpp file

        IAsyncAction Class:: YourMethod ()  
        {  
            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");  
        }  
    

    Update:

    I got your point now. Your Windows Runtime Component project is a C++/CX project, while I thought it is a C++/WinRT project. The asynchronous programming in C++/CX is different from that in C++/WinRT.

    In C++/CX, asynchronous C++/CX code makes use of Parallel Patterns Library (PPL) tasks. Typically, an asynchronous C++/CX method chains PPL tasks together by using lambda functions with concurrency::create_task and concurrency::task::then. Each lambda function returns a task which, when it completes, produces a value that is then passed into the lambda of the task's continuation. Alternatively, instead of calling create_task to create a task, an asynchronous C++/CX method can call concurrency::create_async to create an IAsyncXxx^. You can get more information about asynchronous programming in C++/CX referring to the document.

    For your scenario, you could refer to the following code:

    #include <ppltasks.h>  
      
    using namespace Platform;  
    using namespace concurrency;  
    using namespace Windows::Storage;  
    using namespace Windows::Storage::Search;  
    ……  
      
    void PTSExtraction::test_function ()  
    {  
        Windows::Foundation::IAsyncOperation<Windows::Storage::StorageLibrary^>^ lib = Windows::Storage::StorageLibrary::GetLibraryAsync(Windows::Storage::KnownLibraryId::Videos);  
        auto t = create_task(lib);  
        t.then([this](Windows::Storage::StorageLibrary^ library) {  
            Windows::Storage::StorageFolder^ folder= library->Folders->GetAt(0);  
            return folder;  
           }).then([this](Windows::Storage::StorageFolder^ folder) {  
                Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^ file = folder->GetFileAsync("1122.mp4");  
                auto myFile = create_task(file);  
                return myFile;  
                }).then([this](Windows::Storage::StorageFile^ myFile) {  
                    String^ str = myFile->Name;  
                    });  
          
    }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful