private void ExecuteInstallAppx(ParameterHelper parameters, string appxFile, string certificate)
        {
            if (_verbose)
            {
                Console.Out.WriteLine("Starting Appx installation...");
            }

            var file = new FileInfo(Path.GetFullPath(appxFile));

            if (!file.Exists)
            {
                throw new System.IO.FileNotFoundException("Specified appx file '" + appxFile + "' wasn't found");
            }

            if (!String.IsNullOrWhiteSpace(certificate))
            {
                var certFile = new FileInfo(certificate);
                if (!certFile.Exists)
                {
                    throw new System.IO.FileNotFoundException("Specified certificate file '" + certFile + "' wasn't found");
                }
                certificate = certFile.FullName;
            }
            else
            {
                // Must pass in null instead of empty string if certificate is omitted
                certificate = null;
            }

            // Parse the AppxManfest contained in the Appx file to extract the package name, dependencies, AppID, etc.
            AppxManifest appxData;

            try
            {
                appxData = AppxManifest.Get(appxFile);
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine("Failed to parse Appx manifest: " + ex.Message);
                throw;
            }
            if (!appxData.IsValid)
            {
                throw new System.ArgumentException("Specified Appx '" + appxFile + "' contains an invalid AppxManifest");
            }

            // Construct an "identity" object from the AppxManifest data which can be referenced later to launch the installed app
            var appIdentity = new AppPackageIdentity(appxData);

            // Query for app packages already installed on the device and uninstall them if necessary
            // NOTE: Check for any uninstall any package matching this appx PackageName and Publisher to
            //  ensure a clean install of the new build

            List <PackageInfo> matchingPackages;

            if (TryRetrieveInstalledPackages(appIdentity, out matchingPackages) && matchingPackages.Count() > 0)
            {
                if (_verbose)
                {
                    Console.Out.WriteLine("Uninstalling previous app..");
                }

                foreach (var package in matchingPackages)
                {
                    try
                    {
                        if (_verbose)
                        {
                            Console.Out.WriteLine("Uninstalling package: " + package.FullName);
                        }

                        _portal.UninstallApplicationAsync(package.FullName).Wait();
                    }
                    catch (AggregateException ex)
                    {
                        // NOTE: We really shouldn't continue with installation if we failed to remove a previous version of the app.
                        // If a version of the app remains on the device, the Install API will NOT replace it but still reports "success",
                        // meaning the user could be running old code and not know it. A hard fail is the only way to ensure this doesn't happen.
                        Console.Out.WriteLine("Uninstall of package '" + package.FullName + "' failed: " + ex.InnerException.Message);
                        System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                    }
                }

                if (_verbose)
                {
                    Console.Out.WriteLine("Finished uninstalling previous app packages");
                }
            }

            Task installTask = _portal.InstallApplicationAsync(null, file.FullName, appxData.Dependencies, certificate, 500, 1, false);

            try
            {
                installTask.Wait();
                Console.Out.WriteLine("Installation completed successfully");
            }
            catch (AggregateException ex)
            {
                Console.Out.WriteLine("Installation of Appx failed!");

                HandleInstallOperationException(ex);
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
            }

            // Save AppIdentity to field after successful installation
            _installedAppId = appIdentity;

            // If the app Identity is "complete" we have the FullPackageName and AUMID parameters, so we'll
            // add them to our parameter set to later launch the app; no need to query package info from the device
            if (_installedAppId.CompleteIdentity)
            {
                parameters.AddOrUpdateParameter(parameterPackage, _installedAppId.PackageFullName);
                parameters.AddOrUpdateParameter(ParameterAumid, _installedAppId.LaunchId);
            }
        }
