Exportar (0) Imprimir
Expandir Tudo

Excluir certificado de serviço

Atualizado: abril de 2014

A operação Delete Service Certificate exclui um certificado de serviço do repositório de certificados de um serviço hospedado.

A operação Delete Service Certificate é assíncrona. Para determinar se o serviço de gerenciamento concluiu o processamento da solicitação, chame Obter status da operação. Para obter mais informações sobre as operações assíncronas, consulte Controlando solicitações assíncronas de gerenciamento de serviço.

A solicitação Delete Service Certificate pode ser especificada da seguinte maneira. Substitua <subscription-id> por sua ID da assinatura, <service-name> pelo nome do prefixo DNS do seu serviço hospedado, <thumbprint-algorithm> pelo algoritmo para a impressão digital do certificado de serviço e <thumbprint-in-hexadecimal> pela representação hexadecimal da impressão digital:

 

Método URI de solicitação Versão HTTP

DELETE

https://management.core.windows.net/<subscription-id>/services/hostedservices/<service-name>/certificates/<thumbprint-algorithm>-<thumbprint_in_hexadecimal>

HTTP/1.1

A tabela a seguir descreve os cabeçalhos de solicitação obrigatórios e opcionais.

 

Cabeçalho de solicitação Descrição

x-ms-version

Obrigatório. Especifica a versão da operação a ser usada para esta solicitação. Este cabeçalho deve ser definido como 2009-10-01 ou por uma versão posterior. Para obter mais informações sobre cabeçalhos de controle de versão, consulte Controle de versão de gerenciamento de serviço.

A resposta inclui um código de status HTTP e um conjunto de cabeçalhos de resposta.

Como Delete Service Certificate é uma operação assíncrona, você deverá chamar Obter status da operação para determinar se a operação foi concluída, se falhou ou se ainda está em andamento.

Como Delete Service Certificate é uma operação assíncrona, sempre retornará o código de status 202 (aceitar). Para determinar o código de status da operação quando ela for concluída, chame Obter status da operação. O código de status é inserido na resposta para esta operação; se for bem-sucedida, será o código de status 200 (OK).

Para obter informações sobre códigos de status, consulte Status de Gerenciamento de Serviço e códigos de erro.

A resposta para esta operação inclui os cabeçalhos a seguir. A resposta também pode incluir cabeçalhos padrão HTTP adicionais. Todos os cabeçalhos padrão obedecem a especificação de protocolo HTTP/1.1.

 

Cabeçalho de resposta Descrição

x-ms-request-id

Um valor que identifica exclusivamente uma solicitação feita no serviço de Gerenciamento. Para uma operação assíncrona, você pode chamar Obter status da operação com o valor desse cabeçalho para determinar se a operação foi concluída, se falhou ou se ainda está em andamento. Consulte Controlando solicitações assíncronas de gerenciamento de serviço para obter mais informações.

Qualquer certificado de gerenciamento associado à assinatura especificada por <id-assinatura> pode ser usado para autenticar esta operação. Para obter mais detalhes, consulte Autenticando solicitações do gerenciamento de serviços.

Você pode excluir os certificados associados a um serviço hospedado em particular de forma programática, usando a operação Delete Service Certificate. A operação retornará imediatamente com uma ID da solicitação, quando a exclusão for executada de forma assíncrona pelo Windows Azure. Para determinar quando a operação de exclusão de certificado tiver sido concluída, você poderá sondar a operação Obter status da operação com a ID da solicitação. Isto retornará um corpo XML com um elemento Operation com um elemento Status. Isso terá um valor InProgress, Failed ou Succeeded, dependendo do status da operação de exclusão. Se você sondar até o status se tornar Failed ou Succeeded, o elemento Operation conterá um código de status no elemento StatusCode. As operações com falha conterão informações de erro adicionais no elemento Error. Consulte Obter status da operação para obter mais informações.

