Gil Sand
Gil Sand

Reputation: 6038

Accessing file in UWP throws UnauthorizedAccessException even with access granted

I'm trying to browse files and send them to a service, and for that I'm making a small internal utility app in UWP.

I made a POC console application and everything works fine.

Now I'm in an UWP app and I get an System.UnauthorizedAccessException when executing the same code.

I must add, the exception comes from a package I'm using (but I'm not developing), I'm assuming since it works in the console app and not the UWP app, the error is from my end, still, here is the complete error message :

An exception of type 'System.UnauthorizedAccessException' occurred in System.Private.CoreLib.dll but was not handled in user code
Access to the path 'D:\pulseinvoices\uk_00003.pdf' is denied.

I have authorized the app in the filesystem privacy settings enter image description here

And I have done the same in the manifest :

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
 
  IgnorableNamespaces="uap mp rescap">

...

  <Capabilities>
    <rescap:Capability Name="broadFileSystemAccess" />
    <Capability Name="internetClient" />
    <uap:Capability Name="documentsLibrary"/>
  </Capabilities>

I've read somewhere that setting the file as an environment variable is also necessary. This would completely defeat the purpose of file picking (if users are required to set an environment variable every time they need to pick a file, that's just not practical), but hey, I'm open to suggestions, so I also did this :

enter image description here

For the sake of being as complete as possible, here is the code that I'm executing :

private static readonly string FILE = @"D:\pulseinvoices\uk_00003.pdf";  //Test document

await service.ProcessAndWait(FILE, channel, params);

I'm lost because the console app works fine, executing this code only fails in the UWP app.

important : The service object is coming from an external .dll, as I said earlier in the post. I'm still hoping the issue is coming from my end so I can fix it. So I have the path using StorageFile, but when that .dll is trying to access it, I get the exception. That .dll is in my solution, so it should have the same access rights as the solution, correct?

Everything is hardcoded, this is pretty much a one-liner app at this stage. The only difference is that it's running in UWP vs Console.

What are my options?

EDIT : Adding some more details for clarity.

Here is how I fetch the file in the first place, before using the external .dll to process it.

enter image description here

Behind selectFile, a custom object is created with the path of the file among other things, so I do have a StorageFile object that is usable within my UWP app at that point. It's only once I use that external .dll and with file.Path that it fails. If I don't use the storage file at all and just hardcode the path I have the same exception. My solution can access the file, but the .dll within that solution cannot ?

Upvotes: 0

Views: 701

Answers (2)

Roy Li - MSFT
Roy Li - MSFT

Reputation: 8681

The reason for this unexpected behavior should be the same as @Martin Zikmund said. When you declare the broadFileSystemAccess capability, you have to use the StorageFile API to access the files.

The issue is that what API the service object is using in the DLL. It's highly possible that the DLL is using some desktop API to access the file instead of using StorageFile API. That will cause the issue.

Upvotes: 1

Martin Zikmund
Martin Zikmund

Reputation: 39102

Even when you declare the broadFileSystemAccess capability, you still can't access the files through non-UWP APIs. Instead, you have to use the StorageFile API:

var file = await StorageFile.GetFileFromPathAsync(path);

If you want to interop with non-UWP APIs, you can work with the Stream of the file. Add using System.IO; to the top of your file and then to read:

var stream = await storageFile.OpenStreamForReadAsync();

Or to write:

var stream = await storageFile.OpenStreamForWriteAsync();

Upvotes: 1

Related Questions