Exemple #2
0
        /// <summary>
        /// Main entry point for handling an install operation
        /// </summary>
        /// <param name="portal">DevicePortal reference for communicating with the device.</param>
        /// <param name="parameters">Parsed command line parameters.</param>
        public static void HandleOperation(DevicePortal portal, ParameterHelper parameters)
        {
            if (parameters.HasFlag(ParameterHelper.HelpFlag))
            {
                Console.WriteLine(XblInstallUsageMessage);
                return;
            }

            InstallOperation operation = new InstallOperation(portal);

            portal.AppInstallStatus += operation.AppInstallStatusHandler;

            if (parameters.HasFlag(ParameterHelper.VerboseFlag))
            {
                operation.verbose = true;
            }

            List <string> dependencies = new List <string>();

            // Build up the list of dependencies.
            if (parameters.HasParameter("depend"))
            {
                dependencies.AddRange(parameters.GetParameterValue("depend").Split(';'));
            }

            string certificate = parameters.GetParameterValue("cer");

            string appxFile     = parameters.GetParameterValue("appx");
            string folderPath   = parameters.GetParameterValue("folder");
            string registerPath = parameters.GetParameterValue("register");

            try
            {
                if (!string.IsNullOrEmpty(appxFile))
                {
                    operation.mreAppInstall.Reset();
                    Task installTask = portal.InstallApplicationAsync(null, appxFile, dependencies, certificate);
                    operation.mreAppInstall.WaitOne();

                    if (operation.installResults.Status == ApplicationInstallStatus.Completed)
                    {
                        Console.WriteLine("Install complete.");
                    }
                    else
                    {
                        Console.WriteLine("Install failed in phase {0}. {1}", operation.installResults.Phase, operation.installResults.Message);
                    }
                }
                else if (!string.IsNullOrEmpty(folderPath))
                {
                    // Install all dependencies one at a time (loose folder doesn't handle dependencies well).
                    foreach (string dependency in dependencies)
                    {
                        operation.mreAppInstall.Reset();
                        Task installTask = portal.InstallApplicationAsync(null, dependency, new List <string>());
                        operation.mreAppInstall.WaitOne();

                        if (operation.installResults.Status != ApplicationInstallStatus.Completed)
                        {
                            Console.WriteLine("Deploy failed during dependency installation. {0}", operation.installResults.Message);
                            return;
                        }
                    }

                    if (!Directory.Exists(folderPath))
                    {
                        Console.WriteLine("Failed to find provided loose folder.");
                        Console.WriteLine();
                        Console.WriteLine(XblInstallUsageMessage);
                        return;
                    }

                    // Remove any trailing slash
                    if (folderPath.EndsWith("\\"))
                    {
                        folderPath = folderPath.Remove(folderPath.Length - 1);
                    }

                    string destinationFolderName = parameters.GetParameterValue("destfoldername");

                    if (string.IsNullOrEmpty(destinationFolderName))
                    {
                        // Get just the folder name
                        string folderName = folderPath.Substring(folderPath.LastIndexOf('\\') + 1);

                        destinationFolderName = folderName;
                    }

                    string transferType = parameters.GetParameterValue("transfer");

                    if (string.IsNullOrEmpty(transferType) || string.Equals(transferType, "smb", StringComparison.OrdinalIgnoreCase))
                    {
                        string shareName         = Path.Combine("\\\\", parameters.GetParameterValue(ParameterHelper.IpOrHostname), "DevelopmentFiles");
                        string destinationFolder = Path.Combine(shareName, "LooseApps", destinationFolderName);

                        try
                        {
                            operation.CopyDirectory(folderPath, destinationFolder);
                        }
                        catch (IOException e)
                        {
                            if (e.HResult == ErrorLogonFailureHresult)
                            {
                                Task <SmbInfo> smbTask = portal.GetSmbShareInfoAsync();
                                smbTask.Wait();

                                // Set the username/password for accessing the share.
                                NetworkShare.DisconnectFromShare(shareName, true);
                                int connected = NetworkShare.ConnectToShare(shareName, smbTask.Result.Username, smbTask.Result.Password);

                                if (connected != 0)
                                {
                                    Console.WriteLine(string.Format("Failed to connect to the network share: {0}", connected));
                                    return;
                                }

                                operation.CopyDirectory(folderPath, destinationFolder);

                                NetworkShare.DisconnectFromShare(shareName, false);
                            }
                            else
                            {
                                Console.WriteLine(string.Format("Unexpected exception encountered: {0}", e.Message));
                                return;
                            }
                        }
                    }
                    else if (string.Equals(transferType, "http", StringComparison.OrdinalIgnoreCase))
                    {
                        operation.UploadDirectoryOverHttp(folderPath, destinationFolderName);
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Unexpected transfer type received: {0}. Expecting one of SMB or HTTP.", transferType));
                        return;
                    }

                    Task registerTask = portal.RegisterApplicationAsync(destinationFolderName);
                    registerTask.Wait();

                    Console.WriteLine("Install complete.");
                }
                else if (!string.IsNullOrEmpty(registerPath))
                {
                    Task registerTask = portal.RegisterApplicationAsync(registerPath);
                    registerTask.Wait();

                    Console.WriteLine("Registration complete.");
                }
                else
                {
                    Console.WriteLine("Must provide an appx package, loose folder, or path to register.");
                    Console.WriteLine();
                    Console.WriteLine(XblInstallUsageMessage);
                    return;
                }
            }
            catch (AggregateException e)
            {
                if (e.InnerException is DevicePortalException)
                {
                    DevicePortalException innerException = e.InnerException as DevicePortalException;

                    Console.WriteLine(string.Format("Exception encountered: {0}, hr = 0x{1:X} : {2}", innerException.StatusCode, innerException.HResult, innerException.Reason));
                }
                else if (e.InnerException is OperationCanceledException)
                {
                    Console.WriteLine("The operation was cancelled.");
                }
                else
                {
                    Console.WriteLine(string.Format("Unexpected exception encountered: {0}", e.Message));
                }

                return;
            }
        }