创建生产设备提交Create a production device submission

重要提示 截至 2016 年 10 月底,将不再提供可使用的仪表板提交 REST API。Important The dashboard submission REST APIs will no longer be available for use as of the end of October 2016. 正在考虑为将来版本提供适用于驱动程序提交的 API。APIs for driver submissions are under consideration for a future release.

你可以使用组织的服务帐户和文件签名服务,将认证和文件签名提交构建到现有开发和部署框架中。You can build certification and file signing submissions into your existing development and deployment framework using your organization's service account and file signing services.

创建生产设备提交请求To create a production device submission request

  1. 通过遵循管理你的服务帐户凭据中的步骤,获取组织的服务帐户凭据。Get the service account credentials of your organization by following the steps in Manage your service account credentials. 如果没有服务帐户,请按照管理你的服务帐户凭据 中的步骤操作。If you do not have a service account, follow the steps in Manage your service account credentials. 你将在下一步的 client_secret 值中需要使用服务帐户凭据。You will use the service account credentials in the client_secret value in the next step.

  2. 从 Azure 访问控制服务 (ACS) 获取身份验证令牌。Get an authentication token from Azure Access Control service (ACS). 有关详细信息,请参阅如何从 ACS 请求 SWT 令牌For more information, see How to Request SWT Token from ACS. 在客户端请求该令牌时,使用以下代码。Use the following code in the client requesting the token.

    string realm = "https://devicesigningservice.cloudapp.net";
    string acsNameSpace = "https://sysdevacs.accesscontrol.windows.net";
    var client = new HttpClient();
    client.BaseAddress = new Uri(acsNameSpace);
    List<KeyValuePair<string, string>> values = new List<KeyValuePair<string, string>>();
    values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
    values.Add(new KeyValuePair<string, string>("client_id", "Fabrikam"));
    values.Add(new KeyValuePair<string, string>("client_secret", "Contoso"));
    values.Add(new KeyValuePair<string, string>("scope", realm));
    var content = new FormUrlEncodedContent(values);
    var responseMessage = client.PostAsync("v2/OAuth2-13", content).Result;
    var jss = new JavaScriptSerializer();
    dynamic responseString = jss.Deserialize<dynamic>(responseMessage.Content.ReadAsStringAsync().Result);
    string token = responseString["access_token"] as string;
    
  3. 使用创建请求操作和步骤 2 中的身份验证令牌,创建仪表板提交对象对象。Create a Dashboard submission objects object using the Create a request operation and the authentication token from step 2. 身份验证令牌必须在标头中。The authentication token must be in the header. 这将发出请求并返回一个共享访问签名 (SAS) URI。This initiates the request and returns a Shared Access Signature (SAS) URI.

    var json = CreateSubmissionMetadata(new {
    ProductName = "Test",
    MarketingNames = new object[]{
    new {
    Name = "Testing Name",
    Locale = new object[]{
    "English"
    }
    }
    },
    AnnouncementDate = DateTime.Now.AddDays(4).ToString("s"),
    PublishingDate = DateTime.Now.AddDays(6).ToString("s"),
    OSSelections = new object[]{
    new {
    OS = "Windows 8",
    ProductType = "Printer",
    QualificationLevel = "Signature Only"
    }
    },
    InitialUploadFileSize = 1,
    TestHarnessType = "HLK"
    });
    
            static dynamic CreateSubmissionMetadata(dynamic json)
            {
                var SysdevEndpoint = "https://devicesigningservice.cloudapp.net/api/signing/devices";
                HttpRequestMessage createRequest = new HttpRequestMessage()
                {
                    Method = HttpMethod.Post,
                    RequestUri = new Uri(SysdevEndpoint),
                    Content = new StringContent(new JavaScriptSerializer().Serialize(json).ToString())
                };
                createRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                HttpResponseMessage response = null;
                TimeAction("Creating an azure submission took {0} ms", () => { response = SendRequest(createRequest); });
    
                var submissionUrl = response.Headers.Location.ToString();
                var sasUrl = response.Content.ReadAsStringAsync().Result;
    
                return new
                {
                    SasUrl = sasUrl.Substring(1, sasUrl.Length - 2),
                    SubmissionGuid = GetFirstGuidFromUrl(submissionUrl)
                };
            }
            static HttpResponseMessage SendRequest(HttpRequestMessage message)
            {
                Trace.WriteLine("Sending request to " + message.RequestUri);
                using (HttpClient client = new HttpClient())
                {
                    //Trace.WriteLine("Set Bearer header to " + AuthToken);
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
    
                    var resp = client.SendAsync(message).Result;
                    if(resp.IsSuccessStatusCode)
                    {
                        return resp;
                    }
                    else
                    {
                        throw new HttpRequestException("The request failed with status code response: " + resp.StatusCode.ToString());
                    }
                }
            }
    
  4. 通过步骤 3 中的 SAS URI,使用 Azure 存储 API 上载你的硬件认证工具包 (HCK)。Using the SAS URI from step 3, use the Azure Storage API to upload your Hardware Certification Kit (HCK) package.

    /// <summary>
            /// Uploads the given file using the SAS Url provided. This method can be replaced with a call to the Azure Storage Client API
            /// </summary>
            /// <param name="sasUrl">Sas Url returned from the Sysdev API</param>
            /// <param name="filepath">Path to the file that will be uploaded</param>
            static void UploadFile(string sasUrl, string filepath)
            {
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("x-ms-version", Version);
                    client.DefaultRequestHeaders.Add("x-ms-client-request-id", SessionGuid);
    
                    StringBuilder sb = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?><BlockList>");
    
                    foreach (byte[] chunk in GetFileChunks(filepath))
                    {
                        var blockid = GetHash(chunk);
                        HttpRequestMessage chunkMessage = new HttpRequestMessage()
                        {
                            Method = HttpMethod.Put,
                            RequestUri = new Uri(sasUrl + "&timeout=90&comp=block&blockid=" + WebUtility.UrlEncode(blockid)),
                            Content = new ByteArrayContent(chunk)
                        };
                        chunkMessage.Headers.Add("x-ms-blob-type", "BlockBlob");
                        chunkMessage.Content.Headers.Add("MD5-Content", blockid);
    
                        TimeAction("Uploading chunk " + blockid + " took {0} ms", () =>
                        {
                            var response = client.SendAsync(chunkMessage).Result;
                        });
                        sb.Append("<Latest>");
                        sb.Append(blockid);
                        sb.Append("</Latest>");
                    }
                    sb.Append("</BlockList>");
    
                    Trace.WriteLine(sb.ToString());
    
                    HttpRequestMessage commitMessage = new HttpRequestMessage()
                    {
                        Method = HttpMethod.Put,
                        RequestUri = new Uri(sasUrl + "&timeout=90&comp=blocklist"),
                        Content = new StringContent(sb.ToString())
                    };
                    TimeAction("Commiting the blocks took {0} ms", () =>
                    {
                        var commit = client.SendAsync(commitMessage).Result;
                    });
                }
            }
    
  5. 上载完成后,通过在更新现有提交 操作中将 UpdateComplete 标志设置为 true,开始提交过程。After uploading is complete, start the submission process by setting the UpdateComplete flag to true in the Update an existing submission operation. 这将通知 Microsoft 启动后端处理。This notifies Microsoft to start the backend processing.

    static void UpdateSubmission(string guid, dynamic json)
            {
                HttpRequestMessage update = new HttpRequestMessage()
                {
                    Method = new HttpMethod("PATCH"),
                    RequestUri = new Uri(SysdevEndpoint + "/" + guid),
                    Content = new StringContent(new JavaScriptSerializer().Serialize(json))
                };
                update.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    
                TimeAction("Updating the information for submission " + guid, () => { var response = SendRequest(update); });
            }
    
  6. 若要轮询状态,请使用获取现有提交的元数据 操作并评估 Status 值以响应 ApprovedManual ReviewRejectedTo poll for status, use the Get metadata for an existing submission operation and evaluate the Status value in the response for Approved, Manual Review, or Rejected. 处理可能需要 10 分钟到 24 小时的时间。Processing can take from 10 minutes to 24 hours.

    Trace.WriteLine("Begin waiting for the submission to finish");
                    //Poll for the status of the submission in our system
                    //Give up checking after an hour
                    for (int retryCount = 0; ; retryCount++)
                    {
                        Thread.Sleep(60 * 1000);
                        var submission = GetSubmission(resp.SubmissionGuid);
                        if (String.Compare(submission["Status"], "Completed") == 0)
                        {
                            //Once the submission is finished processing, loop through the signed files and download them
                            foreach (var asset in submission["Assets"])
                            {
                                if (String.Compare(asset["AssetType"], "SignedFile") == 0)
                                {
                                    //Download the signed files from the azure storage blob
                                    DownloadFile(resp.SubmissionGuid, asset["DeviceSigningAssetID"], Path.Combine(outputDirectory, asset["Name"]));
                                }
                            }
                            break;
                        }
                        if (retryCount == 60)
                        {
                            throw new ApplicationException("Submission is taking a long time to process, last status: " + submission["Status"]);
                        }
    

下载资源Download an asset

处理完成后,执行以下操作来下载已签名文件、认证验证报告的 URL 或驱动程序更新可接受 (DUA) shell 包:When processing is completed, do the following to download your signed files, the URL to certification verification reports, or the Driver Update Acceptable (DUA) shell package:

  1. 如果你的令牌已过期,请从 ACS 获取新的身份验证令牌。If your token is expired, get a new authentication token from ACS.

  2. 使用获取现有提交的元数据操作检索仪表板提交对象Retrieve the Dashboard submission objects using the Get metadata for an existing submission operation.

    static dynamic GetSubmission(string guid)
            {
                HttpRequestMessage update = new HttpRequestMessage()
                {
                    Method = HttpMethod.Get,
                    RequestUri = new Uri(SysdevEndpoint + "/" + guid)
                };
    
                HttpResponseMessage response = null;
               TimeAction("Getting information for submission "+guid, () => { response = SendRequest(update); });
    
                JavaScriptSerializer jss = new JavaScriptSerializer();
    
                return jss.Deserialize<dynamic>(response.Content.ReadAsStringAsync().Result);
            }
    
  3. 仪表板提交对象使用仪表板提交对象,并使用获取提交内特定资源操作检索 SAS URI。Use the Dashboard submission objects from the Dashboard submission objects and retrieve the SAS URI using the Get a specific asset within a submission operation.

    static Uri GetSasUrlForAsset(string submissionGuid, string assetGuid)
            {
                HttpRequestMessage asset = new HttpRequestMessage()
                {
                    Method = HttpMethod.Get,
                    RequestUri = new Uri(SysdevEndpoint + "/" + submissionGuid + "/assets/" + assetGuid)
                };
    
                HttpResponseMessage get = null;
                TimeAction("Getting the sas url for "+submissionGuid +"/"+assetGuid + "took {0} ms", ()=>{SendRequest(asset);});
    
                return get.Headers.Location;
            }
    
  4. 使用 Azure 存储 API 下载你请求的资源。Use the Azure Storage API to download your requested asset.

    static void DownloadFile(string submissionGuid, string assetGuid, string filepath, Uri sasUrl)
            {
              using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("x-ms-version", Version);
                    client.DefaultRequestHeaders.Add("x-ms-client-request-id", SessionGuid);
    
                    HttpRequestMessage download = new HttpRequestMessage()
                    {
                        Method = HttpMethod.Get,
                        RequestUri = sasUrl
                    };
    
                    using (FileStream fs = new FileStream(filepath, FileMode.CreateNew))
                    {
                        using (var stream = client.SendAsync(download).Result.Content.ReadAsStreamAsync().Result)
                        {
                            byte[] buffer = new byte[ChunkSize];
                            int size = 0;
                            while ((size = stream.Read(buffer, 0, ChunkSize)) > 0)
                            {
                                fs.Write(buffer, 0, size);
                            }
                        }
                    }
                }
            }
    

相关主题Related topics

仪表板提交 REST API 参考Dashboard submission REST API reference

仪表板提交对象Dashboard submission objects

管理你的服务帐户凭据Manage your service account credentials

向 Microsoft 发送有关该主题的评论Send comments about this topic to Microsoft