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

/MicroFrameworkPK_v4_2/Framework/Tools/BuildTasks/GetDeviceFrameworkPath.cs

https://bitbucket.org/pmfsampaio/netmf-lpc
C# | 322 lines | 251 code | 54 blank | 17 comment | 65 complexity | 8e77ff42f64b8570a820083565616ac4 MD5 | raw file
  1. #region Using directives
  2. using System;
  3. using System.IO;
  4. using System.Text;
  5. using Microsoft.Build.Framework;
  6. using Microsoft.Build.Utilities;
  7. using Microsoft.Win32;
  8. using System.Diagnostics;
  9. #endregion
  10. namespace Microsoft.SPOT.Tasks
  11. {
  12. public sealed class GetDeviceFrameworkPaths : Task
  13. {
  14. internal class RegistryValues
  15. {
  16. public const string Default = "";
  17. public const string FrameworkRegistryBase = @"Software\Microsoft\.NETMicroFramework";
  18. public const string FrameworkRegistryBase32 = @"Software\Wow6432Node\Microsoft\.NETMicroFramework";
  19. public const string InstallRoot = "InstallRoot";
  20. }
  21. public class Directories
  22. {
  23. public const string Tools = "Tools";
  24. public const string Assemblies = "Assemblies";
  25. }
  26. class RegistryKeys
  27. {
  28. public const string AssemblyFoldersEx = "AssemblyFoldersEx";
  29. }
  30. internal class MfSdkInternalError : Exception
  31. {
  32. public MfSdkInternalError(string errMsg)
  33. : base ("MF SDK internal error: " + errMsg + "; this MF SDK installation is not valid.")
  34. {
  35. }
  36. }
  37. #region Properties
  38. private string runtimeVersion = null;
  39. private string toolsPath;
  40. private string frameworkAssembliesPath, frameworkAssembliesPathLE, frameworkAssembliesPathBE;
  41. private string installRoot;
  42. public string RuntimeVersion
  43. {
  44. get { return runtimeVersion; }
  45. set { runtimeVersion = value; }
  46. }
  47. [Output]
  48. public string FrameworkAssembliesPath
  49. {
  50. get { return frameworkAssembliesPath; }
  51. set { frameworkAssembliesPath = value; }
  52. }
  53. [Output]
  54. public string FrameworkAssembliesPathLE
  55. {
  56. get { return frameworkAssembliesPathLE; }
  57. set { frameworkAssembliesPathLE = value; }
  58. }
  59. [Output]
  60. public string FrameworkAssembliesPathBE
  61. {
  62. get { return frameworkAssembliesPathBE; }
  63. set { frameworkAssembliesPathBE = value; }
  64. }
  65. [Output]
  66. public string ToolsPath
  67. {
  68. get { return toolsPath; }
  69. set { toolsPath = value; }
  70. }
  71. [Output]
  72. public string InstallRoot
  73. {
  74. get { return installRoot; }
  75. set { installRoot = value; }
  76. }
  77. #endregion
  78. #region ITask Members
  79. public override bool Execute()
  80. {
  81. try
  82. {
  83. if (!string.IsNullOrEmpty(runtimeVersion) && !runtimeVersion.StartsWith("v"))
  84. throw new MfSdkInternalError(String.Format("runtimeVersion string \"{0}\" is malformed", runtimeVersion));
  85. string build_root = Environment.GetEnvironmentVariable("BUILD_ROOT");
  86. if (!string.IsNullOrEmpty(runtimeVersion))
  87. {
  88. Version ver = Version.Parse(runtimeVersion.TrimStart('v'));
  89. installRoot = GetDeviceFrameworkValue("v" + ver.ToString(2), null, RegistryValues.InstallRoot);
  90. }
  91. if (installRoot == null || !Directory.Exists(installRoot) || 0 == string.Compare(Path.GetDirectoryName(Path.GetDirectoryName(installRoot)), Path.GetDirectoryName(build_root), true))
  92. {
  93. // If there is no install-root value, perhaps it's because this is an internal development build.
  94. // The SPOCLIENT environment variable should name a valid directory, and BUILD_TREE_CLIENT & BUILD_TREE_SERVER as well.
  95. // Otherwise, it really is a broken installation
  96. string spoclient = Environment.GetEnvironmentVariable(@"SPOCLIENT");
  97. string build_tree_client = Environment.GetEnvironmentVariable(@"BUILD_TREE_CLIENT");
  98. string build_tree_server = Environment.GetEnvironmentVariable(@"BUILD_TREE_SERVER");
  99. if (String.IsNullOrEmpty(spoclient) || String.IsNullOrEmpty(build_tree_client) || String.IsNullOrEmpty(build_tree_server))
  100. {
  101. throw new MfSdkInternalError("The MF SDK does not appear to be available on this machine");
  102. }
  103. installRoot = build_tree_client;
  104. toolsPath = Path.Combine(build_tree_server, @"DLL");
  105. frameworkAssembliesPath = Path.Combine(build_tree_client, @"DLL");
  106. frameworkAssembliesPathLE = frameworkAssembliesPath;
  107. frameworkAssembliesPathBE = frameworkAssembliesPath;
  108. }
  109. else
  110. {
  111. toolsPath = Path.Combine(installRoot, Directories.Tools);
  112. // Check the AssemblyFolder subkey; this is used only internally to support the mfpseudoinstaller style of running MF SDK;
  113. // not needed by the PK or by a real, installed, MF SDK. Not externally documented or supported.
  114. frameworkAssembliesPath = GetDeviceFrameworkValue(runtimeVersion, "AssemblyFolder", RegistryValues.Default);
  115. if (!string.IsNullOrEmpty(frameworkAssembliesPath))
  116. {
  117. if (!Directory.Exists(frameworkAssembliesPath))
  118. {
  119. Log.LogWarning("The directory \"{0}\" named by the AssemblyFolder key does not exist", frameworkAssembliesPath);
  120. frameworkAssembliesPath = null;
  121. }
  122. }
  123. frameworkAssembliesPath = Path.Combine(installRoot, Directories.Assemblies);
  124. if (Directory.Exists(Path.Combine(frameworkAssembliesPath, "be")))
  125. {
  126. frameworkAssembliesPathLE = Path.Combine(frameworkAssembliesPath, "le");
  127. frameworkAssembliesPathBE = Path.Combine(frameworkAssembliesPath, "be");
  128. frameworkAssembliesPath = frameworkAssembliesPathLE;
  129. }
  130. else
  131. {
  132. frameworkAssembliesPathLE = frameworkAssembliesPath;
  133. frameworkAssembliesPathBE = frameworkAssembliesPath;
  134. }
  135. FileInfo mscorlibLEInfo = new FileInfo(Path.Combine(frameworkAssembliesPathLE, @"mscorlib.dll"));
  136. FileInfo mscorlibBEInfo = new FileInfo(Path.Combine(frameworkAssembliesPathBE, @"mscorlib.dll"));
  137. FileInfo metadataProcessorInfo = new FileInfo(Path.Combine(toolsPath, @"MetadataProcessor.exe"));
  138. if (!Directory.Exists(toolsPath) || !metadataProcessorInfo.Exists)
  139. throw new MfSdkInternalError(String.Format("The directory \"{0}\" that should contain the MF SDK toolchain does not exist or is not fully installed", toolsPath));
  140. if (!Directory.Exists(frameworkAssembliesPathLE) || !mscorlibLEInfo.Exists)
  141. throw new MfSdkInternalError(String.Format("The directory \"{0}\" that should contain the MF SDK assemblies does not exist or is not fully installed", frameworkAssembliesPathLE));
  142. if (!Directory.Exists(frameworkAssembliesPathBE) || !mscorlibBEInfo.Exists)
  143. throw new MfSdkInternalError(String.Format("The directory \"{0}\" that should contain the MF SDK assemblies does not exist or is not fully installed", frameworkAssembliesPathBE));
  144. }
  145. return true;
  146. }
  147. catch (Exception ex)
  148. {
  149. try
  150. {
  151. Log.LogErrorFromException(ex);
  152. }
  153. catch{}
  154. }
  155. return false;
  156. }
  157. #endregion
  158. // This method by design does not catch any exceptions; it is intended only to be called by
  159. // public methods of this class, which ought necessarily to be handling their exceptions anyway.
  160. private static string GetDeviceFrameworkValue(string runtimeVersion, string subkey, string valueName)
  161. {
  162. // Look in HKCU first for the value
  163. string valueStr = GetDeviceFrameworkValue(Registry.CurrentUser, runtimeVersion, subkey, valueName);
  164. if ( valueStr != null )
  165. return valueStr;
  166. // Not there? try HKLM
  167. return GetDeviceFrameworkValue(Registry.LocalMachine, runtimeVersion, subkey, valueName);
  168. }
  169. // This private method by design does not catch any exceptions; it is intended only to be called by
  170. // public methods of this class, which ought necessarily to be handling their exceptions anyway.
  171. private static string GetDeviceFrameworkValue(RegistryKey topLevelKey, string runtimeVersion, string subkey, string valueName)
  172. {
  173. object value = null;
  174. RegistryKey key = OpenDeviceFrameworkKey(topLevelKey, runtimeVersion, subkey);
  175. if (key != null && (value = key.GetValue(valueName)) != null)
  176. {
  177. if (value is String)
  178. {
  179. return value as String;
  180. }
  181. else
  182. {
  183. throw new MfSdkInternalError(String.Format("The value of \"{0}\" at key \"{1}\" was not of type string", valueName, key.Name));
  184. }
  185. }
  186. return null;
  187. }
  188. public static string GetDeviceFrameworkValueOrThrow(string runtimeVersion, string subkey, string valueName)
  189. {
  190. string value = GetDeviceFrameworkValue(runtimeVersion, subkey, valueName);
  191. if ( value == null )
  192. {
  193. throw new MfSdkInternalError(
  194. runtimeVersion == null
  195. ? String.Format("\"{0}\" registry value not present at key \"{1}\" in the most recent version", valueName, subkey)
  196. : String.Format("\"{0}\" registry value not present at key \"{1}\" for runtime version {2}", valueName, subkey, runtimeVersion)
  197. );
  198. }
  199. return value;
  200. }
  201. public static RegistryKey OpenDeviceFrameworkKey(RegistryKey topLevelKey, string runtimeVersion, string subkey)
  202. {
  203. RegistryKey retVal = OpenDeviceFrameworkKey(topLevelKey, runtimeVersion, subkey, false);
  204. if (retVal == null)
  205. {
  206. retVal = OpenDeviceFrameworkKey(topLevelKey, runtimeVersion, subkey, true);
  207. }
  208. return retVal;
  209. }
  210. internal static RegistryKey OpenDeviceFrameworkKey(RegistryKey topLevelKey, string runtimeVersion, string subkey, bool fWow64)
  211. {
  212. if (runtimeVersion == null)
  213. {
  214. // attempt to get the 'Product' version of the current executing assembly first;
  215. // by convention we use the InformationalVersion attribute as the Product version
  216. System.Reflection.AssemblyInformationalVersionAttribute[] myInformationalVersionAttributes
  217. = (System.Reflection.AssemblyInformationalVersionAttribute[]) System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(System.Reflection.AssemblyInformationalVersionAttribute), false);
  218. if (null != myInformationalVersionAttributes && myInformationalVersionAttributes.Length > 0)
  219. {
  220. string[] verParts = myInformationalVersionAttributes[0].InformationalVersion.Split(new Char[]{'.'});
  221. if ( verParts == null || verParts.Length == 0)
  222. runtimeVersion = "v4.2";
  223. else if (verParts.Length == 1)
  224. runtimeVersion = String.Format("v{0}.0", verParts[0]);
  225. else
  226. runtimeVersion = String.Format("v{0}.{1}", verParts[0], verParts[1]);
  227. }
  228. }
  229. if (runtimeVersion == null)
  230. {
  231. // Fall back to using the version of this individual assembly if the product-wide version is not present
  232. Version myVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
  233. runtimeVersion = String.Format("v{0}.{1}", myVersion.Major, myVersion.Minor);
  234. }
  235. //call dispose on all these open keys?
  236. string frameworkRegistryBase = fWow64 ? RegistryValues.FrameworkRegistryBase32 : RegistryValues.FrameworkRegistryBase;
  237. // Find registry location
  238. RegistryKey hiveroot = topLevelKey.OpenSubKey(frameworkRegistryBase);
  239. if (hiveroot == null)
  240. return null;
  241. // Find latest version
  242. string version = "v0";
  243. RegistryKey vKey = null;
  244. RegistryKey key = null;
  245. foreach (string subkeyname in hiveroot.GetSubKeyNames())
  246. {
  247. if (runtimeVersion != null && subkeyname.Length < runtimeVersion.Length)
  248. continue;
  249. if (runtimeVersion == null || subkeyname.Substring(0, runtimeVersion.Length) == runtimeVersion)
  250. {
  251. if ((key = hiveroot.OpenSubKey(subkeyname)) == null)
  252. continue;
  253. if (subkey != null && subkey.Length > 0)
  254. {
  255. if ((key = key.OpenSubKey(subkey)) == null)
  256. continue;
  257. }
  258. if (key != null && String.Compare(subkeyname, version) > 0)
  259. {
  260. version = subkeyname;
  261. vKey = key;
  262. }
  263. }
  264. }
  265. return vKey;
  266. }
  267. }
  268. }