microsoft / WindowsDevicePortalWrapper

A client library that wraps the Windows Device Portal REST APIs.
MIT License
182 stars 87 forks source link

Uploading file to 'LocalAppData' using UploadFileAsync returns error 'Failed to get package origin from name' #269

Closed foomaniac closed 7 years ago

foomaniac commented 7 years ago

Hi,

Using the DevicePortal.UploadFileAsync() method to upload a file of any time to the 'LocalAppData' folder returns the error 'Failed to get package origin from name'. Can now upload a file to the 'Documents' folder using same code, so I assume it's doing something different when trying to access the LocalAppData folder. Suspect this is actually an issue in the Api onboard the device rather than this calling code, but I'm pulling what's left of my hair out trying to figure this out.

Full error returned is below:

{"Code" : -2147023728, "CodeText" : "Element not found.\r\n", "Reason" : "Failed to get package origin from name", "Success" : false}

Calling code (using Documents folder):

` public async Task GetDeviceConnectionAsync(string address) { var retryCount = 5; var retryAttempts = 0;

        var portal = new DevicePortal(
            new DefaultDevicePortalConnection(address, DefaultUsername, DefaultPassword));

        var connected = false;

        portal.UnvalidatedCert += DoCertValidation;

        portal.ConnectionStatus += (sender, args) =>
        {
            connected = args?.Status == DeviceConnectionStatus.Connected;
        };

        await portal.ConnectAsync().ConfigureAwait(false);

        while (connected == false)
        {
            if (retryAttempts == retryCount)
            {
                break;
            }

            retryAttempts++;
            await portal.ConnectAsync().ConfigureAwait(false);

        }

        if (!connected)
        {
            throw new Exception($"Failed to make connection to device at address {address}");
        }

        return portal;
    }

    public async Task<bool> UploadPackage(CLOEEInstallPackageViewModel model)
    {
        try
        {
            if (model.ApplicationPackage != null)
            {
                var filePath = $"{TempUploadDirectory}\\{model.ApplicationPackage.FileName}";

                model.ApplicationPackage.SaveAs(filePath);

                var cloeeDevice = await GetDeviceConnectionAsync(model.Address).ConfigureAwait(false);

                await cloeeDevice.UploadFileAsync("Documents", filePath, null,model.ApplicationPackage.FileName).ConfigureAwait(false);

                return true;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

        return false;
    }`

The ApplicationPackage prop on the model is HttpPostedFile.

I'm aiming to be able to upload and install a package on RPi 3 running Win Iot Core. I've tried uploading package files as well as txt files, and it always fails when uploading to the LocalAppData folder with the above message.

WilliamsJason commented 7 years ago

The main difference between using the Documents folder and the LocalAppData folder is in the PackageFullName parameter. Is the package with that package full name installed? Is it a sideloaded package? I believe the answer to both of these questions needs to be yes for the API to function.

One good way to diagnose what's wrong would be to use network monitoring software such as Fiddler to compare the call you are making via DevicePortal.UploadFileAsync with the call that comes from uploading a file via Windows Device Portal's web UI. But I have a strong suspicion it's the PackageFullName parameter.

hpsin commented 7 years ago

When you say install a package, do you mean an appx package or a cab of some sort, or a component of your existing app?

foomaniac commented 7 years ago

Right the LocalAppData folder upload makes sense now then. I would therefore assume that because it ties to an installed package, that to upload there it would just need to be some kind of supporting file for an existing package?

Also, just to clarify, it's a LOB app so sideloaded.

We're looking at ways to handle app updates, so my first thought was to create a scenario where we manually push the updated .appx/.appxbundle to the device and then we can control when we actually install the package. The app monitors machinery on a production line, so we need to be able to schedule the installs.

However, I've since found a great article on being able to self update an app, which will do the job. So I think we're good now.

Appreciate the swift responses!

hpsin commented 7 years ago

You can upload anything to LocalAppData - you could reasonably want an app to save images, settings files, saved game files, or user-generated-content, which would all go into LocalAppData. I'm guessing you found Matthijs' article on self-updating apps ? That is certainly the way to do it - using Device Portal in a production scenario is not something we suggest - you should not have Dev Mode enabled at all on production systems, really, to improve your security profile. Sideload Mode is much better for such purposes (or MDM/Intune-style management).

Glad you were unblocked! Going to close out the issue, but if someone else in the future encounters the same issue, feel free to point at this one in a new issue.