/// <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 <Catalog> LoadAvailableCatalogs() { ICollection <Catalog> result = HelpIndexManager.LoadCatalogs(_client.DownloadData("")); Catalog catalogVisualStudio10 = new Catalog { Name = "VisualStudio10", Description = "VisualStudio10", CatalogLink = string.Empty//"../catalogs/VisualStudio10" }; Catalog catalogDev10 = new Catalog { Name = "dev10", Description = "dev10", CatalogLink = string.Empty//"../catalogs/dev10" }; if (!result.Contains(catalogVisualStudio10) && !result.Contains(catalogDev10)) { result.Add(catalogDev10); } var catalogs = result as List <Catalog>; catalogs?.Sort(); return(result); }
/// <summary> /// Download information about the available books for the selected locale /// </summary> /// <param name="catalog"></param> /// <param name="catalogLocale"></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(Catalog catalog, CatalogLocale catalogLocale) { if (catalogLocale == null) { throw new ArgumentNullException(nameof(catalogLocale)); } // 由于返回的Locale_Link的相对地址有问题,所以 // client.BaseAddress = @"http://services.mtps.microsoft.com/ServiceAPI/catalogs/"; // 不能改为 // client.BaseAddress = @"http://services.mtps.microsoft.com/ServiceAPI/catalogs"; return(HelpIndexManager.LoadBooks(catalog, _client.DownloadData(catalogLocale.LocaleLink))); }
/// <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 <CatalogLocale> LoadAvailableLocales(Catalog nameCatalog) { if (nameCatalog == null) { throw new ArgumentNullException("catalog"); } ICollection <CatalogLocale> result; if (string.Empty == nameCatalog.CatalogLink) { result = new List <CatalogLocale>(); } else { result = HelpIndexManager.LoadLocales(client.DownloadData(nameCatalog.CatalogLink)); } //List<CatalogLocale> result = new List<CatalogLocale>(); string[] Names = { "cs-cz", "de-de", "en-us", "es-es", "fr-fr", "it-it", "ja-jp", "ko-kr", "pl-pl", "pt-br", "ru-ru", "tr-tr", "zh-cn", "zh-tw" }; if (result.Count < Names.Length) { result.Clear(); foreach (string name in Names) { result.Add( new CatalogLocale { Locale = name, CatalogName = nameCatalog.Name, Description = nameCatalog.Name, LocaleLink = ((string.Empty != nameCatalog.CatalogLink) ? (nameCatalog.CatalogLink + @"/" + name) : (@"../catalogs/" + nameCatalog.Name + @"/" + name)) }); } } (result as List <CatalogLocale>).Sort(); return(result); }
/// <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="objLocale"></param> /// <param name="progress"> /// Interface used to report the percentage progress back to the GUI /// </param> /// <param name="objCatalog"></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, Catalog objCatalog, CatalogLocale objLocale, IProgress <int> progress) { if (bookGroups == null) { throw new ArgumentNullException(nameof(bookGroups)); } if (cachePath == null) { throw new ArgumentNullException(nameof(cachePath)); } if (objCatalog == null) { throw new ArgumentNullException(nameof(objCatalog)); } if (objLocale == null) { throw new ArgumentNullException(nameof(objLocale)); } string nameCatalog = objCatalog.DisplayName; string codeLocale = objLocale.Locale; //if ( progress == null ) //{ // throw new ArgumentNullException( "progress" ); //} DateTime lastModifiedTimeCatalogLocale = new DateTime(2000, 1, 1, 0, 0, 0); List <string> strLocales = new List <string>(); // 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>(); if (objCatalog.Name == "dev10") { var lastModifiedTime = new DateTime(2000, 1, 1, 0, 0, 0); // Add branding packages var brandingPackgeName1 = new Package { Name = BrandingPackageName1, Deployed = @"true", LastModified = DateTime.Now, PackageEtag = null, CurrentLink = string.Format(CultureInfo.InvariantCulture, "{0}{1}.cab", BrandingPackageUrl, BrandingPackageName1), CurrentLinkContext = string.Format(CultureInfo.InvariantCulture, "{0}.cab", BrandingPackageName1), PackageSizeBytes = 0, PackageSizeBytesUncompressed = 0, PackageConstituentLink = string.Format(CultureInfo.InvariantCulture, "{0}{1}", @"../../serviceapi/packages/brands/", BrandingPackageName1) }; brandingPackgeName1.LastModified = FetchLastModified(brandingPackgeName1.CurrentLink); brandingPackgeName1.PackageSizeBytes = FetchContentLength(brandingPackgeName1.CurrentLink); brandingPackgeName1.PackageSizeBytesUncompressed = brandingPackgeName1.PackageSizeBytes; //packages.Add(brandingPackgeName1.Name.ToLowerInvariant(), brandingPackgeName1); packages.Add(brandingPackgeName1.CurrentLinkContext.ToLowerInvariant(), brandingPackgeName1); if (brandingPackgeName1.LastModified > lastModifiedTime) { lastModifiedTime = brandingPackgeName1.LastModified; } var brandingPackgeName2 = new Package { Name = BrandingPackageName2, Deployed = @"true", LastModified = DateTime.Now, PackageEtag = null, CurrentLink = string.Format(CultureInfo.InvariantCulture, "{0}{1}.cab", BrandingPackageUrl, BrandingPackageName2), CurrentLinkContext = string.Format(CultureInfo.InvariantCulture, "{0}.cab", BrandingPackageName2), PackageSizeBytes = 0, PackageSizeBytesUncompressed = 0, PackageConstituentLink = string.Format(CultureInfo.InvariantCulture, "{0}{1}", @"../../serviceapi/packages/brands/", BrandingPackageName2) }; brandingPackgeName2.LastModified = FetchLastModified(brandingPackgeName2.CurrentLink); brandingPackgeName2.PackageSizeBytes = FetchContentLength(brandingPackgeName2.CurrentLink); brandingPackgeName2.PackageSizeBytesUncompressed = brandingPackgeName2.PackageSizeBytes; //packages.Add(brandingPackgeName2.Name.ToLowerInvariant(), brandingPackgeName2); packages.Add(brandingPackgeName2.CurrentLinkContext.ToLowerInvariant(), brandingPackgeName2); if (brandingPackgeName2.LastModified > lastModifiedTime) { // ReSharper disable once RedundantAssignment lastModifiedTime = brandingPackgeName2.LastModified; } } foreach (BookGroup bookGroup in bookGroups) { //File.WriteAllText( // Path.Combine( cachePath, bookGroup.CreateFileName() ), // HelpIndexManager.CreateBookGroupBooksIndex( bookGroup ), // Encoding.UTF8 ); //Debug.Print( "BookGroup: {0}", bookGroup.Name ); var lastModifiedTimeBookGroup = new DateTime(2000, 1, 1, 0, 0, 0); foreach (Book book in bookGroup.Books) { var lastModifiedTimeBook = new DateTime(2000, 1, 1, 0, 0, 0); foreach (Package package in book.Packages) { if (book.Wanted) { //string name = package.Name.ToLowerInvariant(); string name = package.CurrentLinkContext.ToLowerInvariant(); //Debug.Print( " Package: {0}", name ); if (!packages.ContainsKey(name)) { //package.LastModified = FetchLastModified(package.CurrentLink); //package.PackageSizeBytes = FetchContentLength(package.CurrentLink); packages.Add(name, package); } //package.LastModified = packages[name].LastModified; //package.PackageSizeBytes = packages[name].PackageSizeBytes; } if (package.LastModified > lastModifiedTimeBook) { lastModifiedTimeBook = package.LastModified; } } if (book.Wanted) { //Debug.Print( " Book: {0}", book.Name ); //File.WriteAllText( // Path.Combine( cachePath, book.CreateFileName() ), // HelpIndexManager.CreateBookPackagesIndex( bookGroup, book ), // Encoding.UTF8 ); if (!strLocales.Contains(book.Locale)) { strLocales.Add(book.Locale); } } book.LastModified = lastModifiedTimeBook; if (book.LastModified > lastModifiedTimeBookGroup) { lastModifiedTimeBookGroup = book.LastModified; } } bookGroup.LastModified = lastModifiedTimeBookGroup; if (bookGroup.LastModified > lastModifiedTimeCatalogLocale) { lastModifiedTimeCatalogLocale = bookGroup.LastModified; } } bool includeEnUs = false; if (0 == strLocales.Count) { return; } if (1 == strLocales.Count) { codeLocale = strLocales[0]; } else if (2 == strLocales.Count) { includeEnUs = true; foreach (string strLoc in strLocales) { if (strLoc.ToLowerInvariant() != "en-us") { codeLocale = strLoc; break; } } } if (!Directory.Exists(cachePath)) { Directory.CreateDirectory(cachePath); } string vsDirectory = Path.Combine(cachePath, nameCatalog); if (!Directory.Exists(vsDirectory)) { Directory.CreateDirectory(vsDirectory); } // Generate Download File List try { string listFileName = objLocale.CreatePackageListFileName(); string listFilePath = Path.Combine(cachePath, listFileName); if (File.Exists(listFilePath)) { File.Delete(listFilePath); } listFilePath = Path.Combine(vsDirectory, listFileName); if (File.Exists(listFilePath)) { File.Delete(listFilePath); } StreamWriter writer = new StreamWriter(listFilePath); //IEnumerable<Package> query = packages.Values.OrderBy(package => package.CurrentLink); var query = packages.Values.ToList(); query.Sort(); foreach (Package package in query) { writer.WriteLine(package.CurrentLink); } writer.Close(); FileLastModifiedTime(listFilePath, lastModifiedTimeCatalogLocale); //File.SetCreationTime( listFilePath, lastModifiedTimeCatalogLocale ); //File.SetLastAccessTime( listFilePath, lastModifiedTimeCatalogLocale ); //File.SetLastWriteTime( listFilePath, lastModifiedTimeCatalogLocale ); } catch (Exception e) { Program.LogException(e); } Directory.GetFiles(cachePath, "*.xml").ForEach(File.Delete); foreach (string file in Directory.GetFiles(cachePath, "*.msha")) { string fileName = Path.GetFileName(file); if (!string.IsNullOrEmpty(fileName)) { if (!fileName.Contains(@"HelpContentSetup")) { File.Delete(file); } if (fileName == @"(" + codeLocale + @")HelpContentSetup") //if ( fileName == @"HelpContentSetup(" + codeLocale + @")" ) { File.Delete(file); //break; } } } foreach (string file in Directory.GetFiles(vsDirectory, "*.msha")) { string fileName = Path.GetFileName(file); if (!string.IsNullOrEmpty(fileName)) { if (!fileName.Contains(@"HelpContentSetup")) { File.Delete(file); } if (fileName == @"(" + codeLocale + @")HelpContentSetup") { File.Delete(file); //break; } } } // Creating setup indexes //File.WriteAllText( //Path.Combine( cachePath, "HelpContentSetup.msha" ), HelpIndexManager.CreateSetupIndex( bookGroups, nameCatalog, catalogLocale ), Encoding.UTF8 ); string xmlname = Path.Combine(vsDirectory, objLocale.CreateFileName()); File.WriteAllText(xmlname, objCatalog.Name == "dev10" ? HelpIndexManager.CreateSetupIndex10(bookGroups, objCatalog, objLocale, vsDirectory) : HelpIndexManager.CreateSetupIndex(bookGroups, objCatalog, objLocale), Encoding.UTF8); FileLastModifiedTime(xmlname, lastModifiedTimeCatalogLocale); //File.SetCreationTime( xmlname, lastModifiedTimeCatalogLocale ); //File.SetLastAccessTime( xmlname, lastModifiedTimeCatalogLocale ); //File.SetLastWriteTime( xmlname, lastModifiedTimeCatalogLocale ); string packagesDirectory = Path.Combine(vsDirectory, "packages"); string packagesDirectoryLocale = Path.Combine(packagesDirectory, codeLocale.ToLowerInvariant()); string packagesDirectoryEnUs = Path.Combine(packagesDirectory, "en-us"); // Cleanup old files //Directory.GetFiles( packagesDirectory, "*.cab" ).ForEach( File.Delete ); CleanupOldPackages(packages, null, cachePath, false); string oldVsDirName = objCatalog.Name; if (oldVsDirName == "dev10") { oldVsDirName = "VisualStudio10"; } string oldvsDirectory = Path.Combine(cachePath, oldVsDirName); if (oldvsDirectory != vsDirectory) { string oldpackagesDirectory = Path.Combine(oldvsDirectory, @"packages"); string oldpackagesDirectoryLocale = Path.Combine(oldpackagesDirectory, codeLocale.ToLowerInvariant()); string oldpackagesDirectoryEnUs = Path.Combine(oldpackagesDirectory, "en-us"); CleanupOldPackages(packages, null, oldvsDirectory, false); CleanupOldPackages(packages, null, oldpackagesDirectory, false); CleanupOldPackages(packages, codeLocale, oldpackagesDirectoryLocale, false); if (!codeLocale.ToLowerInvariant().Contains(@"en-us") && includeEnUs) { CleanupOldPackages(packages, @"en-us", oldpackagesDirectoryEnUs, false); } } CleanupOldPackages(packages, null, Path.Combine(cachePath, @"packages"), false); CleanupOldPackages(packages, null, Path.Combine(cachePath, @"packages", codeLocale.ToLowerInvariant()), false); if (!codeLocale.ToLowerInvariant().Contains(@"en-us") && includeEnUs) { CleanupOldPackages(packages, null, Path.Combine(cachePath, @"packages", @"en-us"), false); } CleanupOldPackages(packages, null, vsDirectory, false); CleanupOldPackages(packages, null, packagesDirectory, false); CleanupOldPackages(packages, codeLocale, packagesDirectoryLocale, true); if (!codeLocale.ToLowerInvariant().Contains(@"en-us") && includeEnUs) { CleanupOldPackages(packages, @"en-us", packagesDirectoryEnUs, true); } // Create cachePath if (!Directory.Exists(packagesDirectory)) { Directory.CreateDirectory(packagesDirectory); } if (!Directory.Exists(packagesDirectoryLocale)) { Directory.CreateDirectory(packagesDirectoryLocale); } if (includeEnUs && !Directory.Exists(packagesDirectoryEnUs)) { Directory.CreateDirectory(packagesDirectoryEnUs); } // Download the packages DateTime lastModifiedDirLoc = new DateTime(2000, 1, 1, 0, 0, 0); DateTime lastModifiedDirEnUs = new DateTime(2000, 1, 1, 0, 0, 0); int packagesCountCurrent = 0; foreach (Package package in packages.Values) { string destDirectory; if (package.Name.ToLowerInvariant().Contains(codeLocale.ToLowerInvariant())) { destDirectory = packagesDirectoryLocale; if (package.LastModified > lastModifiedDirLoc) { lastModifiedDirLoc = package.LastModified; } } else if (package.Name.ToLowerInvariant().Contains(@"en-us")) { destDirectory = packagesDirectoryEnUs; if (package.LastModified > lastModifiedDirEnUs) { lastModifiedDirEnUs = package.LastModified; } } else { destDirectory = packagesDirectory; } string targetFileName = Path.Combine(destDirectory, package.CreateFileName()); // If file exist and file length is the same, skip it if (package.State != PackageState.NotDownloaded) //if ( package.State == PackageState.OutOfDate ) { if (File.Exists(targetFileName)) { FileInfo curFileInfo = new FileInfo(targetFileName); //if (package.State == PackageState.OutOfDate) if (package.LastModified != curFileInfo.LastWriteTime) { package.LastModified = FetchLastModified(package.CurrentLink); } if (package.LastModified != curFileInfo.LastWriteTime) { //File.Delete(targetFileName); package.State = PackageState.OutOfDate; } if (package.PackageSizeBytes != curFileInfo.Length) { package.PackageSizeBytes = FetchContentLength(package.CurrentLink); } if (package.PackageSizeBytes != curFileInfo.Length || !AuthenticodeTools.IsTrusted(targetFileName)) { File.Delete(targetFileName); package.State = PackageState.NotDownloaded; } } else { package.LastModified = FetchLastModified(package.CurrentLink); package.State = PackageState.NotDownloaded; } } else if (package.State == PackageState.NotDownloaded) { package.LastModified = FetchLastModified(package.CurrentLink); } if (package.State == PackageState.NotDownloaded /*|| package.State == PackageState.OutOfDate*/) { //Debug.Print(" Downloading : '{0}' to '{1}'", package.CurrentLink, targetFileName); _client.DownloadFile(package.CurrentLink, targetFileName); if (!AuthenticodeTools.IsTrusted(targetFileName)) { //Debug.Print("The signature on '{0}' is not valid - deleting"); File.Delete(targetFileName); package.State = PackageState.NotDownloaded; throw new InvalidDataException($"The signature on '{targetFileName}' is not valid - deleting"); } } FileLastModifiedTime(targetFileName, package.LastModified); //File.SetCreationTime( targetFileName, package.LastModified ); //File.SetLastAccessTime( targetFileName, package.LastModified ); //File.SetLastWriteTime( targetFileName, package.LastModified ); package.State = PackageState.Ready; progress.Report(100 * ++packagesCountCurrent / packages.Count); } FileLastModifiedTime(packagesDirectoryLocale, lastModifiedDirLoc, true); if (!codeLocale.ToLowerInvariant().Contains(@"en-us") && includeEnUs) { FileLastModifiedTime(packagesDirectoryEnUs, lastModifiedDirEnUs, true); } FileLastModifiedTime(packagesDirectory, lastModifiedTimeCatalogLocale, true); FileLastModifiedTime(vsDirectory, lastModifiedTimeCatalogLocale, true); FileLastModifiedTime(cachePath, lastModifiedTimeCatalogLocale, true); }
/// <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 <CatalogLocale> LoadAvailableLocales(Catalog nameCatalog) { if (nameCatalog == null) { throw new ArgumentNullException(nameof(nameCatalog)); } var result = string.IsNullOrEmpty(nameCatalog.CatalogLink) ? new List <CatalogLocale>() : HelpIndexManager.LoadLocales(_client.DownloadData(nameCatalog.CatalogLink)); //List<CatalogLocale> result = new List<CatalogLocale>(); string[] names = { "cs-cz", "de-de", "en-us", "es-es", "fr-fr", "it-it", "ja-jp", "ko-kr", "pl-pl", "pt-br", "ru-ru", "tr-tr", "zh-cn", "zh-tw" }; //if (result.Count < names.Length) { //result.Clear(); foreach (string name in names) { CatalogLocale cataloglocale = new CatalogLocale { Locale = name, CatalogName = nameCatalog.Name, Description = nameCatalog.Name, LocaleLink = (!string.IsNullOrEmpty(nameCatalog.CatalogLink) ? (nameCatalog.CatalogLink + @"/" + name) : (@"../catalogs/" + nameCatalog.Name + @"/" + name)) }; if (!result.Contains(cataloglocale)) { result.Add(cataloglocale); } } } var catalogLocales = result as List <CatalogLocale>; catalogLocales?.Sort(); return(result); }