question

JulienThron-1594 avatar image
JulienThron-1594 asked ·

[UWP] Bug report: StorageFile.RenameAsync throws an UnauthorizedAccessException with NameCollisionOption.ReplaceExisting

We recently discovered an issue with the StorageFile API while renaming a file created in a picked folder.

Here's the sample code for the issue (just put it in the MainPage's Loaded event):

 var picker = new FolderPicker
 {
   FileTypeFilter = { "*" }
 };
    
 var folder = await picker.PickSingleFolderAsync();
 if (folder != null)
 {
   await Task.Run(async () =>
   {
     var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
     await file.RenameAsync("My File.txt", NameCollisionOption.ReplaceExisting);
   });
 }


The issue doesn't occur with the other NameCollisionOptions, or if you remove the call to Task.Run.

The workaround I found is to use the StorageFile.MoveAsync API instead of RenameAsync:

 await file.MoveAsync(folder, "My File.txt", NameCollisionOption.ReplaceExisting);

Thanks.

windows-uwpwindows-uwp-runtimewindows-uwp-feedback
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

RichardZhang-MSFT avatar image
RichardZhang-MSFT answered ·

Hello,

Welcome to Microsoft Q&A.

It is a permission design, if you want to continue using RenameAsync, you need to add broadFileSystemAccess capability:

package.txt

After adding the corresponding capability, you need to enable the access permission of the application in

Settings -> Pivacy -> File system

After this, the method can be executed normally, which also confirms that this is a permission design.

It is a bit complicated, you also mentioned that you found a workaround, so you can continue to use it.



Update

In addition to using broadFileSystemAccess, there is another method, which is to add folders to FutureAccessList, which is also a way to increase application access permissions. After testing, it works.

 if (folder != null)
 {
     StorageApplicationPermissions.FutureAccessList.Add(folder);
     var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
     await file.RenameAsync("My File.txt", NameCollisionOption.ReplaceExisting);
 }

Thanks.






package.txt (557 B)
9 comments Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,
It makes no sense that RenameAsync is restricted to the broadFileSystemAccess capability, as it didn't exist when the API was released in the first place.
Also, calling RenameAsync with NameCollisionOption.FailIIfExists works as expected. Only ReplaceExisting is failing, even when there is no file to replace.
And to further prove why I think it's a bug, the following code works (with ReplaceExisting):

 var picker = new FolderPicker
 {
   FileTypeFilter = { "*" }
 };
            
 var folder = await picker.PickSingleFolderAsync();
 if (folder != null)
 {
   var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
   await file.RenameAsync("My File.txt", NameCollisionOption.ReplaceExisting);
 }

Thanks.

0 Votes 0 · ·

Hello, I have noticed this problem and I am reporting it. If there is new progress, I will post here.

0 Votes 0 · ·

Hello @JulienThron-1594 , according to the test results, RenameAsync can work in known folders by default, such as documents, pictures, etc. For other folders, there will be permission restrictions. In addition to using broadFileSystemAccess, there is another method, which is to add folders to FutureAccessList, which is also a way to increase application access permissions. After testing, it works.

 if (folder != null)
 {
     StorageApplicationPermissions.FutureAccessList.Add(folder);
     var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
     await file.RenameAsync("My File.txt", NameCollisionOption.ReplaceExisting);
 }


0 Votes 0 · ·
Ivanich avatar image Ivanich RichardZhang-MSFT ·

But folder in Julien's example comes from Folder Picker dialog, it has required access permissions. Perhaps, this is something more complex and related to environment.

0 Votes 0 · ·

Yes I'm aware of these workarounds. But, like Ivanich said, permissions are not a problem as the folder is retrieved from the user. Also, using FailIfExists or GenerateUniqueName (instead of ReplaceExisting) works. It even works with ReplaceExisting if everything is run on the UI thread. There is clearly something wrong there. Please fix it.

0 Votes 0 · ·
Show more comments