O exemplo a seguir é um programa de console que adiciona um certificado pfx a um serviço hospedado especificado e então exclui o certificado do serviço hospedado. Para executar o exemplo, crie um certificado de serviço e salve-o com sua chave privada como um arquivo pfx na pasta Documentos. Quando criar o certificado de serviço como um arquivo pfx, atribua a ele uma senha que posteriormente você inserirá para adicionar o certificado ao serviço hospedado. Modifique o código para atualizar a cadeia de caracteres de Version com o valor a ser usado no cabeçalho x-ms-version. Defina o valor de ManagementThumbprint como a impressão digital do certificado de gerenciamento. Defina o valor de SubscriptionId como o identificador da assinatura e defina ServiceName como o nome do prefixo DNS do seu serviço hospedado. Defina o valor de PfxFile como o nome do arquivo pfx do certificado de serviço e defina o valor de CertificateThumbprint como a impressão digital do certificado. Quando o programa for executado, ele solicitará a senha para o arquivo pfx de certificado de serviço. Então, usará a operação Adicionar certificado de serviço para adicionar o certificado ao serviço hospedado e sondará o resultado assíncrono usando a operação Obter status da operação. Quando o resultado estiver disponível, o programa usará a operação Listar certificados de serviço para exibir os certificados no serviço hospedado. Em seguida, usará a operação Delete Certificate para excluir o certificado adicionado do serviço hospedado e sondará o resultado assíncrono usando a operação Obter status da operação. Por fim, usará a operação Listar certificados de serviço para mostrar que o certificado foi removido. Consulte Criação de um certificado de serviço para o Windows Azure para obter mais informações sobre como criar um certificado, exportá-lo como um arquivo .pfx e obter sua impressão digital.

