/// <summary> /// Retrieves a collection of locales available to download the help for /// </summary> /// <returns> /// Collection of Locales available /// </returns> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public ICollection <Locale> LoadAvailableLocales(string vsVersion) { string catalogPath = string.Format("catalogs/{0}", vsVersion); Debug.Print("Downloading locales list from {0}{1}", client.BaseAddress, catalogPath); return(HelpIndexManager.LoadLocales(client.DownloadData(catalogPath))); }
/// <summary> /// Retrieves a collection of locales available to download the help for /// </summary> /// <returns> /// Collection of Locales available /// </returns> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public async Task <ICollection <Locale> > LoadAvailableLocalesAsync(string vsVersion) { string catalogPath = string.Format("catalogs/{0}", vsVersion); Debug.Print("Downloading locales list from {0}{1}", client.BaseAddress, catalogPath); ICollection <Locale> locales = HelpIndexManager.LoadLocales(await client.DownloadDataTaskAsync(catalogPath)); return(locales); }
/// <summary> /// Download information about the available books for the selected locale /// </summary> /// <param name="path"> /// The relative path to the book catalog download location /// </param> /// <returns> /// Collection of available bookGroups /// </returns> /// <exception cref="NullReferenceException"> /// If path is null or empty /// </exception> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public ICollection <BookGroup> LoadBooksInformation(string path) { if (path == null) { throw new ArgumentNullException("path"); } Debug.Print("Downloading books list from {0}{1}", client.BaseAddress, path); return(HelpIndexManager.LoadBooks(client.DownloadData(path))); }
/// <summary> /// Retrieves a collection of locales available to download the help for /// </summary> /// <returns> /// Collection of Locales available /// </returns> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public ICollection <Locale> LoadAvailableLocales(string vsVersion) { string catalogPath = string.Format("catalogs/{0}", vsVersion); Debug.Print("Downloading locales list from {0}{1}", client.BaseAddress, catalogPath); ICollection <Locale> locales = HelpIndexManager.LoadLocales(client.DownloadData(catalogPath)); foreach (Locale l in locales) { l.CatalogLink = l.CatalogLink.Replace("dev14", "dev15"); } return(locales); }
/// <summary> /// Retrieves a collection of locales available to download the help for /// </summary> /// <returns> /// Collection of Locales available /// </returns> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public ICollection <Locale> LoadAvailableLocales(string vsVersion) { // FIXME: Locales are not currently present for VS2017 if (vsVersion.Equals("dev15", StringComparison.OrdinalIgnoreCase)) { vsVersion = "dev14"; } string catalogPath = string.Format("catalogs/{0}", vsVersion); Debug.Print("Downloading locales list from {0}{1}", client.BaseAddress, catalogPath); ICollection <Locale> locales = HelpIndexManager.LoadLocales(client.DownloadData(catalogPath)); // FIXME: The path for the locales is pointing VS2015 docs due the fix above, fix them to point to VS2017 foreach (Locale l in locales) { l.CatalogLink = l.CatalogLink.Replace("dev14", "dev15"); } return(locales); }
/// <summary> /// Download the requested books and create the appropriate index files for MSDN HelpViewer /// </summary> /// <param name="bookGroups"> /// The collection of bookGroups to with the books to download indicated by the Book.Wanted /// property /// </param> /// <param name="cachePath"> /// The path where the downloaded books are cached /// </param> /// <param name="progress"> /// Interface used to report the percentage progress back to the GUI /// </param> /// <exception cref="ArgumentNullException"> /// If any of the parameters are null /// </exception> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="IOException"> /// If there was a problem reading or writing to the cache directory /// </exception> /// <exception cref="UnauthorizedAccessException"> /// If the user does not have permission to write to the cache directory /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public void DownloadBooks(ICollection <BookGroup> bookGroups, string cachePath, IProgress <int> progress) { if (bookGroups == null) { throw new ArgumentNullException("bookGroups"); } if (cachePath == null) { throw new ArgumentNullException("cachePath"); } if (cachePath == null) { throw new ArgumentNullException("progress"); } // Create cachePath string targetDirectory = Path.Combine(cachePath, "Packages"); if (!Directory.Exists(targetDirectory)) { Directory.CreateDirectory(targetDirectory); } // Cleanup index files Directory.GetFiles(cachePath, "*.msha").ForEach(File.Delete); Directory.GetFiles(cachePath, "*.xml").ForEach(File.Delete); // Creating setup indexes File.WriteAllText( Path.Combine(cachePath, "HelpContentSetup.msha"), HelpIndexManager.CreateSetupIndex(bookGroups), Encoding.UTF8); // Create list of unique packages for possible download and write the book group and // book index files Dictionary <string, Package> packages = new Dictionary <string, Package>(); foreach (BookGroup bookGroup in bookGroups) { File.WriteAllText( Path.Combine(cachePath, bookGroup.CreateFileName()), HelpIndexManager.CreateBookGroupBooksIndex(bookGroup), Encoding.UTF8); Debug.Print("BookGroup: {0}", bookGroup.Name); foreach (Book book in bookGroup.Books) { if (book.Wanted) { Debug.Print(" Book: {0}", book.Name); File.WriteAllText( Path.Combine(cachePath, book.CreateFileName()), HelpIndexManager.CreateBookPackagesIndex(bookGroup, book), Encoding.UTF8); foreach (Package package in book.Packages) { string name = package.Name.ToUpperInvariant(); Debug.Print(" Package: {0}", name); if (!packages.ContainsKey(name)) { packages.Add(name, package); } } } } } // Cleanup old files foreach (string file in Directory.GetFiles(targetDirectory, "*.cab")) { string fileName = Path.GetFileNameWithoutExtension(file); if (!string.IsNullOrEmpty(fileName)) { fileName = fileName.ToUpperInvariant(); if (!packages.ContainsKey(fileName)) { File.Delete(file); } } } // Download the packages int packagesCountCurrent = 0; client.BaseAddress = "http://packages.mtps.microsoft.com/"; foreach (Package package in packages.Values) { string targetFileName = Path.Combine(targetDirectory, package.CreateFileName()); if (package.State == PackageState.NotDownloaded || package.State == PackageState.OutOfDate) { Debug.Print(" Downloading : '{0}' to '{1}'", package.Link, targetFileName); client.DownloadFile(package.Link, targetFileName); if (AuthenticodeTools.IsTrusted(targetFileName)) { File.SetCreationTime(targetFileName, package.LastModified); File.SetLastAccessTime(targetFileName, package.LastModified); File.SetLastWriteTime(targetFileName, package.LastModified); } else { Debug.Print("The signature on '{0}' is not valid - deleting"); File.Delete(targetFileName); throw new InvalidDataException($"The signature on '{targetFileName}' is not valid - deleting"); } } progress.Report(100 * ++packagesCountCurrent / packages.Count); } }
/// <summary> /// Download the requested books and create the appropriate index files for MSDN HelpViewer /// </summary> /// <param name="bookGroups"> /// The collection of bookGroups to with the books to download indicated by the Book.Wanted /// property /// </param> /// <param name="cachePath"> /// The path where the downloaded books are cached /// </param> /// <param name="progress"> /// Interface used to report the percentage progress back to the GUI /// </param> /// <exception cref="ArgumentNullException"> /// If any of the parameters are null /// </exception> /// <exception cref="WebException"> /// If the data cannot be downloaded /// </exception> /// <exception cref="XmlException"> /// If the data cannot be processed /// </exception> /// <exception cref="IOException"> /// If there was a problem reading or writing to the cache directory /// </exception> /// <exception cref="UnauthorizedAccessException"> /// If the user does not have permission to write to the cache directory /// </exception> /// <exception cref="InvalidOperationException"> /// If the data cannot be processed /// </exception> public void DownloadBooks(ICollection <BookGroup> bookGroups, string cachePath, string finalDirectory, Locale locale, MyProgress progress) { if (bookGroups == null) { throw new ArgumentNullException("bookGroups"); } if (cachePath == null) { throw new ArgumentNullException("cachePath"); } if (cachePath == null) { throw new ArgumentNullException("progress"); } // Create cachePath string targetDirectory = Path.Combine(cachePath, "Packages"); if (!Directory.Exists(targetDirectory)) { Directory.CreateDirectory(targetDirectory); } // Create content directories string contentDirectory = null; string indexDirectory = null; if (finalDirectory != null) { if (!Directory.Exists(finalDirectory)) { Directory.CreateDirectory(finalDirectory); } contentDirectory = Path.Combine(finalDirectory, "ContentStore"); if (!Directory.Exists(contentDirectory)) { Directory.CreateDirectory(contentDirectory); } indexDirectory = Path.Combine(finalDirectory, "IndexStore"); if (!Directory.Exists(indexDirectory)) { Directory.CreateDirectory(indexDirectory); } string localeName = "en-US"; try { localeName = CultureInfo.CreateSpecificCulture(locale.Name).Name; } catch { } contentDirectory = Path.Combine(contentDirectory, localeName); if (!Directory.Exists(contentDirectory)) { Directory.CreateDirectory(contentDirectory); } indexDirectory = Path.Combine(indexDirectory, localeName); if (!Directory.Exists(indexDirectory)) { Directory.CreateDirectory(indexDirectory); } } // Create locale name // Cleanup index files Directory.GetFiles(cachePath, "*.msha").ForEach(File.Delete); Directory.GetFiles(cachePath, "*.xml").ForEach(File.Delete); // Creating setup indexes File.WriteAllText( Path.Combine(cachePath, "HelpContentSetup.msha"), HelpIndexManager.CreateSetupIndex(bookGroups), Encoding.UTF8); // Create list of unique packages for possible download and write the book group and // book index files Dictionary <string, Package> packages = new Dictionary <string, Package>(); foreach (BookGroup bookGroup in bookGroups) { File.WriteAllText( Path.Combine(cachePath, bookGroup.CreateFileName()), HelpIndexManager.CreateBookGroupBooksIndex(bookGroup), Encoding.UTF8); Debug.Print("BookGroup: {0}", bookGroup.Name); foreach (Book book in bookGroup.Books) { if (book.Wanted) { Debug.Print(" Book: {0}", book.Name); File.WriteAllText( Path.Combine(cachePath, book.CreateFileName()), HelpIndexManager.CreateBookPackagesIndex(bookGroup, book), Encoding.UTF8); foreach (Package package in book.Packages) { string name = package.Name.ToUpperInvariant(); Debug.Print(" Package: {0}", name); if (!packages.ContainsKey(name)) { packages.Add(name, package); } } } } } // Cleanup old files foreach (string file in Directory.GetFiles(targetDirectory, "*.cab")) { string fileName = Path.GetFileNameWithoutExtension(file); if (!string.IsNullOrEmpty(fileName)) { fileName = fileName.ToUpperInvariant(); if (!packages.ContainsKey(fileName)) { File.Delete(file); } } } // Download the packages int packagesCountCurrent = 0; client.BaseAddress = "http://packages.mtps.microsoft.com/"; foreach (Package package in packages.Values) { string targetFileName = Path.Combine(targetDirectory, package.CreateFileName()); if (package.State == PackageState.NotDownloaded || package.State == PackageState.OutOfDate) { Debug.Print(" Downloading : '{0}' to '{1}'", package.Link, targetFileName); client.DownloadFile(package.Link, targetFileName); File.SetCreationTime(targetFileName, package.LastModified); File.SetLastAccessTime(targetFileName, package.LastModified); File.SetLastWriteTime(targetFileName, package.LastModified); } progress.Report(100 * ++packagesCountCurrent / packages.Count); } // move files if (finalDirectory != null) { packagesCountCurrent = 0; progress.Report(0); Directory.GetFiles(contentDirectory, "*.*").ForEach(File.Delete); Directory.GetFiles(indexDirectory, "*.*").ForEach(File.Delete); foreach (Package package in packages.Values) { string targetFileName = Path.Combine(targetDirectory, package.CreateFileName()); Debug.Print(" Moving : '{0}' to '{1}'", targetFileName, finalDirectory); Move(targetFileName, contentDirectory, indexDirectory); progress.Report(100 * ++packagesCountCurrent / packages.Count); } } }