/// <summary>
        /// Get the SDK.
        /// </summary>
        /// <returns>true</returns>
        public override bool Execute()
        {
            // TargetPlatformVersion and TargetPlatformIdentifier are requried to correctly look for SDKs.
            if (String.IsNullOrEmpty(TargetPlatformVersion) || String.IsNullOrEmpty(TargetPlatformIdentifier))
            {
                Log.LogErrorWithCodeFromResources("GetInstalledSDKs.TargetPlatformInformationMissing");
                return(false);
            }

            // Dictionary of ESDKs. Each entry is a (location, platform version) tuple
            IDictionary <string, Tuple <string, string> > installedSDKs = null;

            try
            {
                Log.LogMessageFromResources("GetInstalledSDKs.SearchingForSDKs", _targetPlatformIdentifier, _targetPlatformVersion);

                Version platformVersion = Version.Parse(TargetPlatformVersion);
                installedSDKs = ToolLocationHelper.GetPlatformExtensionSDKLocationsAndVersions(SDKDirectoryRoots, SDKExtensionDirectoryRoots, SDKRegistryRoot, TargetPlatformIdentifier, platformVersion);
            }
            catch (Exception e)
            {
                if (ExceptionHandling.IsCriticalException(e))
                {
                    throw;
                }

                Log.LogErrorWithCodeFromResources("GetInstalledSDKs.CouldNotGetSDKList", e.Message);
            }

            List <ITaskItem> outputItems = new List <ITaskItem>();

            if (installedSDKs != null && installedSDKs.Count > 0)
            {
                Log.LogMessageFromResources(MessageImportance.Low, "GetInstalledSDKs.FoundSDKs", installedSDKs.Count);
                Log.LogMessageFromResources(MessageImportance.Low, "GetInstalledSDKs.ListInstalledSDKs");

                foreach (KeyValuePair <string, Tuple <string, string> > sdk in installedSDKs)
                {
                    string sdkInfo = ResourceUtilities.FormatResourceString("GetInstalledSDKs.SDKNameAndLocation", sdk.Key, sdk.Value.Item1);
                    Log.LogMessageFromResources(MessageImportance.Low, "ResolveAssemblyReference.FourSpaceIndent", sdkInfo);

                    TaskItem item = new TaskItem(sdk.Value.Item1);
                    item.SetMetadata("SDKName", sdk.Key);
                    item.SetMetadata("PlatformVersion", sdk.Value.Item2);

                    // Need to stash these so we can unroll the platform via GetMatchingPlatformSDK when we get the reference files for the sdks
                    item.SetMetadata(DirectoryRootsMetadataName, String.Join(";", SDKDirectoryRoots ?? new string[0]));
                    item.SetMetadata(ExtensionDirectoryRootsMetadataName, String.Join(";", SDKExtensionDirectoryRoots ?? new string[0]));
                    item.SetMetadata(RegistryRootMetadataName, SDKRegistryRoot);

                    outputItems.Add(item);
                }
            }
            else
            {
                Log.LogWarningWithCodeFromResources("GetInstalledSDKs.NoSDksFound");
            }

            InstalledSDKs = outputItems.ToArray();

            // We need to register an object so that at the end of the build we will clear the static toolLocationhelper caches.
            // this is important because if someone adds an SDK between builds we would not know about it and not be able to use it.
            // This code is mainly used to deal with the case where msbuild nodes hang around between builds.
            IBuildEngine4 buildEngine4 = BuildEngine as IBuildEngine4;

            if (buildEngine4 != null)
            {
                object staticCacheDisposer = buildEngine4.GetRegisteredTaskObject(StaticSDKCacheKey, RegisteredTaskObjectLifetime.Build);
                if (staticCacheDisposer == null)
                {
                    BuildCacheDisposeWrapper staticDisposer = new BuildCacheDisposeWrapper(new BuildCacheDisposeWrapper.CallDuringDispose(ToolLocationHelper.ClearSDKStaticCache));
                    buildEngine4.RegisterTaskObject(StaticSDKCacheKey, staticDisposer, RegisteredTaskObjectLifetime.Build, allowEarlyCollection: false);
                }
            }

            return(!Log.HasLoggedErrors);
        }
        /// <summary>
        /// Get the SDK.
        /// </summary>
        /// <returns>true</returns>
        public override bool Execute()
        {
            // TargetPlatformVersion and TargetPlatformIdentifier are requried to correctly look for SDKs.
            if (String.IsNullOrEmpty(TargetPlatformVersion) || String.IsNullOrEmpty(TargetPlatformIdentifier))
            {
                Log.LogErrorWithCodeFromResources("GetInstalledSDKs.TargetPlatformInformationMissing");
                return false;
            }

            // Dictionary of ESDKs. Each entry is a (location, platform version) tuple
            IDictionary<string, Tuple<string, string>> installedSDKs = null;

            try
            {
                Log.LogMessageFromResources("GetInstalledSDKs.SearchingForSDKs", _targetPlatformIdentifier, _targetPlatformVersion);

                Version platformVersion = Version.Parse(TargetPlatformVersion);
                installedSDKs = ToolLocationHelper.GetPlatformExtensionSDKLocationsAndVersions(SDKDirectoryRoots, SDKExtensionDirectoryRoots, SDKRegistryRoot, TargetPlatformIdentifier, platformVersion);
            }
            catch (Exception e)
            {
                if (ExceptionHandling.IsCriticalException(e))
                {
                    throw;
                }

                Log.LogErrorWithCodeFromResources("GetInstalledSDKs.CouldNotGetSDKList", e.Message);
            }

            List<ITaskItem> outputItems = new List<ITaskItem>();

            if (installedSDKs != null && installedSDKs.Count > 0)
            {
                Log.LogMessageFromResources(MessageImportance.Low, "GetInstalledSDKs.FoundSDKs", installedSDKs.Count);
                Log.LogMessageFromResources(MessageImportance.Low, "GetInstalledSDKs.ListInstalledSDKs");

                foreach (KeyValuePair<string, Tuple<string, string>> sdk in installedSDKs)
                {
                    string sdkInfo = ResourceUtilities.FormatResourceString("GetInstalledSDKs.SDKNameAndLocation", sdk.Key, sdk.Value.Item1);
                    Log.LogMessageFromResources(MessageImportance.Low, "ResolveAssemblyReference.FourSpaceIndent", sdkInfo);

                    TaskItem item = new TaskItem(sdk.Value.Item1);
                    item.SetMetadata("SDKName", sdk.Key);
                    item.SetMetadata("PlatformVersion", sdk.Value.Item2);

                    // Need to stash these so we can unroll the platform via GetMatchingPlatformSDK when we get the reference files for the sdks
                    item.SetMetadata(DirectoryRootsMetadataName, String.Join(";", SDKDirectoryRoots ?? new string[0]));
                    item.SetMetadata(ExtensionDirectoryRootsMetadataName, String.Join(";", SDKExtensionDirectoryRoots ?? new string[0]));
                    item.SetMetadata(RegistryRootMetadataName, SDKRegistryRoot);

                    outputItems.Add(item);
                }
            }
            else
            {
                Log.LogWarningWithCodeFromResources("GetInstalledSDKs.NoSDksFound");
            }

            InstalledSDKs = outputItems.ToArray();

            // We need to register an object so that at the end of the build we will clear the static toolLocationhelper caches.
            // this is important because if someone adds an SDK between builds we would not know about it and not be able to use it.
            // This code is mainly used to deal with the case where msbuild nodes hang around between builds.
            IBuildEngine4 buildEngine4 = BuildEngine as IBuildEngine4;
            if (buildEngine4 != null)
            {
                object staticCacheDisposer = buildEngine4.GetRegisteredTaskObject(StaticSDKCacheKey, RegisteredTaskObjectLifetime.Build);
                if (staticCacheDisposer == null)
                {
                    BuildCacheDisposeWrapper staticDisposer = new BuildCacheDisposeWrapper(new BuildCacheDisposeWrapper.CallDuringDispose(ToolLocationHelper.ClearSDKStaticCache));
                    buildEngine4.RegisterTaskObject(StaticSDKCacheKey, staticDisposer, RegisteredTaskObjectLifetime.Build, allowEarlyCollection: false);
                }
            }

            return !Log.HasLoggedErrors;
        }