1

I am trying to share a file from my UWP app sandbox running on Windows 10 desktop.

Following MS documentation on this page, the implementation seem to be fairly straight forward; however, I am having issues https://learn.microsoft.com/en-us/windows/uwp/app-to-app/share-data

I created DataTransferManager and attached DataRequested event in c-tor of my class as per explanation in the article:

DataTransferManager dataTransferManager;

public MainPage()
{
  this.InitializeComponent();
  ...
    dataTransferManager = DataTransferManager.GetForCurrentView(); 
    dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested); 
}

Next, in a method that is called from background thread, I call ShowShareUI making sure it executes on the main thread

Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
    DataTransferManager.ShowShareUI(); //THIS CALL SHOWS A POPUP AND IMMEDIATELLY CLOSES IT
}).AsTask().Wait();

Then in my OnDataRequested event, I add the file I want to share:

private async void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
    // get the file from application sandbox
    StorageFile attachmentFile = await StorageFile.GetFileFromPathAsync(@"C:\Users\ME\AppData\Local\Packages\f040f23f-....-84\LocalState\logs\MYLOG.log");
    DataRequest request = args.Request; 
    request.Data.Properties.Title = "My Log File";
    request.Data.Properties.Description = "Sharing MYLOG file.";
    List<IStorageItem> storage = new List<IStorageItem>()
    {
        attachmentFile
    };
    request.Data.SetStorageItems(storage);
}

but nothing happens. I had no chance to select anything in the dialog that opened for a 1/2 second and closed. Here is how the dialog looks like, it opens and closes almost immediately after it opened, it just show "This app can't share right now".

enter image description here

pixel
  • 9,653
  • 16
  • 82
  • 149

2 Answers2

4

Figured it out, following is the solution to my problem.

Added global variable in MainPage.xaml.cs:

private DataTransferManager dataTransferManager;

In constructor of MainPage, added this

dataTransferManager = DataTransferManager.GetForCurrentView(); 
dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested); 

Up to this point, my code has not change but next comes call to ShowShareUI and that call was originally called from a background thread but dispatched to UI thread using Dispatcher (see original post). I still dont know why doing it as I explained originally was not working but after changing code like below, It is working now. So, initiate sharing on button click on the UI thread:

private void Button_Click()
{
  DataTransferManager.ShowShareUI();
}

This event handler is triggered by the above call to ShowShareUI():

private async void DataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
    DataRequestDeferral deferral = args.Request.GetDeferral();

    // MyLogger has SendLogs method but calling this in Button_Click above will not work and the Share
    // dialog will just open and close.  Moving it down to this event solves the issue.
    MyLogger.SendLogs(async logpath =>
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
        {
            StorageFile myFile = await StorageFile.GetFileFromPathAsync(logpath);

            DataRequest request = args.Request; 
            request.Data.Properties.Title = "Share My Logs";
            request.Data.Properties.Description = string.Format("Share log file {0}.", myFile.DisplayName);

            List<IStorageItem> myStorageItems = new List<IStorageItem>() { myFile };
            request.Data.SetStorageItems(myStorageItems);
            deferral.Complete();
        });
    });
}

This has resolved my issue

pixel
  • 9,653
  • 16
  • 82
  • 149
1

StorageFile attachmentFile = await StorageFile.GetFileFromPathAsync(@"C:\Users\ME\AppData\Local\Packages\f040f23f-....-84\LocalState\logs\MYLOG.log");

In UWP, you could not get files from path directly.

UWP apps run sandboxed and have very limited access to the file system. For the most part, they can directly access only their install folder and their application data folder. They do not have permission to access the file system elsewhere. Rob has explained this point in his blog Skip the path: stick to the StorageFile

So, your code would be changed like the following:

StorageFolder logsFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("logs");
StorageFile file = await logsFolder.GetFileAsync("MYLOG.log");

Please change your code and try to run your app again to see if you still face this issue.

Xie Steven
  • 8,544
  • 1
  • 9
  • 23
  • But in my case above, it is accessing the file in app application data folder (sandbox). The path I provided is the path to the app sandbox. That works and I know it because I tried first to attach the file to a new email just to find out that that will work only with Mail app from app store but not with any other Win32 app which in my case makes it unusable. So, file is being accessed and retrieved properly here. Thanks – pixel Oct 04 '17 at 17:50
  • ... btw, the same issue exists when I change code like you suggested. Call to ShowShareUI() will open the Share dialog but by the time the event OnDataRequested() is entered (breakpoints), the dialog will already close. No difference – pixel Oct 04 '17 at 21:34