PageRenderTime 51ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/SMLibrary/VMManager.cs

https://github.com/mwasham/wasvcmgmntapi
C# | 651 lines | 535 code | 114 blank | 2 comment | 54 complexity | 06db2c76a2566b519aebc3cc3ea0cf99 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Net.Http.Headers;
  8. using System.Security.Cryptography.X509Certificates;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Xml.Linq;
  13. namespace SMLibrary
  14. {
  15. public class VMManager
  16. {
  17. private String _subscriptionid { get; set; }
  18. private String _certthumbprint { get; set; }
  19. public XNamespace ns = "http://schemas.microsoft.com/windowsazure";
  20. XNamespace ns1 = "http://www.w3.org/2001/XMLSchema-instance";
  21. public VMManager(String SubscriptionID, String CertThumbPrint)
  22. {
  23. _subscriptionid = SubscriptionID;
  24. _certthumbprint = CertThumbPrint;
  25. }
  26. public HttpClient GetHttpClient()
  27. {
  28. WebRequestHandler handler = new WebRequestHandler();
  29. String CertThumbprint = _certthumbprint;
  30. X509Certificate2 managementCert = FindX509Certificate(CertThumbprint);
  31. if (managementCert != null)
  32. {
  33. handler.ClientCertificates.Add(managementCert);
  34. HttpClient httpClient = new HttpClient(handler);
  35. httpClient.DefaultRequestHeaders.Add("x-ms-version", "2012-03-01");
  36. httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
  37. return httpClient;
  38. }
  39. return null;
  40. }
  41. async public Task<XDocument> GetAzureSubscription()
  42. {
  43. String uri = String.Format("https://management.core.windows.net/{0}", _subscriptionid);
  44. XDocument subXML = new XDocument();
  45. HttpClient http = GetHttpClient();
  46. Stream responseStream = await http.GetStreamAsync(uri);
  47. if (responseStream != null)
  48. {
  49. subXML = XDocument.Load(responseStream);
  50. }
  51. return subXML;
  52. }
  53. async public Task<List<String>> GetAzureVMImages()
  54. {
  55. List<String> imageList = new List<String>();
  56. String uri = String.Format("https://management.core.windows.net/{0}/services/images", _subscriptionid);
  57. HttpClient http = GetHttpClient();
  58. Stream responseStream = await http.GetStreamAsync(uri);
  59. if (responseStream != null)
  60. {
  61. XDocument xml = XDocument.Load(responseStream);
  62. var images = xml.Root.Descendants(ns + "OSImage").Where(i => i.Element(ns + "OS").Value == "Windows");
  63. foreach (var image in images)
  64. {
  65. string img = image.Element(ns + "Name").Value;
  66. imageList.Add(img);
  67. }
  68. }
  69. return imageList;
  70. }
  71. async public Task<String> RebootVM(String ServiceName, String RoleName)
  72. {
  73. String requestID = String.Empty;
  74. String deployment = await GetAzureDeploymentName(ServiceName);
  75. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roleInstances/{3}/Operations", _subscriptionid, ServiceName, deployment, RoleName);
  76. HttpClient http = GetHttpClient();
  77. XElement srcTree = new XElement("RestartRoleOperation",
  78. new XAttribute(XNamespace.Xmlns + "i", ns1),
  79. new XElement("OperationType", "RestartRoleOperation")
  80. );
  81. ApplyNamespace(srcTree, ns);
  82. XDocument CSXML = new XDocument(srcTree);
  83. HttpContent content = new StringContent(CSXML.ToString());
  84. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  85. HttpResponseMessage responseMsg = await http.PostAsync(uri, content);
  86. if (responseMsg != null)
  87. {
  88. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  89. }
  90. return requestID;
  91. }
  92. async public Task<String> ShutDownVM(String ServiceName, String RoleName)
  93. {
  94. String requestID = String.Empty;
  95. String deployment = await GetAzureDeploymentName(ServiceName);
  96. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roleInstances/{3}/Operations", _subscriptionid, ServiceName, deployment, RoleName);
  97. HttpClient http = GetHttpClient();
  98. XElement srcTree = new XElement("ShutdownRoleOperation",
  99. new XAttribute(XNamespace.Xmlns + "i", ns1),
  100. new XElement("OperationType", "ShutdownRoleOperation")
  101. );
  102. ApplyNamespace(srcTree, ns);
  103. XDocument CSXML = new XDocument(srcTree);
  104. HttpContent content = new StringContent(CSXML.ToString());
  105. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  106. HttpResponseMessage responseMsg = await http.PostAsync(uri, content);
  107. if (responseMsg != null)
  108. {
  109. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  110. }
  111. return requestID;
  112. }
  113. async public Task<XDocument> GetAzureVMs()
  114. {
  115. List<XDocument> services = await GetAzureServices();
  116. XDocument vms = new XDocument();
  117. vms.Add(new XElement("VirtualMachines"));
  118. ApplyNamespace(vms.Root, ns);
  119. foreach (var svc in services)
  120. {
  121. string ServiceName = svc.Root.Element(ns + "ServiceName").Value;
  122. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}", _subscriptionid, ServiceName, "Production");
  123. try
  124. {
  125. HttpClient http = GetHttpClient();
  126. Stream responseStream = await http.GetStreamAsync(uri);
  127. if (responseStream != null)
  128. {
  129. XDocument xml = XDocument.Load(responseStream);
  130. var roles = xml.Root.Descendants(ns + "RoleInstance");
  131. foreach (XElement r in roles)
  132. {
  133. XElement svcnameel = new XElement("ServiceName", ServiceName);
  134. ApplyNamespace(svcnameel, ns);
  135. r.Add(svcnameel); // not part of the roleinstance
  136. vms.Root.Add(r);
  137. }
  138. }
  139. }
  140. catch (HttpRequestException http)
  141. {
  142. // no vms with cloud service
  143. }
  144. }
  145. return vms;
  146. }
  147. async public Task<List<XDocument>> GetAzureVMs(String ServiceName)
  148. {
  149. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}", _subscriptionid, ServiceName, "Production");
  150. List<XDocument> vms = new List<XDocument>();
  151. HttpClient http = GetHttpClient();
  152. Stream responseStream = await http.GetStreamAsync(uri);
  153. if (responseStream != null)
  154. {
  155. XDocument xml = XDocument.Load(responseStream);
  156. var roles = xml.Root.Descendants(ns + "RoleInstance");
  157. foreach (XElement r in roles)
  158. {
  159. XDocument vm = new XDocument(r);
  160. vms.Add(vm);
  161. }
  162. }
  163. return vms;
  164. }
  165. async public Task<XDocument> GetAzureVM(String ServiceName, String VMName)
  166. {
  167. String deployment = await GetAzureDeploymentName(ServiceName);
  168. XDocument vmXML = new XDocument();
  169. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roles/{3}", _subscriptionid, ServiceName, deployment, VMName);
  170. HttpClient http = GetHttpClient();
  171. Stream responseStream = await http.GetStreamAsync(uri);
  172. if (responseStream != null)
  173. {
  174. vmXML = XDocument.Load(responseStream);
  175. }
  176. return vmXML;
  177. }
  178. async public Task<String> NewAzureCloudService(String ServiceName, String Location, String AffinityGroup)
  179. {
  180. String requestID = String.Empty;
  181. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices", _subscriptionid);
  182. HttpClient http = GetHttpClient();
  183. System.Text.ASCIIEncoding ae = new System.Text.ASCIIEncoding();
  184. byte[] svcNameBytes = ae.GetBytes(ServiceName);
  185. String locationEl = String.Empty;
  186. String locationVal = String.Empty;
  187. if (String.IsNullOrEmpty(Location) == false)
  188. {
  189. locationEl = "Location";
  190. locationVal = Location;
  191. }
  192. else
  193. {
  194. locationEl = "AffinityGroup";
  195. locationVal = AffinityGroup;
  196. }
  197. XElement srcTree = new XElement("CreateHostedService",
  198. new XAttribute(XNamespace.Xmlns + "i", ns1),
  199. new XElement("ServiceName", ServiceName),
  200. new XElement("Label", Convert.ToBase64String(svcNameBytes)),
  201. new XElement(locationEl, locationVal)
  202. );
  203. ApplyNamespace(srcTree, ns);
  204. XDocument CSXML = new XDocument(srcTree);
  205. HttpContent content = new StringContent(CSXML.ToString());
  206. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  207. HttpResponseMessage responseMsg = await http.PostAsync(uri, content);
  208. if (responseMsg != null)
  209. {
  210. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  211. }
  212. return requestID;
  213. }
  214. async public Task<String> NewAzureVM(String ServiceName, String VMName, XDocument VMXML)
  215. {
  216. String requestID = String.Empty;
  217. String deployment = await GetAzureDeploymentName(ServiceName);
  218. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roles", _subscriptionid, ServiceName, deployment);
  219. HttpClient http = GetHttpClient();
  220. HttpContent content = new StringContent(VMXML.ToString());
  221. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  222. HttpResponseMessage responseMsg = await http.PostAsync(uri, content);
  223. if (responseMsg != null)
  224. {
  225. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  226. }
  227. return requestID;
  228. }
  229. async public Task<String> NewAzureVMDeployment(String ServiceName, String VMName, String VNETName, XDocument VMXML, XDocument DNSXML)
  230. {
  231. String requestID = String.Empty;
  232. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments", _subscriptionid, ServiceName);
  233. HttpClient http = GetHttpClient();
  234. XElement srcTree = new XElement("Deployment",
  235. new XAttribute(XNamespace.Xmlns + "i", ns1),
  236. new XElement("Name", ServiceName),
  237. new XElement("DeploymentSlot", "Production"),
  238. new XElement("Label", ServiceName),
  239. new XElement("RoleList", null)
  240. );
  241. if (String.IsNullOrEmpty(VNETName) == false)
  242. {
  243. srcTree.Add(new XElement("VirtualNetworkName", VNETName));
  244. }
  245. if(DNSXML != null)
  246. {
  247. srcTree.Add(new XElement("DNS", new XElement("DNSServers", DNSXML)));
  248. }
  249. XDocument deploymentXML = new XDocument(srcTree);
  250. ApplyNamespace(srcTree, ns);
  251. deploymentXML.Descendants(ns + "RoleList").FirstOrDefault().Add(VMXML.Root);
  252. String fixedXML = deploymentXML.ToString().Replace(" xmlns=\"\"", "");
  253. HttpContent content = new StringContent(fixedXML);
  254. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  255. HttpResponseMessage responseMsg = await http.PostAsync(uri, content);
  256. if (responseMsg != null)
  257. {
  258. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  259. }
  260. return requestID;
  261. }
  262. async public Task<String> UpdateAzureVM(String ServiceName, String VMName, XDocument VMXML)
  263. {
  264. String requestID = String.Empty;
  265. String deployment = await GetAzureDeploymentName(ServiceName);
  266. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roles/{3}", _subscriptionid, ServiceName, deployment, VMName);
  267. HttpClient http = GetHttpClient();
  268. String fixedXML = VMXML.ToString().Replace(" xmlns=\"\"", "");
  269. HttpContent content = new StringContent(fixedXML);
  270. content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
  271. HttpResponseMessage responseMsg = await http.PutAsync(uri, content);
  272. if (responseMsg != null)
  273. {
  274. requestID = responseMsg.Headers.GetValues("x-ms-request-id").FirstOrDefault();
  275. }
  276. return requestID;
  277. }
  278. async public Task<byte[]> GetRDPFile(String ServiceName, String vmName)
  279. {
  280. String deploymentName = await GetAzureDeploymentName(ServiceName);
  281. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roleinstances/{3}/ModelFile?FileType=RDP", _subscriptionid, ServiceName, deploymentName, vmName);
  282. byte[] RDPFile = null;
  283. HttpClient http = GetHttpClient();
  284. Stream responseStream = await http.GetStreamAsync(uri);
  285. if (responseStream != null)
  286. {
  287. using (MemoryStream ms = new MemoryStream())
  288. {
  289. responseStream.CopyTo(ms);
  290. RDPFile = ms.ToArray();
  291. }
  292. }
  293. return RDPFile;
  294. }
  295. async private Task<List<XDocument>> GetAzureServices()
  296. {
  297. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices ", _subscriptionid);
  298. List<XDocument> services = new List<XDocument>();
  299. HttpClient http = GetHttpClient();
  300. Stream responseStream = await http.GetStreamAsync(uri);
  301. if (responseStream != null)
  302. {
  303. XDocument xml = XDocument.Load(responseStream);
  304. var svcs = xml.Root.Descendants(ns + "HostedService");
  305. foreach (XElement r in svcs)
  306. {
  307. XDocument vm = new XDocument(r);
  308. services.Add(vm);
  309. }
  310. }
  311. return services;
  312. }
  313. async public Task<bool> IsServiceNameAvailable(String ServiceName)
  314. {
  315. bool available = false;
  316. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/operations/isavailable/{1}", _subscriptionid, ServiceName);
  317. HttpClient http = GetHttpClient();
  318. Stream responseStream = await http.GetStreamAsync(uri);
  319. if (responseStream != null)
  320. {
  321. XDocument xml = XDocument.Load(responseStream);
  322. var response = xml.Descendants(ns + "AvailabilityResponse").FirstOrDefault();
  323. var strAvailable = response.Element(ns + "Result").Value;
  324. if (strAvailable == "true")
  325. available = true;
  326. }
  327. return available;
  328. }
  329. async private Task<String> GetAzureDeploymentName(String ServiceName)
  330. {
  331. String uri = String.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}", _subscriptionid, ServiceName, "Production");
  332. String DeploymentName = String.Empty;
  333. HttpClient http = GetHttpClient();
  334. Stream responseStream = await http.GetStreamAsync(uri);
  335. if (responseStream != null)
  336. {
  337. XDocument xml = XDocument.Load(responseStream);
  338. var name = xml.Root.Element(ns + "Name");
  339. DeploymentName = name.Value;
  340. }
  341. return DeploymentName;
  342. }
  343. public XDocument NewAzureVMConfig(String RoleName, String VMSize, String ImageName, String MediaLocation, bool InitialDeployment = false)
  344. {
  345. System.Text.ASCIIEncoding ae = new System.Text.ASCIIEncoding();
  346. byte[] roleNameBytes = ae.GetBytes(RoleName);
  347. XElement srcTree = null;
  348. if (InitialDeployment == false)
  349. {
  350. srcTree = new XElement("PersistentVMRole",
  351. new XAttribute(XNamespace.Xmlns + "i", ns1),
  352. new XElement("RoleName", RoleName),
  353. new XElement("OsVersion", new XAttribute(ns1 + "nil", true)),
  354. new XElement("RoleType", "PersistentVMRole"),
  355. new XElement("ConfigurationSets", null),
  356. new XElement("DataVirtualHardDisks", null),
  357. new XElement("Label", Convert.ToBase64String(roleNameBytes)),
  358. new XElement("OSVirtualHardDisk",
  359. new XElement("MediaLink", MediaLocation),
  360. new XElement("SourceImageName", ImageName)),
  361. new XElement("RoleSize", VMSize)
  362. );
  363. ApplyNamespace(srcTree, ns);
  364. }
  365. else
  366. {
  367. srcTree = new XElement("Role",
  368. new XAttribute(ns1 + "type", "PersistentVMRole"),
  369. new XElement("RoleName", RoleName),
  370. new XElement("OsVersion", new XAttribute(ns1 + "nil", true)),
  371. new XElement("RoleType", "PersistentVMRole"),
  372. new XElement("ConfigurationSets", null),
  373. new XElement("DataVirtualHardDisks", null),
  374. new XElement("Label", Convert.ToBase64String(roleNameBytes)),
  375. new XElement("OSVirtualHardDisk",
  376. new XElement("MediaLink", MediaLocation),
  377. new XElement("SourceImageName", ImageName)),
  378. new XElement("RoleSize", VMSize)
  379. );
  380. ApplyNamespace(srcTree, ns);
  381. }
  382. XDocument VMXML = new XDocument();
  383. VMXML.Add(srcTree);
  384. return VMXML;
  385. }
  386. public XDocument NewWindowsProvisioningConfig(XDocument VMXML, String ComputerName, String Password, bool EnableAutomaticUpdate = false, bool ResetPasswordOnFirstLogon = false)
  387. {
  388. XElement srcTree = new XElement("ConfigurationSet",
  389. new XAttribute(ns1 + "type", "WindowsProvisioningConfigurationSet"),
  390. new XElement("ConfigurationSetType", "WindowsProvisioningConfiguration"),
  391. new XElement("ComputerName", ComputerName),
  392. new XElement("AdminPassword", Password),
  393. new XElement("EnableAutomaticUpdates", EnableAutomaticUpdate),
  394. new XElement("ResetPasswordOnFirstLogon", ResetPasswordOnFirstLogon)
  395. );
  396. VMXML.Root.Element(ns + "ConfigurationSets").Add(srcTree);
  397. return VMXML;
  398. }
  399. public XDocument NewNetworkConfigurationSet(XDocument VMXML)
  400. {
  401. XElement srcTree = new XElement("ConfigurationSet",
  402. new XAttribute(ns1 + "type", "NetworkConfigurationSet"),
  403. new XElement("ConfigurationSetType", "NetworkConfiguration"),
  404. new XElement("InputEndpoints", null),
  405. new XElement("SubnetNames", null)
  406. );
  407. VMXML.Root.Element(ns + "ConfigurationSets").Add(srcTree);
  408. return VMXML;
  409. }
  410. public XDocument AddNewDataDisk(XDocument VMXML, int DiskSizeInGB, int Lun, String DiskLabel, String MediaLocation)
  411. {
  412. XElement srcTree = new XElement("DataVirtualHardDisk",
  413. new XElement("DiskLabel", DiskLabel),
  414. new XElement("Lun", Lun),
  415. new XElement("LogicalDiskSizeInGB", DiskSizeInGB),
  416. new XElement("MediaLink", MediaLocation)
  417. );
  418. VMXML.Root.Element(ns + "DataVirtualHardDisks").Add(srcTree);
  419. return VMXML;
  420. }
  421. public XDocument AddNewInputEndpoint(XDocument VMXML, String Name, String Protocol, int LocalPort, int PublicPort)
  422. {
  423. XElement srcTree = new XElement("InputEndpoint",
  424. new XElement("LocalPort", LocalPort),
  425. new XElement("Name", Name),
  426. new XElement("Port", PublicPort),
  427. new XElement("Protocol", Protocol)
  428. );
  429. VMXML.Descendants("InputEndpoints").FirstOrDefault().Add(srcTree);
  430. return VMXML;
  431. }
  432. public XDocument AddNewSubnet(XDocument VMXML, String Name)
  433. {
  434. XElement srcTree = new XElement("SubnetName", Name);
  435. VMXML.Descendants("SubnetNames").FirstOrDefault().Add(srcTree);
  436. return VMXML;
  437. }
  438. async public Task<XElement> GetOperationStatus(string requestId)
  439. {
  440. string uriFormat = "https://management.core.windows.net/{0}/operations/{1}";
  441. Uri uri = new Uri(String.Format(uriFormat, _subscriptionid, requestId));
  442. HttpClient http = GetHttpClient();
  443. Stream responseStream = await http.GetStreamAsync(uri);
  444. if (responseStream != null)
  445. {
  446. StreamReader response = new StreamReader(responseStream);
  447. if (responseStream != null)
  448. {
  449. XDocument xml = XDocument.Load(responseStream);
  450. return xml.Element(ns + "Operation");
  451. }
  452. }
  453. return null;
  454. }
  455. async public Task<OperationResult> PollGetOperationStatus(string requestId, int pollIntervalSeconds, int timeoutSeconds)
  456. {
  457. OperationResult result = new OperationResult();
  458. DateTime beginPollTime = DateTime.UtcNow;
  459. TimeSpan pollInterval = new TimeSpan(0, 0, pollIntervalSeconds);
  460. DateTime endPollTime = beginPollTime + new TimeSpan(0, 0, timeoutSeconds);
  461. bool done = false;
  462. while (!done)
  463. {
  464. XElement operation = await GetOperationStatus(requestId);
  465. result.RunningTime = DateTime.UtcNow - beginPollTime;
  466. try
  467. {
  468. // Turn the Status string into an OperationStatus value
  469. result.Status = (OperationStatus)Enum.Parse(
  470. typeof(OperationStatus),
  471. operation.Element(ns + "Status").Value);
  472. }
  473. catch (Exception)
  474. {
  475. throw new ApplicationException(string.Format(
  476. "Get Operation Status {0} returned unexpected status: {1}{2}",
  477. requestId,
  478. Environment.NewLine,
  479. operation.ToString(SaveOptions.OmitDuplicateNamespaces)));
  480. }
  481. switch (result.Status)
  482. {
  483. case OperationStatus.InProgress:
  484. Thread.Sleep((int)pollInterval.TotalMilliseconds);
  485. break;
  486. case OperationStatus.Failed:
  487. result.StatusCode = (HttpStatusCode)Convert.ToInt32(
  488. operation.Element(ns + "HttpStatusCode").Value);
  489. XElement error = operation.Element(ns + "Error");
  490. result.Code = error.Element(ns + "Code").Value;
  491. result.Message = error.Element(ns + "Message").Value;
  492. done = true;
  493. break;
  494. case OperationStatus.Succeeded:
  495. result.StatusCode = (HttpStatusCode)Convert.ToInt32(
  496. operation.Element(ns + "HttpStatusCode").Value);
  497. done = true;
  498. break;
  499. }
  500. if (!done && DateTime.UtcNow > endPollTime)
  501. {
  502. result.Status = OperationStatus.TimedOut;
  503. done = true;
  504. }
  505. }
  506. return result;
  507. }
  508. private static X509Certificate2 FindX509Certificate(string thumbprint)
  509. {
  510. X509Store certificateStore = null;
  511. X509Certificate2 certificate = null;
  512. try
  513. {
  514. certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
  515. certificateStore.Open(OpenFlags.ReadOnly);
  516. var certificates = certificateStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
  517. if (certificates.Count > 0)
  518. {
  519. certificate = certificates[0];
  520. }
  521. }
  522. finally
  523. {
  524. if (certificateStore != null) certificateStore.Close();
  525. }
  526. return certificate;
  527. }
  528. private static void ApplyNamespace(XElement parent, XNamespace nameSpace)
  529. {
  530. parent.Name = nameSpace + parent.Name.LocalName;
  531. foreach (XElement child in parent.Elements())
  532. {
  533. ApplyNamespace(child, nameSpace);
  534. }
  535. }
  536. }
  537. }