/// <summary> /// Uninstalls the target application on the target device /// </summary> /// <param name="appInfo">Optional cached <see cref="Microsoft.MixedReality.Toolkit.WindowsDevicePortal.ApplicationInfo"/>.</param> /// <returns>True, if uninstall was a success.</returns> public static async Task <bool> UninstallAppAsync(string packageName, DeviceInfo targetDevice, ApplicationInfo appInfo = null) { Debug.Assert(!string.IsNullOrEmpty(packageName)); if (appInfo == null) { appInfo = await GetApplicationInfoAsync(packageName, targetDevice); } if (appInfo == null) { Debug.LogWarning($"Application '{packageName}' not found"); return(false); } Debug.Log($"Attempting to uninstall {packageName} on {targetDevice.ToString()}..."); string query = $"{string.Format(InstallQuery, FinalizeUrl(targetDevice.IP))}?package={UnityWebRequest.EscapeURL(appInfo.PackageFullName)}"; var response = await Rest.DeleteAsync(query, targetDevice.Authorization); if (response.Successful) { Debug.Log($"Successfully uninstalled {packageName} on {targetDevice.ToString()}."); } else if (!response.Successful) { if (response.ResponseCode == 403 && await RefreshCsrfTokenAsync(targetDevice)) { return(await UninstallAppAsync(packageName, targetDevice)); } Debug.LogError($"Failed to uninstall {packageName} on {targetDevice.ToString()}"); Debug.LogError(response.ResponseBody); return(false); } return(true); }
/// <summary> /// Installs the target application on the target device. /// </summary> /// <param name="waitForDone">Should the thread wait until installation is complete?</param> /// <returns>True, if Installation was a success.</returns> public static async Task <bool> InstallAppAsync(string appFullPath, DeviceInfo targetDevice, bool waitForDone = true) { Debug.Assert(!string.IsNullOrEmpty(appFullPath)); var isAuth = await EnsureAuthenticationAsync(targetDevice); if (!isAuth) { return(false); } Debug.Log($"Starting app install on {targetDevice.ToString()}..."); // Calculate the cert and dependency paths string fileName = Path.GetFileName(appFullPath); string certFullPath = Path.ChangeExtension(appFullPath, ".cer"); string certName = Path.GetFileName(certFullPath); string arch = "ARM"; if (appFullPath.Contains("x86")) { arch = "x86"; } else if (appFullPath.Contains("ARM64")) { arch = "ARM64"; } string depPath = $@"{Path.GetDirectoryName(appFullPath)}\Dependencies\{arch}\"; var form = new WWWForm(); try { // APPX file Debug.Assert(appFullPath != null); using (var stream = new FileStream(appFullPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new BinaryReader(stream)) { form.AddBinaryData(fileName, reader.ReadBytes((int)reader.BaseStream.Length), fileName); } } // CERT file Debug.Assert(certFullPath != null); using (var stream = new FileStream(certFullPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new BinaryReader(stream)) { form.AddBinaryData(certName, reader.ReadBytes((int)reader.BaseStream.Length), certName); } } // Dependencies IOFileInfo[] depFiles = new DirectoryInfo(depPath).GetFiles(); foreach (IOFileInfo dep in depFiles) { using (var stream = new FileStream(dep.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new BinaryReader(stream)) { string depFilename = Path.GetFileName(dep.FullName); form.AddBinaryData(depFilename, reader.ReadBytes((int)reader.BaseStream.Length), depFilename); } } } } catch (Exception e) { Debug.LogException(e); return(false); } // Query string query = $"{string.Format(InstallQuery, FinalizeUrl(targetDevice.IP))}?package={UnityWebRequest.EscapeURL(fileName)}"; var response = await Rest.PostAsync(query, form, targetDevice.Authorization); if (!response.Successful) { if (response.ResponseCode == 403 && await RefreshCsrfTokenAsync(targetDevice)) { return(await InstallAppAsync(appFullPath, targetDevice, waitForDone)); } Debug.LogError($"Failed to install {fileName} on {targetDevice.ToString()}."); return(false); } var status = AppInstallStatus.Installing; // Wait for done (if requested) while (waitForDone && status == AppInstallStatus.Installing) { status = await GetInstallStatusAsync(targetDevice); switch (status) { case AppInstallStatus.InstallSuccess: Debug.Log($"Successfully installed {fileName} on {targetDevice.ToString()}."); return(true); case AppInstallStatus.InstallFail: Debug.LogError($"Failed to install {fileName} on {targetDevice.ToString()}."); return(false); } } return(true); }