namespace Microsoft.WindowsAzure.ServiceManagementRESTAPI.Samples
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using System.Threading;
    using System.Xml;
    using System.Xml.Linq;
 
    public class Program
    {
        // Set these constants with your values to run the sample.
        private const string XMsVersion = "2011-10-01";
        private const string ManagementThumbprint = "management-certificate-thumbprint";
        private const string SubscriptionId = "subscription-identifier";
        private const string ServiceName = "service-dns-prefix-name";
        private const string PfxFile = "service-certificate-pfx-file";
        private const string CertificateThumbprint = "service-certificate-thumbprint";
 
        // This is the common namespace for all Service Management REST API XML data.
        private static XNamespace wa = "http://schemas.microsoft.com/windowsazure";
 
        /// <summary>
        /// The operation status values from PollGetOperationStatus.
        /// </summary>
        private enum OperationStatus
        {
            InProgress,
            Failed,
            Succeeded,
            TimedOut
        }
 
        /// <summary>
        /// Gets or sets the management certificate for subscription access.
        /// </summary>
        private static X509Certificate2 ManagementCertificate { get; set; }
 
        static void Main(string[] args)
        {
            try
            {
                ManagementCertificate = GetStoreCertificate(ManagementThumbprint);
 
                // Add a certificate from a particular PFX file in the users
                // documents folder:
                string certificatePath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    PfxFile);
                string certificateData = Convert.ToBase64String(
                    File.ReadAllBytes(certificatePath));
 
                Console.Write("Enter the password for {0}: ", PfxFile);
                string pfxPassword = Console.ReadLine();
 
                string requestId = AddCertificate(
                    ServiceName,
                    certificateData,
                    pfxPassword);
                Console.WriteLine(
                    "Called Add Certificate operation: requestId {0}",
                    requestId);
 
                // Loop on Get Operation Status for result of add certificate
                OperationResult result = PollGetOperationStatus(
                    requestId,
                    pollIntervalSeconds: 20,
                    timeoutSeconds: 180);
                DisplayOperationResult(requestId, result);
 
                // Display the certificates for the hosted service.
                XElement certificates = ListCertificates(ServiceName);
                Console.WriteLine(
                    "Certificates for Hosted Service {0}:{1}{2}",
                    ServiceName,
                    Environment.NewLine,
                    certificates.ToString(SaveOptions.OmitDuplicateNamespaces));
                
                // Now delete the added certificate
                requestId = DeleteCertificate(
                    ServiceName,
                    "sha1",
                    CertificateThumbprint);
                Console.WriteLine(
                    "Called Delete Certificate operation: requestId {0}",
                    requestId);
 
                // Loop on Get Operation Status for result of delete certificate
                result = PollGetOperationStatus(
                    requestId,
                    pollIntervalSeconds: 20,
                    timeoutSeconds: 180);
                DisplayOperationResult(requestId, result);
 
                // Display the certificates for the hosted service.
                certificates = ListCertificates(ServiceName);
                Console.WriteLine(
                    "Certificates for Hosted Service {0}:{1}{2}",
                    ServiceName,
                    Environment.NewLine,
                    certificates.ToString(SaveOptions.OmitDuplicateNamespaces));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception caught in Main:");
                Console.WriteLine(ex.Message);
            }
 
            Console.Write("Press any key to continue:");
            Console.ReadKey();
        }
 
        private static void DisplayOperationResult(
            string requestId, 
            OperationResult result)
        {
            switch (result.Status)
            {
                case OperationStatus.TimedOut:
                    Console.WriteLine(
                        "Poll of Get Operation Status timed out: " +
                        "Operation {0} is still in progress after {1} seconds.",
                        requestId,
                        (int)result.RunningTime.TotalSeconds);
                    break;
 
                case OperationStatus.Failed:
                    Console.WriteLine(
                        "Failed: Operation {0} failed after " +
                        "{1} seconds with status {2} ({3}) - {4}: {5}",
                        requestId,
                        (int)result.RunningTime.TotalSeconds,
                        (int)result.StatusCode,
                        result.StatusCode,
                        result.Code,
                        result.Message);
                    break;
 
                case OperationStatus.Succeeded:
                    Console.WriteLine(
                        "Succeeded: Operation {0} completed " +
                        "after {1} seconds with status {2} ({3})",
                        requestId,
                        (int)result.RunningTime.TotalSeconds,
                        (int)result.StatusCode,
                        result.StatusCode);
                    break;
            }
        }
 
        /// <summary>
        /// Calls the asynchronous Add Certificate operation in the Service 
        /// Management REST API to add a certificate to a hosted service. 
        /// Use the returned request ID value with the Get Operation Status 
        /// operation to get the final result of this operation.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to add the certificate to.</param>
        /// <param name="certificateData">The base-64 encoded contents of the .PFX file containing the certificate data.</param>
        /// <param name="password">The password to access the .PFX certificate data.</param>
        /// <returns>The request ID for use with Get Operation Status.</returns>
        private static string AddCertificate(
            string serviceName,
            string certificateData,
            string password)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/services/hostedservices/{1}/certificates";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName));
 
            // Create the request XML document
            XDocument requestBody = new XDocument(
                new XDeclaration("1.0", "UTF-8", "no"),
                new XElement(
                    wa + "CertificateFile",
                    new XElement(wa + "Data", certificateData),
                    new XElement(wa + "CertificateFormat", "pfx"),
                    new XElement(wa + "Password", password)));
 
            XDocument responseBody;
            return InvokeRequest(
                uri, "POST", HttpStatusCode.Accepted, requestBody, out responseBody);
        }
 
        /// <summary>
        /// Calls the asynchronous Delete Certificate operation in the Service 
        /// Management REST API to remove a certificate from a hosted service. 
        /// Use the returned request ID value with the Get Operation Status 
        /// operation to get the final result of this operation.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to remove the certificate from.</param>
        /// <param name="algorithm">The algorithm of the certificate to delete, for example, "sha1".</param>
        /// <param name="thumbprint">The thumbprint for the certificate to delete.</param>
        /// <returns>The request ID for use with Get Operation Status.</returns>
        private static string DeleteCertificate(
            string serviceName,
            string algorithm,
            string thumbprint)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                    "/services/hostedservices/{1}/certificates/{2}-{3}";
            Uri uri = new Uri(String.Format(
                uriFormat, SubscriptionId, serviceName, algorithm, thumbprint));
 
            XDocument responseBody;
            return InvokeRequest(
                uri, "DELETE", HttpStatusCode.Accepted, null, out responseBody);
        }
 
        /// <summary>
        /// Calls the List Certificates operation in the Service Management 
        /// REST API for the specified subscription and hosted service, and 
        /// returns the Certificates XML element from the response.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to list certificates for.</param>
        /// <returns>The HostedServices XML element from the response.</returns>
        private static XElement ListCertificates(
            string serviceName)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/services/hostedservices/{1}/certificates";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName));
            XDocument responseBody;
            InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody);
            return responseBody.Element(wa + "Certificates");
        }
 
        /// <summary>
        /// Calls the Get Operation Status operation in the Service 
        /// Management REST API for the specified subscription and requestId 
        /// and returns the Operation XML element from the response.
        /// </summary>
        /// <param name="requestId">The requestId of the operation to track.</param>
        /// <returns>The Operation XML element from the response.</returns>
        private static XElement GetOperationStatus(
            string requestId)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/operations/{1}";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, requestId));
            XDocument responseBody;
            InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody);
            return responseBody.Element(wa + "Operation");
        }
 
        /// <summary>
        /// The results from PollGetOperationStatus are passed in this struct.
        /// </summary>
        private struct OperationResult
        {
            // The status: InProgress, Failed, Succeeded, or TimedOut.
            public OperationStatus Status { get; set; }
 
            // The http status code of the requestId operation, if any.
            public HttpStatusCode StatusCode { get; set; }
 
            // The approximate running time for PollGetOperationStatus.
            public TimeSpan RunningTime { get; set; }
 
            // The error code for the failed operation.
            public string Code { get; set; }
 
            // The message for the failed operation.
            public string Message { get; set; }
        }
 
        /// <summary>
        /// Polls Get Operation Status for the operation specified by requestId
        /// every pollIntervalSeconds until timeoutSeconds have passed or the
        /// operation has returned a Failed or Succeeded status. 
        /// </summary>
        /// <param name="requestId">The requestId of the operation to get status for.</param>
        /// <param name="pollIntervalSeconds">The interval between calls to Get Operation Status.</param>
        /// <param name="timeoutSeconds">The maximum number of seconds to poll.</param>
        /// <returns>An OperationResult structure with status or error information.</returns>
        private static OperationResult PollGetOperationStatus(
            string requestId,
            int pollIntervalSeconds,
            int timeoutSeconds)
        {
            OperationResult result = new OperationResult();
            DateTime beginPollTime = DateTime.UtcNow;
            TimeSpan pollInterval = new TimeSpan(0, 0, pollIntervalSeconds);
            DateTime endPollTime = beginPollTime + new TimeSpan(0, 0, timeoutSeconds);
 
            bool done = false;
            while (!done)
            {
                XElement operation = GetOperationStatus(requestId);
                result.RunningTime = DateTime.UtcNow - beginPollTime;
                try
                {
                    // Turn the Status string into an OperationStatus value
                    result.Status = (OperationStatus)Enum.Parse(
                        typeof(OperationStatus),
                        operation.Element(wa + "Status").Value);
                }
                catch (Exception e)
                {
                    throw new ApplicationException(string.Format(
                        "Get Operation Status {0} returned unexpected status: {1}{2}",
                        requestId,
                        Environment.NewLine,
                        operation.ToString(SaveOptions.OmitDuplicateNamespaces)),
                        e);
                }
 
                switch (result.Status)
                {
                    case OperationStatus.InProgress:
                        Console.WriteLine(
                            "In progress for {0} seconds",
                            (int)result.RunningTime.TotalSeconds);
                        Thread.Sleep((int)pollInterval.TotalMilliseconds);
                        break;
 
                    case OperationStatus.Failed:
                        result.StatusCode = (HttpStatusCode)Convert.ToInt32(
                            operation.Element(wa + "HttpStatusCode").Value);
                        XElement error = operation.Element(wa + "Error");
                        result.Code = error.Element(wa + "Code").Value;
                        result.Message = error.Element(wa + "Message").Value;
                        done = true;
                        break;
 
                    case OperationStatus.Succeeded:
                        result.StatusCode = (HttpStatusCode)Convert.ToInt32(
                            operation.Element(wa + "HttpStatusCode").Value);
                        done = true;
                        break;
                }
 
                if (!done && DateTime.UtcNow > endPollTime)
                {
                    result.Status = OperationStatus.TimedOut;
                    done = true;
                }
            }
 
            return result;
        }
 
        /// <summary>
        /// Gets the certificate matching the thumbprint from the local store.
        /// Throws an ArgumentException if a matching certificate is not found.
        /// </summary>
        /// <param name="thumbprint">The thumbprint of the certificate to find.</param>
        /// <returns>The certificate with the specified thumbprint.</returns>
        private static X509Certificate2 GetStoreCertificate(string thumbprint)
        {
            List<StoreLocation> locations = new List<StoreLocation> 
            { 
                StoreLocation.CurrentUser, 
                StoreLocation.LocalMachine 
            };
 
            foreach (var location in locations)
            {
                X509Store store = new X509Store("My", location);
                try
                {
                    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                    X509Certificate2Collection certificates = store.Certificates.Find(
                        X509FindType.FindByThumbprint, thumbprint, false);
                    if (certificates.Count == 1)
                    {
                        return certificates[0];
                    }
                }
                finally
                {
                    store.Close();
                }
            }
 
            throw new ArgumentException(string.Format(
                "A Certificate with thumbprint '{0}' could not be located.",
                thumbprint));
        }
 
        /// <summary>
        /// A helper function to invoke a Service Management REST API operation.
        /// Throws an ApplicationException on unexpected status code results.
        /// </summary>
        /// <param name="uri">The URI of the operation to invoke using a web request.</param>
        /// <param name="method">The method of the web request, GET, PUT, POST, or DELETE.</param>
        /// <param name="expectedCode">The expected status code.</param>
        /// <param name="requestBody">The XML body to send with the web request. Use null to send no request body.</param>
        /// <param name="responseBody">The XML body returned by the request, if any.</param>
        /// <returns>The requestId returned by the operation.</returns>
        private static string InvokeRequest(
            Uri uri,
            string method,
            HttpStatusCode expectedCode,
            XDocument requestBody,
            out XDocument responseBody)
        {
            responseBody = null;
            string requestId = String.Empty;
 
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
            request.Method = method;
            request.Headers.Add("x-ms-Version", XMsVersion);
            request.ClientCertificates.Add(ManagementCertificate);
            request.ContentType = "application/xml";
 
            if (requestBody != null)
            {
                using (Stream requestStream = request.GetRequestStream())
                {
                    using (StreamWriter streamWriter = new StreamWriter(
                        requestStream, System.Text.UTF8Encoding.UTF8))
                    {
                        requestBody.Save(streamWriter, SaveOptions.DisableFormatting);
                    }
                }
            }
 
            HttpWebResponse response;
            HttpStatusCode statusCode = HttpStatusCode.Unused;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                // GetResponse throws a WebException for 4XX and 5XX status codes
                response = (HttpWebResponse)ex.Response;
            }
 
            try
            {
                statusCode = response.StatusCode;
                if (response.ContentLength > 0)
                {
                    using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
                    {
                        responseBody = XDocument.Load(reader);
                    }
                }
 
                if (response.Headers != null)
                {
                    requestId = response.Headers["x-ms-request-id"];
                }
            }
            finally
            {
                response.Close();
            }
 
            if (!statusCode.Equals(expectedCode))
            {
                throw new ApplicationException(string.Format(
                    "Call to {0} returned an error:{1}Status Code: {2} ({3}):{1}{4}",
                    uri.ToString(),
                    Environment.NewLine,
                    (int)statusCode,
                    statusCode,
                    responseBody.ToString(SaveOptions.OmitDuplicateNamespaces)));
            }
 
            return requestId;
        }
    }
}

