I'm developing a UWP application which shall be able to share its files. I followed the documentation from Microsoft and the solution worked pretty well.
Here is my implementation:
public void ShareLocalFile(LocalFileToShare file)
{
DataTransferManager.GetForCurrentView().DataRequested += async (sender, args) =>
{
var deferral = args.Request.GetDeferral();
try
{
var storageFile = await StorageFile.GetFileFromPathAsync(file.FilePath).AsTask();
args.Request.Data.SetStorageItems(new[] { storageFile });
}
finally
{
deferral.Complete();
}
};
DataTransferManager.ShowShareUI();
}
However, the app stores all files with not human-readable names which makes users be uneasy with the sharing. So, I wanted to share a file with an alternative name without actually renaming it on the file system because files are opened in a third-party reader. In addition, the files are quite big and copying them with new names is not a good choice.
Firstly I thought that I could make a symbolic link but it's only possible with Administrator rights
Then I looked at the signature of "void DataPackage.SetStorageItems(IEnumerable value)" method and guessed that it's probably possible to pass there my own implementation of IStorageItem what I did:
public class StorageItemWithAlternativeName : IStorageItem
{
private readonly IStorageItem storageItem;
public StorageItemWithAlternativeName(IStorageItem storageItem, string alternativeItemName)
{
this.storageItem = storageItem;
Name = alternativeItemName;
}
public string Name { get; }
// the interface implementation omitted for briefness but it simply delegates all actions to the decorated storageItem
}
public static class LocalFileToShareExtensions
{
public static async Task<IStorageItem> GetStorageItem(this LocalFileToShare file)
{
var storageFile = await StorageFile.GetFileFromPathAsync(file.FilePath).AsTask();
if (!string.IsNullOrWhiteSpace(file.AlternativeFileName))
{
storageFile = new StorageItemWithAlternativeName(storageFile, file.AlternativeFileName);
}
return storageFile;
}
}
And here I failed. The error is quite silly - SetStorageItems method throws an InvalidCastException: "No such interface supported. The collection contains item(s) that can't be converted to read-only form."
I investigated the windows event log and found the following entry:
Faulting application name: [MyApp].Windows.exe, version: 7.0.0.0, time stamp: 0x5bb69bfe
Faulting module name: combase.dll, version: 10.0.17763.253, time stamp: 0xa3f81b2d
Exception code: 0xc000027b
Fault offset: 0x00209931
Faulting process id: 0x4ee4
Faulting application start time: 0x01d4be3ccca1f00f
Faulting application path: [PathToMyApp].Windows.exe
Faulting module path: C:\WINDOWS\System32\combase.dll
Report Id: 35999df1-6b4f-4675-a821-a84e6ea0cfb4
Faulting package full name: [MyAppPackageName]
Faulting package-relative application ID: App
It seems that the DataPackage object communicates with COM so I also tried [assembly: [ComVisible(true)]
attribute on my assembly but I did not succeed.
The question is how can I kind of dumb the system and share a file with a different name? Is it possible to pass my own implementations to UWP SDK methods? Because now it violates the Liskov substitution principle.
I will appreciate any help with this!
Please try to use the overloaded method SetStorageItems
with parameter readOnly:false
, something like this:
args.Request.Data.SetStorageItems(new[] { storageFile }, false);
User contributions licensed under CC BY-SA 3.0