/// <summary> /// Submits the http get request to the specified uri. /// </summary> /// <param name="uri">The uri to which the get request will be issued.</param> /// <returns>Response data as a stream.</returns> #pragma warning disable 1998 private async Task <Stream> GetAsync(Uri uri) { IBuffer dataBuffer = null; HttpBaseProtocolFilter requestSettings = new HttpBaseProtocolFilter(); requestSettings.AllowUI = false; if (this.deviceConnection.Credentials != null) { requestSettings.ServerCredential = new PasswordCredential(); requestSettings.ServerCredential.UserName = this.deviceConnection.Credentials.UserName; requestSettings.ServerCredential.Password = this.deviceConnection.Credentials.Password; } using (HttpClient client = new HttpClient(requestSettings)) { this.ApplyHttpHeaders(client, HttpMethods.Get); using (HttpResponseMessage response = await client.GetAsync(uri)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } using (IHttpContent messageContent = response.Content) { dataBuffer = await messageContent.ReadAsBufferAsync(); } } } return((dataBuffer != null) ? dataBuffer.AsStream() : null); }
/// <summary> /// Submits the http put request to the specified uri. /// </summary> /// <param name="client">The HTTP client to use.</param> /// <param name="uri">The uri to which the put request will be issued.</param> /// <param name="body">The HTTP content comprising the body of the request.</param> /// <returns>Task tracking the PUT completion.</returns> public static async Task <Stream> PutAsync( IHttpClient client, Uri uri, HttpContent body = null) { MemoryStream dataStream = null; using (HttpResponseMessage response = await client.PutAsync(uri, body).ConfigureAwait(false)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } if (response.Content != null) { using (HttpContent content = response.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; } } } return(dataStream); }
private async Task <HttpResponseMessage> Wrap(HttpMethods method, Func <HttpClient, Task <HttpResponseMessage> > func) { var handler = new HttpClientHandler { UseDefaultCredentials = false, Credentials = this.credentials, ServerCertificateCustomValidationCallback = this.serverCertificateValidation }; using (HttpClient client = new HttpClient(handler)) { this.ApplyHttpHeaders(client, method); HttpResponseMessage response = await func(client).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); return(response); } }
/// <summary> /// Initializes a new instance of the <see cref="DevicePortalException"/> class. /// </summary> /// <param name="responseMessage">Http response message.</param> /// <param name="message">Optional exception message.</param> /// <param name="innerException">Optional inner exception.</param> /// <returns>async task</returns> public static async Task <DevicePortalException> CreateAsync( HttpResponseMessage responseMessage, string message = "", Exception innerException = null) { DevicePortalException error = new DevicePortalException( responseMessage.StatusCode, responseMessage.ReasonPhrase, responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null, message, innerException); try { if (responseMessage.Content != null) { Stream dataStream = null; using (HttpContent content = responseMessage.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we point the stream at the origin. dataStream.Position = 0; } if (dataStream != null) { HttpErrorResponse errorResponse = dataStream.ReadJson <HttpErrorResponse>(); if (errorResponse != null) { error.HResult = errorResponse.ErrorCode; error.Reason = errorResponse.ErrorMessage; // If we didn't get the Hresult and reason from these properties, try the other ones. if (error.HResult == 0) { error.HResult = errorResponse.Code; } if (string.IsNullOrEmpty(error.Reason)) { error.Reason = errorResponse.Reason; } } } } } catch (Exception) { // Do nothing if we fail to get additional error details from the response body. } return(error); }
/// <summary> /// Submits the http post request to the specified uri. /// </summary> /// <param name="uri">The uri to which the post request will be issued.</param> /// <param name="requestStream">Optional stream containing data for the request body.</param> /// <param name="requestStreamContentType">The type of that request body data.</param> /// <returns>Task tracking the completion of the POST request</returns> private async Task <Stream> PostAsync( Uri uri, Stream requestStream = null, string requestStreamContentType = null) { StreamContent requestContent = null; MemoryStream dataStream = null; if (requestStream != null) { requestContent = new StreamContent(requestStream); requestContent.Headers.Remove(ContentTypeHeaderName); requestContent.Headers.TryAddWithoutValidation(ContentTypeHeaderName, requestStreamContentType); } WebRequestHandler requestSettings = new WebRequestHandler(); requestSettings.UseDefaultCredentials = false; requestSettings.Credentials = this.deviceConnection.Credentials; requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(requestSettings)) { this.ApplyHttpHeaders(client, HttpMethods.Post); Task <HttpResponseMessage> postTask = TestHelpers.MockHttpResponder.PostAsync(uri, requestContent); await postTask.ConfigureAwait(false); postTask.Wait(); using (HttpResponseMessage response = postTask.Result) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } if (response.Content != null) { using (HttpContent content = response.Content) { dataStream = new MemoryStream(); Task copyTask = content.CopyToAsync(dataStream); await copyTask.ConfigureAwait(false); copyTask.Wait(); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; } } } } return(dataStream); }
/// <summary> /// Sends a message to the server. /// </summary> /// <param name="message">The message to send.</param> /// <returns>The task of sending the message to the websocket</returns> private async Task SendMessageInternalAsync(string message) { await this.webSocketTask.ConfigureAwait(false); this.webSocketTask.Wait(); using (HttpResponseMessage response = this.webSocketTask.Result) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } } }
/// <summary> /// Submits the http post request to the specified uri. /// </summary> /// <param name="uri">The uri to which the post request will be issued.</param> /// <param name="requestStream">Optional stream containing data for the request body.</param> /// <param name="requestStreamContentType">The type of that request body data.</param> /// <returns>Task tracking the completion of the POST request</returns> #pragma warning disable 1998 private async Task <Stream> PostAsync( Uri uri, Stream requestStream = null, string requestStreamContentType = null) { HttpStreamContent requestContent = null; IBuffer dataBuffer = null; if (requestStream != null) { requestContent = new HttpStreamContent(requestStream.AsInputStream()); requestContent.Headers.Remove(ContentTypeHeaderName); requestContent.Headers.TryAppendWithoutValidation(ContentTypeHeaderName, requestStreamContentType); } HttpBaseProtocolFilter httpFilter = new HttpBaseProtocolFilter(); httpFilter.AllowUI = false; if (this.deviceConnection.Credentials != null) { httpFilter.ServerCredential = new PasswordCredential(); httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName; httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password; } using (HttpClient client = new HttpClient(httpFilter)) { this.ApplyHttpHeaders(client, HttpMethods.Post); using (HttpResponseMessage response = await client.PostAsync(uri, requestContent)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); if (response.Content != null) { using (IHttpContent messageContent = response.Content) { dataBuffer = await messageContent.ReadAsBufferAsync(); } } } } return((dataBuffer != null) ? dataBuffer.AsStream() : null); }
/// <summary> /// Submits the http post request to the specified uri. /// </summary> /// <param name="uri">The uri to which the post request will be issued.</param> /// <param name="requestContent">Optional content containing data for the request body.</param> /// <returns>Task tracking the completion of the POST request</returns> public async Task <Stream> PostAsync( Uri uri, HttpContent requestContent) { MemoryStream responseDataStream = null; WebRequestHandler requestSettings = new WebRequestHandler(); requestSettings.UseDefaultCredentials = false; requestSettings.Credentials = this.deviceConnection.Credentials; requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(requestSettings)) { client.Timeout = TimeSpan.FromMilliseconds(-1); this.ApplyHttpHeaders(client, HttpMethods.Post); using (HttpResponseMessage response = await client.PostAsync(uri, requestContent).ConfigureAwait(false)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); if (response.Content != null) { using (HttpContent responseContent = response.Content) { responseDataStream = new MemoryStream(); await responseContent.CopyToAsync(responseDataStream).ConfigureAwait(false); // Ensure we return with the stream pointed at the origin. responseDataStream.Position = 0; if (responseDataStream.Length == 0) { responseDataStream = null; } } } } } return(responseDataStream); }
/// <summary> /// Submits the http delete request to the specified uri. /// </summary> /// <param name="uri">The uri to which the delete request will be issued.</param> /// <returns>Task tracking HTTP completion</returns> private async Task <Stream> DeleteAsync(Uri uri) { MemoryStream dataStream = null; WebRequestHandler requestSettings = new WebRequestHandler(); requestSettings.UseDefaultCredentials = false; requestSettings.Credentials = this.deviceConnection.Credentials; requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(requestSettings)) { this.ApplyHttpHeaders(client, HttpMethods.Delete); Task <HttpResponseMessage> deleteTask = TestHelpers.MockHttpResponder.DeleteAsync(uri); await deleteTask.ConfigureAwait(false); deleteTask.Wait(); using (HttpResponseMessage response = deleteTask.Result) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } if (response.Content != null) { using (HttpContent content = response.Content) { dataStream = new MemoryStream(); Task copyTask = content.CopyToAsync(dataStream); await copyTask.ConfigureAwait(false); copyTask.Wait(); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; } } } } return(dataStream); }
/// <summary> /// Submits the http put request to the specified uri. /// </summary> /// <param name="uri">The uri to which the put request will be issued.</param> /// <param name="body">The HTTP content comprising the body of the request.</param> /// <returns>Task tracking the PUT completion.</returns> #pragma warning disable 1998 public async Task <Stream> PutAsync( Uri uri, IHttpContent body = null) { IBuffer dataBuffer = null; using (var httpFilter = new HttpBaseProtocolFilter()) { httpFilter.AllowUI = false; if (this.deviceConnection.Credentials != null) { httpFilter.ServerCredential = new PasswordCredential(); httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName; httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password; } using (HttpClient client = new HttpClient(httpFilter)) { this.ApplyHttpHeaders(client, HttpMethods.Put); // Send the request using (HttpResponseMessage response = await client.PutAsync(uri, body)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); if (response.Content != null) { using (IHttpContent messageContent = response.Content) { dataBuffer = await messageContent.ReadAsBufferAsync(); } } } } } return((dataBuffer != null) ? dataBuffer.AsStream() : null); }
/// <summary> /// Submits the http put request to the specified uri. /// </summary> /// <param name="uri">The uri to which the put request will be issued.</param> /// <param name="body">The HTTP content comprising the body of the request.</param> /// <returns>Task tracking the PUT completion.</returns> private async Task <Stream> PutAsync( Uri uri, HttpContent body = null) { MemoryStream dataStream = null; WebRequestHandler requestSettings = new WebRequestHandler(); requestSettings.UseDefaultCredentials = false; requestSettings.Credentials = this.deviceConnection.Credentials; requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(requestSettings)) { this.ApplyHttpHeaders(client, HttpMethods.Put); // Send the request using (HttpResponseMessage response = await client.PutAsync(uri, body).ConfigureAwait(false)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); if (response.Content != null) { using (HttpContent content = response.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; } } } } return(dataStream); }
#pragma warning restore 1998 /// <summary> /// Starts listening for messages from the websocket. /// Once they are received they are parsed and the WebSocketMessageReceived event is raised. /// </summary> /// <returns>The task of listening for messages from the websocket.</returns> private async Task StartListeningForMessagesInternalAsync() { this.IsListeningForMessages = true; this.keepListeningForMessages = true; try { while (this.keepListeningForMessages) { await this.webSocketTask.ConfigureAwait(false); using (HttpResponseMessage response = this.webSocketTask.Result) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } using (HttpContent content = response.Content) { MemoryStream dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; this.ConvertStreamToMessage(dataStream); } } } } catch { } finally { this.stoppedReceivingMessages.Set(); this.IsListeningForMessages = false; } }
/// <summary> /// Submits the http get request to the specified uri. /// </summary> /// <param name="uri">The uri to which the get request will be issued.</param> /// <returns>Response data as a stream.</returns> public async Task <Stream> GetAsync( Uri uri) { HttpClient client = null; HttpResponseMessage response = null; try { WebRequestHandler handler = new WebRequestHandler(); handler.UseDefaultCredentials = false; handler.Credentials = this.deviceConnection.Credentials; handler.ServerCertificateValidationCallback = this.ServerCertificateValidation; client = new HttpClient(handler); this.ApplyHttpHeaders(client, HttpMethods.Get); response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } this.RetrieveCsrfToken(response); if (response.Content == null) { throw new DevicePortalException(System.Net.HttpStatusCode.NoContent, "", uri); } return(await response.Content.ReadAsStreamAsync()); } catch (Exception) { response?.Dispose(); client?.Dispose(); throw; } }
/// <summary> /// Submits the http get request to the specified uri. /// </summary> /// <param name="uri">The uri to which the get request will be issued.</param> /// <returns>Response data as a stream.</returns> private async Task <Stream> GetAsync( Uri uri) { MemoryStream dataStream = null; WebRequestHandler handler = new WebRequestHandler(); handler.UseDefaultCredentials = false; handler.Credentials = this.deviceConnection.Credentials; handler.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(handler)) { this.ApplyHttpHeaders(client, HttpMethods.Get); using (HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false)) { if (!response.IsSuccessStatusCode) { throw await DevicePortalException.CreateAsync(response); } using (HttpContent content = response.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; } } } return(dataStream); }
/// <summary> /// Gets the status of a pending or most recent installation, if any. /// </summary> /// <returns>The status</returns> public async Task <ApplicationInstallStatus> GetInstallStatusAsync() { ApplicationInstallStatus status = ApplicationInstallStatus.None; Uri uri = Utilities.BuildEndpoint( this.deviceConnection.Connection, InstallStateApi); WebRequestHandler handler = new WebRequestHandler(); handler.UseDefaultCredentials = false; handler.Credentials = this.deviceConnection.Credentials; handler.ServerCertificateValidationCallback = this.ServerCertificateValidation; using (HttpClient client = new HttpClient(handler)) { this.ApplyHttpHeaders(client, HttpMethods.Get); using (HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false)) { if (response.IsSuccessStatusCode) { if (response.StatusCode == HttpStatusCode.OK) { // Status code: 200 if (response.Content == null) { status = ApplicationInstallStatus.Completed; } else { // If we have a response body, it's possible this was an error // (even though we got an HTTP 200). Stream dataStream = null; using (HttpContent content = response.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we point the stream at the origin. dataStream.Position = 0; } if (dataStream != null) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse)); HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream); if (errorResponse.Success) { status = ApplicationInstallStatus.Completed; } else { throw new DevicePortalException(response.StatusCode, errorResponse, uri); } } else { throw new DevicePortalException(response.StatusCode, "Failed to deserialize GetInstallStatus response."); } } } else if (response.StatusCode == HttpStatusCode.NoContent) { // Status code: 204 status = ApplicationInstallStatus.InProgress; } } else { throw await DevicePortalException.CreateAsync(response); } } } return(status); }
/// <summary> /// API for getting installation status. /// </summary> /// <returns>The status</returns> #pragma warning disable 1998 public async Task <ApplicationInstallStatus> GetInstallStatusAsync() { ApplicationInstallStatus status = ApplicationInstallStatus.None; Uri uri = Utilities.BuildEndpoint( this.deviceConnection.Connection, InstallStateApi); HttpBaseProtocolFilter httpFilter = new HttpBaseProtocolFilter(); httpFilter.AllowUI = false; if (this.deviceConnection.Credentials != null) { httpFilter.ServerCredential = new PasswordCredential(); httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName; httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password; } using (HttpClient client = new HttpClient(httpFilter)) { this.ApplyHttpHeaders(client, HttpMethods.Get); using (HttpResponseMessage response = await client.GetAsync(uri)) { if (response.IsSuccessStatusCode) { if (response.StatusCode == HttpStatusCode.Ok) { // Status code: 200 if (response.Content != null) { Stream dataStream = null; IBuffer dataBuffer = null; using (IHttpContent messageContent = response.Content) { dataBuffer = await messageContent.ReadAsBufferAsync(); if (dataBuffer != null) { dataStream = dataBuffer.AsStream(); } } if (dataStream != null) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse)); HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream); if (errorResponse.Success) { status = ApplicationInstallStatus.Completed; } else { throw new DevicePortalException(response.StatusCode, errorResponse, uri); } } else { throw new DevicePortalException(HttpStatusCode.Conflict, "Failed to deserialize GetInstallStatus response."); } } } else if (response.StatusCode == HttpStatusCode.NoContent) { // Status code: 204 status = ApplicationInstallStatus.InProgress; } } else { throw await DevicePortalException.CreateAsync(response); } } } return(status); }
/// <summary> /// Installs an application /// </summary> /// <param name="appName">Friendly name (ex: Hello World) of the application. If this parameter is not provided, the name of the package is assumed to be the app name.</param> /// <param name="packageFileName">Full name of the application package file.</param> /// <param name="dependencyFileNames">List containing the full names of any required dependency files.</param> /// <param name="certificateFileName">Full name of the optional certificate file.</param> /// <param name="stateCheckIntervalMs">How frequently we should check the installation state.</param> /// <param name="timeoutInMinutes">Operation timeout.</param> /// <param name="uninstallPreviousVersion">Indicate whether or not the previous app version should be uninstalled prior to installing.</param> /// <remarks>InstallApplication sends ApplicationInstallStatus events to indicate the current progress in the installation process. /// Some applications may opt to not register for the AppInstallStatus event and await on InstallApplication.</remarks> /// <returns>Task for tracking completion of install initialization.</returns> public async Task InstallApplication( string appName, string packageFileName, List <string> dependencyFileNames, string certificateFileName = null, short stateCheckIntervalMs = 500, short timeoutInMinutes = 15, bool uninstallPreviousVersion = true) { string installPhaseDescription = string.Empty; try { FileInfo packageFile = new FileInfo(packageFileName); // If appName was not provided, use the package file name if (string.IsNullOrEmpty(appName)) { appName = packageFile.Name; } // Uninstall the application's previous version, if one exists. if (uninstallPreviousVersion) { installPhaseDescription = string.Format("Uninstalling any previous version of {0}", appName); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.UninstallingPreviousVersion, installPhaseDescription); AppPackages installedApps = await this.GetInstalledAppPackages(); foreach (PackageInfo package in installedApps.Packages) { if (package.Name == appName) { await this.UninstallApplication(package.FullName); break; } } } // Create the API endpoint and generate a unique boundary string. Uri uri; string boundaryString; this.CreateAppInstallEndpointAndBoundaryString( packageFile.Name, out uri, out boundaryString); using (MemoryStream dataStream = new MemoryStream()) { byte[] data; // Copy the application package. installPhaseDescription = string.Format("Copying: {0}", packageFile.Name); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.CopyingFile, installPhaseDescription); data = Encoding.ASCII.GetBytes(string.Format("--{0}\r\n", boundaryString)); dataStream.Write(data, 0, data.Length); CopyFileToRequestStream(packageFile, dataStream); // Copy dependency files, if any. foreach (string dependencyFile in dependencyFileNames) { FileInfo fi = new FileInfo(dependencyFile); installPhaseDescription = string.Format("Copying: {0}", fi.Name); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.CopyingFile, installPhaseDescription); data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", boundaryString)); dataStream.Write(data, 0, data.Length); CopyFileToRequestStream(fi, dataStream); } // Copy the certificate file, if provided. if (!string.IsNullOrEmpty(certificateFileName)) { FileInfo fi = new FileInfo(certificateFileName); installPhaseDescription = string.Format("Copying: {0}", fi.Name); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.CopyingFile, installPhaseDescription); data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", boundaryString)); dataStream.Write(data, 0, data.Length); CopyFileToRequestStream(fi, dataStream); } // Close the installation request data. data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}--\r\n", boundaryString)); dataStream.Write(data, 0, data.Length); dataStream.Position = 0; string contentType = string.Format("multipart/form-data; boundary={0}", boundaryString); // Make the HTTP request. await this.Post(uri, dataStream, contentType); } // Poll the status until complete. ApplicationInstallStatus status = ApplicationInstallStatus.InProgress; do { installPhaseDescription = string.Format("Installing {0}", appName); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.Installing, installPhaseDescription); await Task.Delay(TimeSpan.FromMilliseconds(stateCheckIntervalMs)); status = await this.GetInstallStatus(); }while (status == ApplicationInstallStatus.InProgress); installPhaseDescription = string.Format("{0} installed successfully", appName); this.SendAppInstallStatus( ApplicationInstallStatus.Completed, ApplicationInstallPhase.Idle, installPhaseDescription); } catch (Exception e) { DevicePortalException dpe = e as DevicePortalException; if (dpe != null) { this.SendAppInstallStatus( ApplicationInstallStatus.Failed, ApplicationInstallPhase.Idle, string.Format("Failed to install {0}: {1}", appName, dpe.Reason)); } else { this.SendAppInstallStatus( ApplicationInstallStatus.Failed, ApplicationInstallPhase.Idle, string.Format("Failed to install {0}: {1}", appName, installPhaseDescription)); } } }
/// <summary> /// Installs an application /// </summary> /// <param name="appName">Friendly name (ex: Hello World) of the application. If this parameter is not provided, the name of the package is assumed to be the app name.</param> /// <param name="packageFileName">Full name of the application package file.</param> /// <param name="dependencyFileNames">List containing the full names of any required dependency files.</param> /// <param name="certificateFileName">Full name of the optional certificate file.</param> /// <param name="stateCheckIntervalMs">How frequently we should check the installation state.</param> /// <param name="timeoutInMinutes">Operation timeout.</param> /// <param name="uninstallPreviousVersion">Indicate whether or not the previous app version should be uninstalled prior to installing.</param> /// <remarks>InstallApplication sends ApplicationInstallStatus events to indicate the current progress in the installation process. /// Some applications may opt to not register for the AppInstallStatus event and await on InstallApplication.</remarks> /// <returns>Task for tracking completion of install initialization.</returns> public async Task InstallApplicationAsync( string appName, string packageFileName, List <string> dependencyFileNames, string certificateFileName = null, short stateCheckIntervalMs = 500, short timeoutInMinutes = 15, bool uninstallPreviousVersion = true) { string installPhaseDescription = string.Empty; try { FileInfo packageFile = new FileInfo(packageFileName); // If appName was not provided, use the package file name if (string.IsNullOrEmpty(appName)) { appName = packageFile.Name; } // Uninstall the application's previous version, if one exists. if (uninstallPreviousVersion) { installPhaseDescription = string.Format("Uninstalling any previous version of {0}", appName); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.UninstallingPreviousVersion, installPhaseDescription); AppPackages installedApps = await this.GetInstalledAppPackagesAsync(); foreach (PackageInfo package in installedApps.Packages) { if (package.Name == appName) { await this.UninstallApplicationAsync(package.FullName); break; } } } // Create the API endpoint and generate a unique boundary string. Uri uri; string boundaryString; this.CreateAppInstallEndpointAndBoundaryString( packageFile.Name, out uri, out boundaryString); installPhaseDescription = string.Format("Copying: {0}", packageFile.Name); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.CopyingFile, installPhaseDescription); var content = new HttpMultipartFileContent(); await content.Add(packageFile.FullName); await content.AddRange(dependencyFileNames); await content.Add(certificateFileName); await this.PostAsync(uri, content); // Poll the status until complete. ApplicationInstallStatus status = ApplicationInstallStatus.InProgress; do { installPhaseDescription = string.Format("Installing {0}", appName); this.SendAppInstallStatus( ApplicationInstallStatus.InProgress, ApplicationInstallPhase.Installing, installPhaseDescription); await Task.Delay(TimeSpan.FromMilliseconds(stateCheckIntervalMs)); status = await this.GetInstallStatusAsync().ConfigureAwait(false); }while (status == ApplicationInstallStatus.InProgress); installPhaseDescription = string.Format("{0} installed successfully", appName); this.SendAppInstallStatus( ApplicationInstallStatus.Completed, ApplicationInstallPhase.Idle, installPhaseDescription); } catch (Exception e) { DevicePortalException dpe = e as DevicePortalException; if (dpe != null) { this.SendAppInstallStatus( ApplicationInstallStatus.Failed, ApplicationInstallPhase.Idle, string.Format("Failed to install {0}: {1}", appName, dpe.Reason)); } else { this.SendAppInstallStatus( ApplicationInstallStatus.Failed, ApplicationInstallPhase.Idle, string.Format("Failed to install {0}: {1}", appName, installPhaseDescription)); } } }
/// <summary> /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor. /// </summary> /// <param name="ssid">Optional network SSID.</param> /// <param name="ssidKey">Optional network key.</param> /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param> /// <param name="rawManualCertificate">Allows specifying the raw certificate manually. This allows loading it from a local file or loading an override for a web proxy.</param> /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process. /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks> /// <returns>Task for tracking the connect.</returns> public async Task Connect( string ssid = null, string ssidKey = null, bool updateConnection = true, byte[] rawManualCertificate = null) { #if WINDOWS_UWP this.ConnectionHttpStatusCode = HttpStatusCode.Ok; #else this.ConnectionHttpStatusCode = HttpStatusCode.OK; #endif // WINDOWS_UWP string connectionPhaseDescription = string.Empty; try { // Get the device certificate bool certificateAcquired = false; if (rawManualCertificate == null) { try { connectionPhaseDescription = "Acquiring device certificate"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.AcquiringCertificate, connectionPhaseDescription); this.deviceConnection.SetDeviceCertificate(await this.GetDeviceCertificate()); certificateAcquired = true; } catch { // This device does not support the root certificate endpoint. this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.AcquiringCertificate, "No device certificate available"); } } else { #if WINDOWS_UWP this.deviceConnection.SetDeviceCertificate(new Certificate(rawManualCertificate.AsBuffer())); #else this.deviceConnection.SetDeviceCertificate(new X509Certificate2(rawManualCertificate)); #endif // WINDOWS_UWP certificateAcquired = true; } // Get the device family and operating system information. connectionPhaseDescription = "Requesting operating system information"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.RequestingOperatingSystemInformation, connectionPhaseDescription); this.deviceConnection.Family = await this.GetDeviceFamily(); this.deviceConnection.OsInfo = await this.GetOperatingSystemInformation(); // Default to using HTTPS if we were successful in acquiring the device's root certificate. bool requiresHttps = certificateAcquired; // HoloLens is the only device that supports the GetIsHttpsRequired method. if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens) { // Check to see if HTTPS is required to communicate with this device. connectionPhaseDescription = "Checking secure connection requirements"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.DeterminingConnectionRequirements, connectionPhaseDescription); requiresHttps = await this.GetIsHttpsRequired(); } // Connect the device to the specified network. if (!string.IsNullOrWhiteSpace(ssid)) { connectionPhaseDescription = string.Format("Connecting to {0} network", ssid); this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.ConnectingToTargetNetwork, connectionPhaseDescription); WifiInterfaces wifiInterfaces = await this.GetWifiInterfaces(); // TODO - consider what to do if there is more than one wifi interface on a device await this.ConnectToWifiNetwork(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey); } // Get the device's IP configuration and update the connection as appropriate. if (updateConnection) { connectionPhaseDescription = "Updating device connection"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.UpdatingDeviceAddress, connectionPhaseDescription); this.deviceConnection.UpdateConnection(await this.GetIpConfig(), requiresHttps); } this.SendConnectionStatus( DeviceConnectionStatus.Connected, DeviceConnectionPhase.Idle, "Device connection established"); } catch (Exception e) { DevicePortalException dpe = e as DevicePortalException; if (dpe != null) { this.ConnectionHttpStatusCode = dpe.StatusCode; } else { this.ConnectionHttpStatusCode = HttpStatusCode.Conflict; } this.SendConnectionStatus( DeviceConnectionStatus.Failed, DeviceConnectionPhase.Idle, string.Format("Device connection failed: {0}", connectionPhaseDescription)); } }
/// <summary> /// Initializes a new instance of the <see cref="DevicePortalException"/> class. /// </summary> /// <param name="responseMessage">Http response message.</param> /// <param name="message">Optional exception message.</param> /// <param name="innerException">Optional inner exception.</param> /// <returns>async task</returns> public static async Task <DevicePortalException> CreateAsync( HttpResponseMessage responseMessage, string message = "", Exception innerException = null) { DevicePortalException error = new DevicePortalException( responseMessage.StatusCode, responseMessage.ReasonPhrase, responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null, message, innerException); try { if (responseMessage.Content != null) { Stream dataStream = null; #if !WINDOWS_UWP using (HttpContent content = responseMessage.Content) { dataStream = new MemoryStream(); await content.CopyToAsync(dataStream).ConfigureAwait(false); // Ensure we point the stream at the origin. dataStream.Position = 0; } #else // WINDOWS_UWP IBuffer dataBuffer = null; using (IHttpContent messageContent = responseMessage.Content) { dataBuffer = await messageContent.ReadAsBufferAsync(); if (dataBuffer != null) { dataStream = dataBuffer.AsStream(); } } #endif // WINDOWS_UWP if (dataStream != null) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse)); HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream); error.HResult = errorResponse.ErrorCode; error.Reason = errorResponse.ErrorMessage; // If we didn't get the Hresult and reason from these properties, try the other ones. if (error.HResult == 0) { error.HResult = errorResponse.Code; } if (string.IsNullOrEmpty(error.Reason)) { error.Reason = errorResponse.Reason; } dataStream.Dispose(); } } } catch (Exception) { // Do nothing if we fail to get additional error details from the response body. } return(error); }
/// <summary> /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor. /// </summary> /// <param name="ssid">Optional network SSID.</param> /// <param name="ssidKey">Optional network key.</param> /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param> /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process. /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks> /// <returns>Task for tracking the connect.</returns> public async Task Connect( string ssid = null, string ssidKey = null, bool updateConnection = true) { #if WINDOWS_UWP this.ConnectionHttpStatusCode = HttpStatusCode.Ok; #else this.ConnectionHttpStatusCode = HttpStatusCode.OK; #endif // WINDOWS_UWP string connectionPhaseDescription = string.Empty; try { // Get the device family and operating system information. connectionPhaseDescription = "Requesting operating system information"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.RequestingOperatingSystemInformation, connectionPhaseDescription); this.deviceConnection.Family = await this.GetDeviceFamily(); this.deviceConnection.OsInfo = await this.GetOperatingSystemInformation(); // Default to using HTTPS. bool requiresHttps = true; // HoloLens is the only device that supports the GetIsHttpsRequired method. if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens) { // Check to see if HTTPS is required to communicate with this device. connectionPhaseDescription = "Checking secure connection requirements"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.DeterminingConnectionRequirements, connectionPhaseDescription); requiresHttps = await this.GetIsHttpsRequired(); } // Connect the device to the specified network. if (!string.IsNullOrWhiteSpace(ssid)) { connectionPhaseDescription = string.Format("Connecting to {0} network", ssid); this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.ConnectingToTargetNetwork, connectionPhaseDescription); WifiInterfaces wifiInterfaces = await this.GetWifiInterfaces(); // TODO - consider what to do if there is more than one wifi interface on a device await this.ConnectToWifiNetwork(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey); } // Get the device's IP configuration and update the connection as appropriate. if (updateConnection) { connectionPhaseDescription = "Updating device connection"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.UpdatingDeviceAddress, connectionPhaseDescription); this.deviceConnection.UpdateConnection(await this.GetIpConfig(), requiresHttps); } this.SendConnectionStatus( DeviceConnectionStatus.Connected, DeviceConnectionPhase.Idle, "Device connection established"); } catch (Exception e) { DevicePortalException dpe = e as DevicePortalException; if (dpe != null) { this.ConnectionHttpStatusCode = dpe.StatusCode; this.ConnectionFailedDescription = dpe.Message; } else { this.ConnectionHttpStatusCode = HttpStatusCode.Conflict; // Get to the innermost exception for our return message. Exception innermostException = e; while (innermostException.InnerException != null) { innermostException = innermostException.InnerException; } this.ConnectionFailedDescription = innermostException.Message; } this.SendConnectionStatus( DeviceConnectionStatus.Failed, DeviceConnectionPhase.Idle, string.Format("Device connection failed: {0}, {1}", connectionPhaseDescription, this.ConnectionFailedDescription)); } }
/// <summary> /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor. /// </summary> /// <param name="ssid">Optional network SSID.</param> /// <param name="ssidKey">Optional network key.</param> /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param> /// <param name="manualCertificate">A manually provided X509 Certificate for trust validation against this device.</param> /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process. /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks> /// <returns>Task for tracking the connect.</returns> public async Task ConnectAsync( string ssid = null, string ssidKey = null, bool updateConnection = false, X509Certificate2 manualCertificate = null) { this.ConnectionHttpStatusCode = HttpStatusCode.OK; string connectionPhaseDescription = string.Empty; if (manualCertificate != null) { this.SetManualCertificate(manualCertificate); } try { // Get the device family and operating system information. connectionPhaseDescription = "Requesting operating system information"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.RequestingOperatingSystemInformation, connectionPhaseDescription); this.deviceConnection.Family = await this.GetDeviceFamilyAsync().ConfigureAwait(false); this.deviceConnection.OsInfo = await this.GetOperatingSystemInformationAsync().ConfigureAwait(false); // Default to using whatever was specified in the connection. bool requiresHttps = this.IsUsingHttps(); // HoloLens is the only device that supports the GetIsHttpsRequired method. if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens) { // Check to see if HTTPS is required to communicate with this device. connectionPhaseDescription = "Checking secure connection requirements"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.DeterminingConnectionRequirements, connectionPhaseDescription); requiresHttps = await this.GetIsHttpsRequiredAsync().ConfigureAwait(false); } // Connect the device to the specified network. if (!string.IsNullOrWhiteSpace(ssid)) { connectionPhaseDescription = string.Format("Connecting to {0} network", ssid); this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.ConnectingToTargetNetwork, connectionPhaseDescription); WifiInterfaces wifiInterfaces = await this.GetWifiInterfacesAsync().ConfigureAwait(false); // TODO - consider what to do if there is more than one wifi interface on a device await this.ConnectToWifiNetworkAsync(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey).ConfigureAwait(false); } // Get the device's IP configuration and update the connection as appropriate. if (updateConnection) { connectionPhaseDescription = "Updating device connection"; this.SendConnectionStatus( DeviceConnectionStatus.Connecting, DeviceConnectionPhase.UpdatingDeviceAddress, connectionPhaseDescription); bool preservePort = true; // HoloLens and Mobile are the only devices that support USB. // They require the port to be changed when the connection is updated // to WiFi. if ((this.Platform == DevicePortalPlatforms.HoloLens) || (this.Platform == DevicePortalPlatforms.Mobile)) { preservePort = false; } this.deviceConnection.UpdateConnection( await this.GetIpConfigAsync().ConfigureAwait(false), requiresHttps, preservePort); } this.SendConnectionStatus( DeviceConnectionStatus.Connected, DeviceConnectionPhase.Idle, "Device connection established"); } catch (Exception e) { DevicePortalException dpe = e as DevicePortalException; if (dpe != null) { this.ConnectionHttpStatusCode = dpe.StatusCode; this.ConnectionFailedDescription = dpe.Message; } else { this.ConnectionHttpStatusCode = HttpStatusCode.Conflict; // Get to the innermost exception for our return message. Exception innermostException = e; while (innermostException.InnerException != null) { innermostException = innermostException.InnerException; await Task.Yield(); } this.ConnectionFailedDescription = innermostException.Message; } this.SendConnectionStatus( DeviceConnectionStatus.Failed, DeviceConnectionPhase.Idle, string.Format("Device connection failed: {0}, {1}", connectionPhaseDescription, this.ConnectionFailedDescription)); } }