private async Task <CommandStatus> InstallAppAsync( AppInfo installedAppInfo, Version installedAppVersion, string connectionString, IDictionary <string, AppInfo> installedApps, AppxManagementDataContract.AppDesiredState desiredState) { Logger.Log("Processing install request for " + desiredState.packageFamilyId, LoggingLevel.Verbose); if (installedAppInfo == null) { // It is a new application. Logger.Log(" Can't find an installed version... Installing a fresh copy...", LoggingLevel.Verbose); await InstallAppFromAzureAsync(installedAppInfo, connectionString, desiredState, false /*not self update*/); // ---> InstallAppFromAzureAsync } else { Windows.ApplicationModel.PackageId thisPackage = Windows.ApplicationModel.Package.Current.Id; Debug.WriteLine("FamilyName = " + thisPackage.FamilyName); Debug.WriteLine("Name = " + thisPackage.Name); bool isSelf = desiredState.packageFamilyName == thisPackage.FamilyName; // A version of this application is installed. Logger.Log(" Found an installed version...", LoggingLevel.Verbose); if (desiredState.version == installedAppVersion) { Logger.Log(" Same version is installed...", LoggingLevel.Verbose); AppxManagementDataContract.AppReportedState appReportedState = null; if (AppUtils.StartUpTypeToMessage(desiredState.startUp) == installedAppInfo.StartUp) { Logger.Log(" App StartUp is the same: desired = " + desiredState.startUp, LoggingLevel.Verbose); appReportedState = new AppxManagementDataContract.AppReportedState( desiredState.packageFamilyId, desiredState.packageFamilyName, installedAppVersion.ToString(), AppUtils.StartUpTypeFromMessage(installedAppInfo.StartUp), installedAppInfo.InstallDate, 0, null, // no error JsonReport.Report); } else { Logger.Log(" App StartUp is different: desired = " + desiredState.startUp.ToString() + ", current = " + installedAppInfo.StartUp.ToString(), LoggingLevel.Verbose); switch (desiredState.startUp) { case AppxStartUpType.None: { bool background = installedAppInfo.StartUp == StartUpType.Background; if (background) { Logger.Log(" Removing app from background apps.", LoggingLevel.Verbose); StartupAppInfo startupAppInfo = new StartupAppInfo(desiredState.packageFamilyName, background); await RemoveStartupAppAsync(startupAppInfo); } else { Logger.Log(" App is no longer marked to be start-up app. Change takes effect when another app is set to be the start-up app.", LoggingLevel.Verbose); } } break; case AppxStartUpType.Foreground: { Logger.Log(" Setting app to be the foreground app.", LoggingLevel.Verbose); StartupAppInfo startupAppInfo = new StartupAppInfo(desiredState.packageFamilyName, false /*background*/); await AddStartupAppAsync(startupAppInfo); } break; case AppxStartUpType.Background: { Logger.Log(" Adding app to the background apps.", LoggingLevel.Verbose); StartupAppInfo startupAppInfo = new StartupAppInfo(desiredState.packageFamilyName, true /*background*/); await AddStartupAppAsync(startupAppInfo); } break; } AppxStartUpType appStartUp = await GetAppStartup(desiredState.packageFamilyName); Logger.Log(" Querying returned app startup: " + appStartUp.ToString(), LoggingLevel.Verbose); appReportedState = new AppxManagementDataContract.AppReportedState( desiredState.packageFamilyId, desiredState.packageFamilyName, installedAppVersion.ToString(), appStartUp, installedAppInfo.InstallDate, 0, null, // no error JsonReport.Report); } _stateToReport[desiredState.packageFamilyId] = appReportedState; } else if (desiredState.version > installedAppVersion) { Logger.Log(" Older version is installed...", LoggingLevel.Verbose); if (!String.IsNullOrEmpty(desiredState.appxSource)) { // Trigger the update... await InstallAppFromAzureAsync(installedAppInfo, connectionString, desiredState, isSelf); if (isSelf) { // If isSelf == true, it means that SystemConfigurator will force this application to exit very soon. // Let's stop processing any further desired properties. return(CommandStatus.PendingDMAppRestart); } } else { // Note that store updates are not control through DM desired properties. // Instead, they are triggered by the system scan for all store applications. throw new Error(ErrorCodes.INVALID_DESIRED_APPX_SRC, "Appx package is required to update " + desiredState.packageFamilyName); } } else { // desiredState.version < installedAppVersion Logger.Log(" Newer version is installed...rolling back.", LoggingLevel.Verbose); if (String.IsNullOrEmpty(desiredState.appxSource)) { AppxManagementDataContract.AppReportedState appReportedState = new AppxManagementDataContract.AppReportedState( desiredState.packageFamilyId, desiredState.packageFamilyName, installedAppVersion.ToString(), AppUtils.StartUpTypeFromMessage(installedAppInfo.StartUp), installedAppInfo.InstallDate, ErrorCodes.INVALID_DESIRED_APPX_SRC, "Cannot install appx without a source.", JsonReport.Report); _stateToReport[desiredState.packageFamilyId] = appReportedState; throw new Exception("Failed to roll back application version."); } if (isSelf) { // The reverting is implemented as an 'uninstall' followed by an 'install'. // The package to be installed is downloaded in the 'install' step. // So, if we were to revert self to an older version, we would have to: // - (1) download the old version first, // - (2) send an atomic uninstall-install request to SystemConfigurator to // uninstall and follow with an install and re-launch. // The above two steps are not implemented yet. throw new Error(ErrorCodes.CANNOT_REVERT_DM_APPLICATION, "Reverting to an older version of the device management application (" + desiredState.packageFamilyName + ") is not supported."); } // Note that UninstallAppAsync will throw if it fails - and correctly avoid launching the install... await UninstallAppAsync(installedAppInfo, packageFamilyId : desiredState.packageFamilyId, packageFamilyName : desiredState.packageFamilyName); await InstallAppFromAzureAsync(installedAppInfo, connectionString, desiredState, isSelf); } } return(CommandStatus.Committed); }
private async Task <CommandStatus> ApplyAppDesiredState(string connectionString, IDictionary <string, AppInfo> installedApps, AppxManagementDataContract.AppDesiredState desiredState) { CommandStatus commandStatus = CommandStatus.NotStarted; Version installedAppVersion = null; AppInfo installedAppInfo = FindInstalledAppInfo(installedApps, desiredState.packageFamilyName); if (installedAppInfo != null) { installedAppVersion = new Version(installedAppInfo.Version); } switch (desiredState.action) { case AppDesiredAction.Install: { commandStatus = await InstallAppAsync(installedAppInfo, installedAppVersion, connectionString, installedApps, desiredState); } break; case AppDesiredAction.Uninstall: { await UninstallAppAsync(installedAppInfo, packageFamilyId : desiredState.packageFamilyId, packageFamilyName : desiredState.packageFamilyName); } break; case AppDesiredAction.Query: { ReportQueriedApp(installedAppInfo, desiredState, _stateToReport); } break; case AppDesiredAction.Unreport: { Logger.Log("Processing unreport request...", LoggingLevel.Verbose); AppxManagementDataContract.AppReportedState appReportedState = new AppxManagementDataContract.AppReportedState( desiredState.packageFamilyId, desiredState.packageFamilyName, null, // no version AppUtils.StartUpTypeFromMessage(StartUpType.None), null, // no install date 0, null, // no error JsonReport.Unreport); _stateToReport[desiredState.packageFamilyId] = appReportedState; } break; case AppDesiredAction.Undefined: { Logger.Log("Processing unknown request...", LoggingLevel.Verbose); AppxManagementDataContract.AppReportedState appReportedState = new AppxManagementDataContract.AppReportedState( desiredState.packageFamilyId, desiredState.packageFamilyName, null, // no version AppUtils.StartUpTypeFromMessage(StartUpType.None), null, // no install date ErrorCodes.INVALID_DESIRED_APPX_OPERATION, "Invalid application operation.", JsonReport.Report); _stateToReport[desiredState.packageFamilyId] = appReportedState; } break; } return(commandStatus); }
private async Task InstallAppFromAzureAsync(AppInfo currentState, string connectionString, AppxManagementDataContract.AppDesiredState desiredState, bool selfUpdate) { // Is this a fresh installation? if (currentState == null) { currentState = new AppInfo(); currentState.PackageFamilyName = desiredState.packageFamilyName; currentState.Version = AppxManagementDataContract.VersionNotInstalled; currentState.InstallDate = ""; } AppxManagementDataContract.AppReportedState reportedState = null; try { Logger.Log("-> installing " + desiredState.packageFamilyName + " from " + desiredState.appxSource, LoggingLevel.Verbose); if (String.IsNullOrEmpty(desiredState.appxSource)) { throw new Error(ErrorCodes.INVALID_DESIRED_APPX_SRC, "Cannot install appx without a source."); } var requestData = new AppInstallRequestData(); requestData.PackageFamilyName = desiredState.packageFamilyName; requestData.StartUp = AppUtils.StartUpTypeToMessage(desiredState.startUp); // Downloading dependencies... Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Downloading...", LoggingLevel.Verbose); if (!String.IsNullOrEmpty(desiredState.depsSources)) { string[] depsSources = desiredState.depsSources.Split(';'); for (int i = 0; i < depsSources.Length; ++i) { IoTDMClient.BlobInfo dependencyBlob = IoTDMClient.BlobInfo.BlobInfoFromSource(connectionString, depsSources[i]); Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Downloading " + dependencyBlob.BlobName, LoggingLevel.Verbose); var dependencyPath = await dependencyBlob.DownloadToTempAsync(this._systemConfiguratorProxy); Logger.Log(dependencyPath, LoggingLevel.Verbose); requestData.Dependencies.Add(dependencyPath); } } // Downloading certificates... Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Downloading appx certificate...", LoggingLevel.Verbose); IoTDMClient.BlobInfo certificateBlob = IoTDMClient.BlobInfo.BlobInfoFromSource(connectionString, desiredState.certSource); requestData.CertFile = await certificateBlob.DownloadToTempAsync(this._systemConfiguratorProxy); requestData.CertStore = desiredState.certStore; // Downloading appx... Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Downloading appx...", LoggingLevel.Verbose); IoTDMClient.BlobInfo appxBlob = IoTDMClient.BlobInfo.BlobInfoFromSource(connectionString, desiredState.appxSource); requestData.AppxPath = await appxBlob.DownloadToTempAsync(this._systemConfiguratorProxy); requestData.IsDMSelfUpdate = selfUpdate; // Installing appx... Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Installing appx...", LoggingLevel.Verbose); AppInstallResponse response = await InstallAppAsync(requestData); if (response.data.pending) { Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Installing appx is pending...", LoggingLevel.Verbose); Debug.Assert(selfUpdate); reportedState = new AppxManagementDataContract.AppReportedState(desiredState.packageFamilyId, desiredState.packageFamilyName, CommonDataContract.JsonPending, AppUtils.StartUpTypeFromMessage(response.data.startUp), response.data.installDate, 0, null, JsonReport.Report); _stateToReport[desiredState.packageFamilyId] = reportedState; return; } else { Logger.Log(DateTime.Now.ToString("HH:mm:ss") + " Done installing appx...", LoggingLevel.Verbose); Error e = null; if (desiredState.version.ToString() != response.data.version) { if (currentState.Version == response.data.version) { e = new Error(ErrorCodes.INVALID_INSTALLED_APP_VERSION_UNCHANGED, "Installating the supplied appx succeeded, but the new app version is not the desired version, and is the same as the old app version."); } else { e = new Error(ErrorCodes.INVALID_INSTALLED_APP_VERSION_UNEXPECTED, "Installating the supplied appx succeeded, but the new app version is not the desired version."); } } reportedState = new AppxManagementDataContract.AppReportedState(desiredState.packageFamilyId, desiredState.packageFamilyName, response.data.version, AppUtils.StartUpTypeFromMessage(response.data.startUp), response.data.installDate, (e != null? e.HResult : 0), (e != null ? e.Message : null), JsonReport.Report); _stateToReport[desiredState.packageFamilyId] = reportedState; return; } } catch (Error e) { reportedState = new AppxManagementDataContract.AppReportedState(desiredState.packageFamilyId, desiredState.packageFamilyName, currentState.Version, AppUtils.StartUpTypeFromMessage(currentState.StartUp), currentState.InstallDate, // install date e.HResult, e.Message, JsonReport.Report); } catch (Exception e) { reportedState = new AppxManagementDataContract.AppReportedState(desiredState.packageFamilyId, desiredState.packageFamilyName, currentState.Version, AppUtils.StartUpTypeFromMessage(currentState.StartUp), currentState.InstallDate, // install date e.HResult, e.Message, JsonReport.Report); } _stateToReport[desiredState.packageFamilyId] = reportedState; throw new Exception("Failed to install " + desiredState.packageFamilyName); }