public async Task InitializeAsync() { await _threadHandling.Value.SwitchToUIThread(); // Initialize our cache file string appDataFolder = await _shellUtilitiesHelper.Value.GetLocalAppDataFolderAsync(_vsShellService); if (appDataFolder != null) { _versionDataCacheFile = new RemoteCacheFile(Path.Combine(appDataFolder, s_versionDataFilename), s_versionCompatibilityDownloadFwlink, TimeSpan.FromHours(s_cacheFileValidHours), _fileSystem.Value, _httpClient); } VisualStudioVersion = await _shellUtilitiesHelper.Value.GetVSVersionAsync(_vsAppIdService); _vsSolution = await _vsSolutionService.GetValueAsync(); Verify.HResult(_vsSolution.AdviseSolutionEvents(this, out _solutionCookie)); // Check to see if a solution is already open. If so we set _solutionOpened to true so that subsequent projects added to // this solution are processed. if (ErrorHandler.Succeeded(_vsSolution.GetProperty((int)__VSPROPID4.VSPROPID_IsSolutionFullyLoaded, out object isFullyLoaded)) && isFullyLoaded is bool isFullyLoadedBool && isFullyLoadedBool) { SolutionOpen = true; // do not block package initialization on this _threadHandling.Value.RunAndForget(async() => { // First make sure that the cache file exists if (_versionDataCacheFile.ReadCacheFile() is null) { await _versionDataCacheFile.TryToUpdateCacheFileAsync(); } // check if the project is compatible await CheckCompatibilityAsync(); }, unconfiguredProject: null); } }
/// <summary> /// Pings the server to download version compatibility information and stores this in a cached file in the users app data. If the cached file is /// less than 24 hours old, it uses that data. Otherwise it downloads from the server. If the download fails it will use the previously cached /// file, or if that file doesn't not exist, it uses the data baked into this class /// </summary> private VersionCompatibilityData GetVersionCmpatibilityData() { // Do we need to update our cached data? Note that since the download could take a long time like tens of seconds we don't really want to // start showing messages to the user well after their project is opened and they are interacting with it. Thus we start a task to update the // file, so that the next time we come here, we have updated data. if (_curVersionCompatibilityData != null && _timeCurVersionDataLastUpdatedUtc.AddHours(CacheFileValidHours).IsLaterThan(DateTime.UtcNow)) { return(_curVersionCompatibilityData); } try { // Try the cache file Dictionary <Version, VersionCompatibilityData> versionCompatData = GetCompabilityDataFromCacheFile(); // See if the cache file needs refreshing and if so, kick off a task to do so if (_versionDataCacheFile != null && _versionDataCacheFile.CacheFileIsStale()) { Task noWait = _versionDataCacheFile.TryToUpdateCacheFileAsync(() => { // Invalidate the in-memory cached data on success _timeCurVersionDataLastUpdatedUtc = DateTime.MinValue; }); } if (versionCompatData != null) { // First try to match exatly on our VS version and if that fails, match on just major, minor if (versionCompatData.TryGetValue(_ourVSVersion, out VersionCompatibilityData compatData) || versionCompatData.TryGetValue(new Version(_ourVSVersion.Major, _ourVSVersion.Minor), out compatData)) { // Now fix up missing data if (string.IsNullOrEmpty(compatData.OpenSupportedMessage)) { compatData.OpenSupportedMessage = VSResources.PartialSupportedDotNetCoreProject; } if (string.IsNullOrEmpty(compatData.OpenUnsupportedMessage)) { compatData.OpenUnsupportedMessage = VSResources.NotSupportedDotNetCoreProject; } UpdateInMemoryCachedData(compatData); } } } catch { } if (_curVersionCompatibilityData == null) { // Something failed or no remote file, use the compatibility data we shipped with which does not have any warnings UpdateInMemoryCachedData(new VersionCompatibilityData() { OpenSupportedMessage = VSResources.PartialSupportedDotNetCoreProject, OpenUnsupportedMessage = VSResources.NotSupportedDotNetCoreProject }); } return(_curVersionCompatibilityData); }