A seguinte saída de exemplo mostra o certificado adicionado ao serviço hospedado e então mostra que o serviço hospedado não tem nenhum certificado após a exclusão do certificado:

Enter the password for hostedservicecertificate.pfx: ********
Called Add Certificate operation: requestId fdcf42761fb1424688a5968aa38811d7
In progress for 0 seconds
Succeeded: Operation fdcf42761fb1424688a5968aa38811d7 completed after 21 seconds with status 200 (OK)
Certificates for Hosted Service MyHostedService1:
<Certificates xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Certificate>
    <CertificateUrl>https://management.core.windows.net/01234567-89ab-cdef-0123-456789abcdef/services/hostedservices/MyHostedService1/certificates/sha1-2EA90CBB65EFCF71C92F55363954A16B87941ECD</CertificateUrl>
    <Thumbprint>2EA90CBB65EFCF71C92F55363954A16B87941ECD</Thumbprint>
    <ThumbprintAlgorithm>sha1</ThumbprintAlgorithm>
    <Data>MIIDIDCCAgygAwIBAgIQFacJqSCsGKVGE19GKlrEejAJBgUrDgMCHQUAMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZTAeFw0xMTExMTAwMDM3NDRaFw0zOTEyMzEyMzU5NTlaMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM94zedfRaAcpOESoStDBM/r18qdOI7HFawK+8sd+atW93L+pJgUjmEYgbHsBET2YZRTWHV2l6HkV7CRnSgTMQ/0SrIsGj+l1BG5Xncdp5Do9dbpHOQmZYVB3t3l0BcFgj3DP+atNXWctUpjdyDJB+USZJB7o0gz3esmyxdD1HaFBu1LW7GfhWHDmC0+QERdoKxAvVKY1wuvCxY1/LdCno6ZMV95l5xJ5jzf/itRo0A9wD5tlcR7bJL7Xp45REKZoaVwxCIooL8fC427LQf2EZbwjhU3kqPOyQ40vNTB+ksJneXqXjhh7Hefond9fFe6O7mwGVfbqOsbFWJsrTA7b40CAwEAAaNYMFYwVAYDVR0BBE0wS4AQMezArIE9mdwqywnNC9Y/NaElMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZYIQFacJqSCsGKVGE19GKlrEejAJBgUrDgMCHQUAA4IBAQA0XehZ43Yt/u/NlOSYOkGhCeomndZbBcijGH9fo39OiMPwN1BOY1Ch1YmlTt60o/1u1Lg7oxx9+NfE4O2x2xqBK+SIT/W4gtowjmwFg+dRu0qRCYcJL1HaQWGoRbkZrJHNOKsBVUWJbSKyOtM/MZ2v5eZ2q2imDLNMnIPY6YaeP9s4lLhcu53iuzkHf1JvsmNkvI7XQkCw2W/COu8ndcXmTrhc1btz+j3r6G9siGeRQ+xDV394GIAtTZgszefJXVkjiYlHczUmr0ZPKWh3vA/RTyrcQfDVH0QBZ9CMYNhhI1PIJOPAQ3X5YsYQwah9pbYV4mIXaJKld+eNsEFt3Zo8</Data>
  </Certificate>
</Certificates>
Called Delete Certificate operation: requestId e480c3ffab2a4b7a840730200f004130
Succeeded: Operation e480c3ffab2a4b7a840730200f004130 completed after 0 seconds with status 200 (OK)
Certificates for Hosted Service MyHostedService1:
<Certificates xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
Press any key to continue:

A Microsoft está realizando uma pesquisa online para saber sua opinião sobre o site do MSDN. Se você optar por participar, a pesquisa online lhe será apresentada quando você sair do site do MSDN.

Deseja participar?
Mostrar:
© 2014 Microsoft