public override TimeSpan Analyze(ClientContext cc) { try { base.Analyze(cc); // Only scan when it's a valid publishing portal var pageCount = ContinueScanning(cc); if (pageCount > 0 || pageCount == -1) { try { PublishingWebScanResult scanResult = new PublishingWebScanResult() { SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, WebRelativeUrl = this.SiteUrl.Replace(this.SiteCollectionUrl, ""), WebTemplate = this.webScanResult.WebTemplate, BrokenPermissionInheritance = this.webScanResult.BrokenPermissionInheritance, PageCount = pageCount == -1 ? 0 : pageCount, SiteMasterPage = this.webScanResult.CustomMasterPage, SystemMasterPage = this.webScanResult.MasterPage, AlternateCSS = this.webScanResult.AlternateCSS, Admins = this.siteScanResult.Admins, Owners = this.webScanResult.Owners, UserCustomActions = new List <UserCustomActionResult>() }; // User custom actions will play a role in complexity calculation if (this.siteScanResult.SiteUserCustomActions != null && this.siteScanResult.SiteUserCustomActions.Count > 0) { scanResult.UserCustomActions.AddRange(this.siteScanResult.SiteUserCustomActions); } if (this.webScanResult.WebUserCustomActions != null && this.webScanResult.WebUserCustomActions.Count > 0) { scanResult.UserCustomActions.AddRange(this.webScanResult.WebUserCustomActions); } Web web = cc.Web; // Load additional web properties web.EnsureProperties(p => p.Language); scanResult.Language = web.Language; // PageLayouts handling var availablePageLayouts = web.GetPropertyBagValueString(AvailablePageLayouts, ""); var defaultPageLayout = web.GetPropertyBagValueString(DefaultPageLayout, ""); if (string.IsNullOrEmpty(availablePageLayouts)) { scanResult.PageLayoutsConfiguration = "Any"; } else if (availablePageLayouts.Equals("__inherit", StringComparison.InvariantCultureIgnoreCase)) { scanResult.PageLayoutsConfiguration = "Inherit from parent"; } else { scanResult.PageLayoutsConfiguration = "Defined list"; // Fill the defined list var element = XElement.Parse(availablePageLayouts); var nodes = element.Descendants("layout"); if (nodes != null && nodes.Count() > 0) { string allowedPageLayouts = ""; foreach (var node in nodes) { allowedPageLayouts = allowedPageLayouts + node.Attribute("url").Value.Replace("_catalogs/masterpage/", "") + ","; } allowedPageLayouts = allowedPageLayouts.TrimEnd(new char[] { ',' }); scanResult.AllowedPageLayouts = allowedPageLayouts; } } if (!string.IsNullOrEmpty(defaultPageLayout)) { var element = XElement.Parse(defaultPageLayout); scanResult.DefaultPageLayout = element.Attribute("url").Value.Replace("_catalogs/masterpage/", ""); } // Navigation var navigationSettings = web.GetNavigationSettings(); if (navigationSettings != null) { if (navigationSettings.GlobalNavigation.ManagedNavigation) { scanResult.GlobalNavigationType = "Managed"; } else { scanResult.GlobalNavigationType = "Structural"; scanResult.GlobalStructuralNavigationMaxCount = navigationSettings.GlobalNavigation.MaxDynamicItems; scanResult.GlobalStructuralNavigationShowPages = navigationSettings.GlobalNavigation.ShowPages; scanResult.GlobalStructuralNavigationShowSiblings = navigationSettings.GlobalNavigation.ShowSiblings; scanResult.GlobalStructuralNavigationShowSubSites = navigationSettings.GlobalNavigation.ShowSubsites; } if (navigationSettings.CurrentNavigation.ManagedNavigation) { scanResult.CurrentNavigationType = "Managed"; } else { scanResult.CurrentNavigationType = "Structural"; scanResult.CurrentStructuralNavigationMaxCount = navigationSettings.CurrentNavigation.MaxDynamicItems; scanResult.CurrentStructuralNavigationShowPages = navigationSettings.CurrentNavigation.ShowPages; scanResult.CurrentStructuralNavigationShowSiblings = navigationSettings.CurrentNavigation.ShowSiblings; scanResult.CurrentStructuralNavigationShowSubSites = navigationSettings.CurrentNavigation.ShowSubsites; } if (navigationSettings.GlobalNavigation.ManagedNavigation || navigationSettings.CurrentNavigation.ManagedNavigation) { scanResult.ManagedNavigationAddNewPages = navigationSettings.AddNewPagesToNavigation; scanResult.ManagedNavigationCreateFriendlyUrls = navigationSettings.CreateFriendlyUrlsForNewPages; // get information about the managed nav term set configuration var managedNavXml = web.GetPropertyBagValueString(WebNavigationSettings, ""); if (!string.IsNullOrEmpty(managedNavXml)) { var managedNavSettings = XElement.Parse(managedNavXml); IEnumerable <XElement> navNodes = managedNavSettings.XPathSelectElements("./SiteMapProviderSettings/TaxonomySiteMapProviderSettings"); foreach (var node in navNodes) { if (node.Attribute("Name").Value.Equals("CurrentNavigationTaxonomyProvider", StringComparison.InvariantCulture)) { if (node.Attribute("TermSetId") != null) { scanResult.CurrentManagedNavigationTermSetId = node.Attribute("TermSetId").Value; } else if (node.Attribute("UseParentSiteMap") != null) { scanResult.CurrentManagedNavigationTermSetId = "Inherit from parent"; } } else if (node.Attribute("Name").Value.Equals("GlobalNavigationTaxonomyProvider", StringComparison.InvariantCulture)) { if (node.Attribute("TermSetId") != null) { scanResult.GlobalManagedNavigationTermSetId = node.Attribute("TermSetId").Value; } else if (node.Attribute("UseParentSiteMap") != null) { scanResult.GlobalManagedNavigationTermSetId = "Inherit from parent"; } } } } } } // Pages library var pagesLibrary = web.GetListsToScan().Where(p => p.BaseTemplate == 850).FirstOrDefault(); if (pagesLibrary != null) { pagesLibrary.EnsureProperties(p => p.EnableModeration, p => p.EnableVersioning, p => p.EnableMinorVersions, p => p.EventReceivers, p => p.Fields, p => p.DefaultContentApprovalWorkflowId); scanResult.LibraryEnableModeration = pagesLibrary.EnableModeration; scanResult.LibraryEnableVersioning = pagesLibrary.EnableVersioning; scanResult.LibraryEnableMinorVersions = pagesLibrary.EnableMinorVersions; scanResult.LibraryItemScheduling = pagesLibrary.ItemSchedulingEnabled(); scanResult.LibraryApprovalWorkflowDefined = pagesLibrary.DefaultContentApprovalWorkflowId != Guid.Empty; } // Variations if (scanResult.Level == 0) { var variationLabels = cc.GetVariationLabels(); string labels = ""; string sourceLabel = ""; foreach (var label in variationLabels) { labels = labels + $"{label.Title} ({label.Language}),"; if (label.IsSource) { sourceLabel = label.Title; } } scanResult.VariationLabels = labels.TrimEnd(new char[] { ',' });; scanResult.VariationSourceLabel = sourceLabel; } // Scan pages inside the pages library if (pagesLibrary != null && Options.IncludePublishingWithPages(this.ScanJob.Mode)) { CamlQuery query = new CamlQuery { ViewXml = CAMLQueryByExtension, }; var pages = pagesLibrary.GetItems(query); // Load additional page related information IEnumerable <ListItem> enumerable = web.Context.LoadQuery(pages.IncludeWithDefaultProperties((ListItem item) => item.ContentType)); web.Context.ExecuteQueryRetry(); if (enumerable.FirstOrDefault() != null) { foreach (var page in enumerable) { string pageUrl = null; try { if (page.FieldValues.ContainsKey(FileRefField) && !String.IsNullOrEmpty(page[FileRefField].ToString())) { pageUrl = page[FileRefField].ToString(); } else { //skip page continue; } // Basic information about the page PublishingPageScanResult pageScanResult = new PublishingPageScanResult() { SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, WebRelativeUrl = scanResult.WebRelativeUrl, PageRelativeUrl = scanResult.WebRelativeUrl.Length > 0 ? pageUrl.Replace(scanResult.WebRelativeUrl, "") : pageUrl, }; // Page name if (page.FieldValues.ContainsKey(FileLeafRefField) && !String.IsNullOrEmpty(page[FileLeafRefField].ToString())) { pageScanResult.PageName = page[FileLeafRefField].ToString(); } // Get page change information pageScanResult.ModifiedAt = page.LastModifiedDateTime(); if (!this.ScanJob.SkipUserInformation) { pageScanResult.ModifiedBy = page.LastModifiedBy(); } // Page layout pageScanResult.PageLayout = page.PageLayout(); pageScanResult.PageLayoutFile = page.PageLayoutFile().Replace(pageScanResult.SiteColUrl, "").Replace("/_catalogs/masterpage/", ""); // Customization status if (this.MasterPageGalleryCustomization == null) { this.MasterPageGalleryCustomization = new Dictionary <string, CustomizedPageStatus>(); } // Load the file to check the customization status, only do this if the file was not loaded before for this site collection Uri uri = new Uri(page.PageLayoutFile()); var url = page.PageLayoutFile().Replace($"{uri.Scheme}://{uri.DnsSafeHost}".ToLower(), ""); if (!this.MasterPageGalleryCustomization.ContainsKey(url)) { try { var publishingPageLayout = cc.Site.RootWeb.GetFileByServerRelativeUrl(url); cc.Load(publishingPageLayout); cc.ExecuteQueryRetry(); this.MasterPageGalleryCustomization.Add(url, publishingPageLayout.CustomizedPageStatus); } catch (Exception ex) { // eat potential exceptions } } // store the page layout customization status if (this.MasterPageGalleryCustomization.TryGetValue(url, out CustomizedPageStatus pageStatus)) { if (pageStatus == CustomizedPageStatus.Uncustomized) { pageScanResult.PageLayoutWasCustomized = false; } else { pageScanResult.PageLayoutWasCustomized = true; } } else { // If the file was not loaded for some reason then assume it was customized pageScanResult.PageLayoutWasCustomized = true; } // Page audiences var audiences = page.Audiences(); if (audiences != null) { pageScanResult.GlobalAudiences = audiences.GlobalAudiences; pageScanResult.SecurityGroupAudiences = audiences.SecurityGroups; pageScanResult.SharePointGroupAudiences = audiences.SharePointGroups; } // Contenttype pageScanResult.ContentType = page.ContentType.Name; pageScanResult.ContentTypeId = page.ContentType.Id.StringValue; // Get page web parts var pageAnalysis = page.WebParts(this.ScanJob.PageTransformation); if (pageAnalysis != null) { pageScanResult.WebParts = pageAnalysis.Item2; } // Persist publishing page scan results if (!this.ScanJob.PublishingPageScanResults.TryAdd(pageUrl, pageScanResult)) { ScanError error = new ScanError() { Error = $"Could not add publishing page scan result for {pageScanResult.PageRelativeUrl}", SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, Field1 = "PublishingAnalyzer", Field2 = pageScanResult.PageRelativeUrl, }; this.ScanJob.ScanErrors.Push(error); } } catch (Exception ex) { ScanError error = new ScanError() { Error = ex.Message, SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, Field1 = "MainPublishingPageAnalyzerLoop", Field2 = ex.StackTrace, Field3 = pageUrl }; this.ScanJob.ScanErrors.Push(error); Console.WriteLine("Error for page {1}: {0}", ex.Message, pageUrl); } } } } // Persist publishing scan results if (!this.ScanJob.PublishingWebScanResults.TryAdd(this.SiteUrl, scanResult)) { ScanError error = new ScanError() { Error = $"Could not add publishing scan result for {this.SiteUrl}", SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, Field1 = "PublishingAnalyzer", }; this.ScanJob.ScanErrors.Push(error); } } catch (Exception ex) { ScanError error = new ScanError() { Error = ex.Message, SiteColUrl = this.SiteCollectionUrl, SiteURL = this.SiteUrl, Field1 = "MainPublishingAnalyzerLoop", Field2 = ex.StackTrace, }; this.ScanJob.ScanErrors.Push(error); Console.WriteLine("Error for web {1}: {0}", ex.Message, this.SiteUrl); } } } finally { this.StopTime = DateTime.Now; } // return the duration of this scan return(new TimeSpan((this.StopTime.Subtract(this.StartTime).Ticks))); }
/// <summary> /// Override of the scanner execute method, needed to output our results /// </summary> /// <returns>Time when scanning was started</returns> public override DateTime Execute() { // Triggers the run of the scanning...will result in ModernizationScanJob_TimerJobRun being called per site collection var start = base.Execute(); // Handle the export of the job specific scanning data string outputfile = string.Format("{0}\\ModernizationSiteScanResults.csv", this.OutputFolder); string[] outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "ReadyForGroupify", "GroupifyBlockers", "GroupifyWarnings", "GroupMode", "PermissionWarnings", "ModernHomePage", "ModernUIWarnings", "WebTemplate", "Office365GroupId", "MasterPage", "AlternateCSS", "UserCustomActions", "SubSites", "SubSitesWithBrokenPermissionInheritance", "ModernPageWebFeatureDisabled", "ModernPageFeatureWasEnabledBySPO", "ModernListSiteBlockingFeatureEnabled", "ModernListWebBlockingFeatureEnabled", "SitePublishingFeatureEnabled", "WebPublishingFeatureEnabled", "ViewsRecent", "ViewsRecentUniqueUsers", "ViewsLifeTime", "ViewsLifeTimeUniqueUsers", "Everyone(ExceptExternalUsers)Claim", "UsesADGroups", "ExternalSharing", "Admins", "AdminContainsEveryone(ExceptExternalUsers)Claim", "AdminContainsADGroups", "Owners", "OwnersContainsEveryone(ExceptExternalUsers)Claim", "OwnersContainsADGroups", "Members", "MembersContainsEveryone(ExceptExternalUsers)Claim", "MembersContainsADGroups", "Visitors", "VisitorsContainsEveryone(ExceptExternalUsers)Claim", "VisitorsContainsADGroups" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); foreach (var item in this.SiteScanResults) { var groupifyBlockers = item.Value.GroupifyBlockers(); var groupifyWarnings = item.Value.GroupifyWarnings(this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim); var modernWarnings = item.Value.ModernWarnings(); var groupSecurity = item.Value.PermissionModel(this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim); outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), (groupifyBlockers.Count > 0 ? "FALSE" : "TRUE"), ToCsv(SiteScanResult.FormatList(groupifyBlockers)), ToCsv(SiteScanResult.FormatList(groupifyWarnings)), ToCsv(groupSecurity.Item1), ToCsv(SiteScanResult.FormatList(groupSecurity.Item2)), item.Value.ModernHomePage, ToCsv(SiteScanResult.FormatList(modernWarnings)), ToCsv(item.Value.WebTemplate), ToCsv(item.Value.Office365GroupId != Guid.Empty ? item.Value.Office365GroupId.ToString() : ""), item.Value.MasterPage, item.Value.AlternateCSS, ((item.Value.SiteUserCustomActions != null && item.Value.SiteUserCustomActions.Count > 0) || (item.Value.WebUserCustomActions != null && item.Value.WebUserCustomActions.Count > 0)), item.Value.SubSites, item.Value.SubSitesWithBrokenPermissionInheritance, item.Value.ModernPageWebFeatureDisabled, item.Value.ModernPageFeatureWasEnabledBySPO, item.Value.ModernListSiteBlockingFeatureEnabled, item.Value.ModernListWebBlockingFeatureEnabled, item.Value.SitePublishingFeatureEnabled, item.Value.WebPublishingFeatureEnabled, (SkipUsageInformation ? 0: item.Value.ViewsRecent), (SkipUsageInformation ? 0 : item.Value.ViewsRecentUniqueUsers), (SkipUsageInformation ? 0 : item.Value.ViewsLifeTime), (SkipUsageInformation ? 0 : item.Value.ViewsLifeTimeUniqueUsers), item.Value.EveryoneClaimsGranted, item.Value.ContainsADGroup(), ToCsv(item.Value.SharingCapabilities), ToCsv(SiteScanResult.FormatUserList(item.Value.Admins, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), item.Value.HasClaim(item.Value.Admins, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim), item.Value.ContainsADGroup(item.Value.Admins), ToCsv(SiteScanResult.FormatUserList(item.Value.Owners, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), item.Value.HasClaim(item.Value.Owners, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim), item.Value.ContainsADGroup(item.Value.Owners), ToCsv(SiteScanResult.FormatUserList(item.Value.Members, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), item.Value.HasClaim(item.Value.Members, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim), item.Value.ContainsADGroup(item.Value.Members), ToCsv(SiteScanResult.FormatUserList(item.Value.Visitors, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), item.Value.HasClaim(item.Value.Visitors, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim), item.Value.ContainsADGroup(item.Value.Visitors) ))); } } outputfile = string.Format("{0}\\ModernizationWebScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "WebTemplate", "BrokenPermissionInheritance", "ModernPageWebFeatureDisabled", "ModernPageFeatureWasEnabledBySPO", "WebPublishingFeatureEnabled", "MasterPage", "CustomMasterPage", "AlternateCSS", "UserCustomActions", "Everyone(ExceptExternalUsers)Claim", "UniqueOwners", "UniqueMembers", "UniqueVisitors" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); foreach (var item in this.WebScanResults) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(item.Value.WebTemplate), item.Value.BrokenPermissionInheritance, item.Value.ModernPageWebFeatureDisabled, item.Value.ModernPageFeatureWasEnabledBySPO, item.Value.WebPublishingFeatureEnabled, ToCsv(item.Value.MasterPage), ToCsv(item.Value.CustomMasterPage), ToCsv(item.Value.AlternateCSS), (item.Value.WebUserCustomActions.Count > 0), item.Value.EveryoneClaimsGranted, ToCsv(SiteScanResult.FormatUserList(item.Value.Owners, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), ToCsv(SiteScanResult.FormatUserList(item.Value.Members, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), ToCsv(SiteScanResult.FormatUserList(item.Value.Visitors, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)) ))); } } outputfile = string.Format("{0}\\ModernizationUserCustomActionScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "Title", "Name", "Location", "RegistrationType", "RegistrationId", "Reason", "CommandAction", "ScriptBlock", "ScriptSrc" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); foreach (var item in this.SiteScanResults) { if (item.Value.SiteUserCustomActions == null || item.Value.SiteUserCustomActions.Count == 0) { continue; } foreach (var uca in item.Value.SiteUserCustomActions) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(uca.Title), ToCsv(uca.Name), ToCsv(uca.Location), uca.RegistrationType, ToCsv(uca.RegistrationId), ToCsv(uca.Problem), ToCsv(uca.CommandAction), ToCsv(uca.ScriptBlock), ToCsv(uca.ScriptSrc) ))); } } foreach (var item in this.WebScanResults) { if (item.Value.WebUserCustomActions == null || item.Value.WebUserCustomActions.Count == 0) { continue; } foreach (var uca in item.Value.WebUserCustomActions) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(uca.Title), ToCsv(uca.Name), ToCsv(uca.Location), uca.RegistrationType, ToCsv(uca.RegistrationId), ToCsv(uca.Problem), ToCsv(uca.CommandAction), ToCsv(uca.ScriptBlock), ToCsv(uca.ScriptSrc) ))); } } } if (Options.IncludeLists(this.Mode)) { outputfile = string.Format("{0}\\ModernizationListScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "Url", "Site Url", "Site Collection Url", "List Title", "Only blocked by OOB reasons", "Blocked at site level", "Blocked at web level", "Blocked at list level", "List page render type", "List experience", "Blocked by not being able to load Page", "Blocked by not being able to load page exception", "Blocked by managed metadata navigation", "Blocked by view type", "View type", "Blocked by list base template", "List base template", "Blocked by zero or multiple web parts", "Blocked by JSLink", "JSLink", "Blocked by XslLink", "XslLink", "Blocked by Xsl", "Blocked by JSLink field", "JSLink fields", "Blocked by business data field", "Business data fields", "Blocked by task outcome field", "Task outcome fields", "Blocked by publishingField", "Publishing fields", "Blocked by geo location field", "Geo location fields", "Blocked by list custom action", "List custom actions" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); foreach (var list in this.ListScanResults) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(list.Key.Substring(36)), ToCsv(list.Value.SiteURL), ToCsv(list.Value.SiteColUrl), ToCsv(list.Value.ListTitle), list.Value.OnlyBlockedByOOBReasons, list.Value.BlockedAtSiteLevel, list.Value.BlockedAtWebLevel, list.Value.BlockedAtListLevel, list.Value.PageRenderType, list.Value.ListExperience, list.Value.BlockedByNotBeingAbleToLoadPage, ToCsv(list.Value.BlockedByNotBeingAbleToLoadPageException), list.Value.XsltViewWebPartCompatibility.BlockedByManagedMetadataNavFeature, list.Value.XsltViewWebPartCompatibility.BlockedByViewType, ToCsv(list.Value.XsltViewWebPartCompatibility.ViewType), list.Value.XsltViewWebPartCompatibility.BlockedByListBaseTemplate, list.Value.XsltViewWebPartCompatibility.ListBaseTemplate, list.Value.BlockedByZeroOrMultipleWebParts, list.Value.XsltViewWebPartCompatibility.BlockedByJSLink, ToCsv(list.Value.XsltViewWebPartCompatibility.JSLink), list.Value.XsltViewWebPartCompatibility.BlockedByXslLink, ToCsv(list.Value.XsltViewWebPartCompatibility.XslLink), list.Value.XsltViewWebPartCompatibility.BlockedByXsl, list.Value.XsltViewWebPartCompatibility.BlockedByJSLinkField, ToCsv(list.Value.XsltViewWebPartCompatibility.JSLinkFields), list.Value.XsltViewWebPartCompatibility.BlockedByBusinessDataField, ToCsv(list.Value.XsltViewWebPartCompatibility.BusinessDataFields), list.Value.XsltViewWebPartCompatibility.BlockedByTaskOutcomeField, ToCsv(list.Value.XsltViewWebPartCompatibility.TaskOutcomeFields), list.Value.XsltViewWebPartCompatibility.BlockedByPublishingField, ToCsv(list.Value.XsltViewWebPartCompatibility.PublishingFields), list.Value.XsltViewWebPartCompatibility.BlockedByGeoLocationField, ToCsv(list.Value.XsltViewWebPartCompatibility.GeoLocationFields), list.Value.XsltViewWebPartCompatibility.BlockedByListCustomAction, ToCsv(list.Value.XsltViewWebPartCompatibility.ListCustomActions) ))); } } } if (Options.IncludePage(this.Mode)) { outputfile = string.Format("{0}\\PageScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "PageUrl", "Library", "HomePage", "Type", "Layout", "Mapping %", "Unmapped web parts", "ModifiedBy", "ModifiedAt", "ViewsRecent", "ViewsRecentUniqueUsers", "ViewsLifeTime", "ViewsLifeTimeUniqueUsers" }; Console.WriteLine("Outputting scan results to {0}", outputfile); string header1 = string.Join(this.Separator, outputHeaders); string header2 = ""; for (int i = 1; i <= 30; i++) { if (ExportWebPartProperties) { header2 = header2 + $"{this.Separator}WPType{i}{this.Separator}WPTitle{i}{this.Separator}WPData{i}"; } else { header2 = header2 + $"{this.Separator}WPType{i}{this.Separator}WPTitle{i}"; } } List <string> UniqueWebParts = new List <string>(); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", header1 + header2)); foreach (var item in this.PageScanResults) { var part1 = string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(item.Value.PageUrl), ToCsv(item.Value.Library), item.Value.HomePage, ToCsv(item.Value.PageType), ToCsv(item.Value.Layout), "{MappingPercentage}", "{UnmappedWebParts}", ToCsv(item.Value.ModifiedBy), item.Value.ModifiedAt, (SkipUsageInformation ? 0 : item.Value.ViewsRecent), (SkipUsageInformation ? 0 : item.Value.ViewsRecentUniqueUsers), (SkipUsageInformation ? 0 : item.Value.ViewsLifeTime), (SkipUsageInformation ? 0 : item.Value.ViewsLifeTimeUniqueUsers)); string part2 = ""; if (item.Value.WebParts != null) { int webPartsOnPage = item.Value.WebParts.Count(); int webPartsOnPageMapped = 0; List <string> nonMappedWebParts = new List <string>(); foreach (var webPart in item.Value.WebParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { var found = this.PageTransformation.WebParts.Where(p => p.Type.Equals(webPart.Type, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (found != null && found.Mappings != null) { webPartsOnPageMapped++; } else { var t = webPart.Type.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0]; if (!nonMappedWebParts.Contains(t)) { nonMappedWebParts.Add(t); } } if (ExportWebPartProperties) { part2 = part2 + $"{this.Separator}{ToCsv(webPart.TypeShort())}{this.Separator}{ToCsv(webPart.Title)}{this.Separator}{ToCsv(webPart.Json())}"; } else { part2 = part2 + $"{this.Separator}{ToCsv(webPart.TypeShort())}{this.Separator}{ToCsv(webPart.Title)}"; } if (!UniqueWebParts.Contains(webPart.Type)) { UniqueWebParts.Add(webPart.Type); } } part1 = part1.Replace("{MappingPercentage}", webPartsOnPage == 0 ? "100" : String.Format("{0:0}", (((double)webPartsOnPageMapped / (double)webPartsOnPage) * 100))).Replace("{UnmappedWebParts}", SiteScanResult.FormatList(nonMappedWebParts)); } else { part1 = part1.Replace("{MappingPercentage}", "").Replace("{UnmappedWebParts}", ""); } outfile.Write(string.Format("{0}\r\n", part1 + (!string.IsNullOrEmpty(part2) ? part2 : ""))); } } outputfile = string.Format("{0}\\UniqueWebParts.csv", this.OutputFolder); Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", $"Type{this.Separator}InMappingFile")); foreach (var type in UniqueWebParts) { var found = this.PageTransformation.WebParts.Where(p => p.Type.Equals(type, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); outfile.Write(string.Format("{0}\r\n", $"{ToCsv(type)}{this.Separator}{found != null}")); } } } if (Options.IncludePublishing(this.Mode)) { // "Calculate" publishing site results based upon the web/page level data we retrieved this.PublishingSiteScanResults = PublishingAnalyzer.GeneratePublishingSiteResults(this.Mode, this.PublishingWebScanResults, this.PublishingPageScanResults); // Export the site publishing data outputfile = string.Format("{0}\\ModernizationPublishingSiteScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "NumberOfWebs", "NumberOfPages", "UsedSiteMasterPages", "UsedSystemMasterPages", "UsedPageLayouts", "LastPageUpdateDate" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); if (PublishingSiteScanResults != null) { foreach (var item in this.PublishingSiteScanResults) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), item.Value.NumberOfWebs, item.Value.NumberOfPages, ToCsv(PublishingPageScanResult.FormatList(item.Value.UsedSiteMasterPages)), ToCsv(PublishingPageScanResult.FormatList(item.Value.UsedSystemMasterPages)), ToCsv(PublishingPageScanResult.FormatList(item.Value.UsedPageLayouts)), item.Value.LastPageUpdateDate.HasValue ? item.Value.LastPageUpdateDate.ToString() : "" ))); } } } // Export the web publishing data outputfile = string.Format("{0}\\ModernizationPublishingWebScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "WebRelativeUrl", "WebTemplate", "Level", "PageCount", "Language", "VariationLabels", "VariationSourceLabel", "SiteMasterPage", "SystemMasterPage", "AlternateCSS", "AllowedPageLayouts", "PageLayoutsConfiguration", "DefaultPageLayout", "GlobalNavigationType", "GlobalStructuralNavigationShowSubSites", "GlobalStructuralNavigationShowPages", "GlobalStructuralNavigationShowSiblings", "GlobalStructuralNavigationMaxCount", "GlobalManagedNavigationTermSetId", "CurrentNavigationType", "CurrentStructuralNavigationShowSubSites", "CurrentStructuralNavigationShowPages", "CurrentStructuralNavigationShowSiblings", "CurrentStructuralNavigationMaxCount", "CurrentManagedNavigationTermSetId", "ManagedNavigationAddNewPages", "ManagedNavigationCreateFriendlyUrls", "LibraryItemScheduling", "LibraryEnableModeration", "LibraryEnableVersioning", "LibraryEnableMinorVersions", "LibraryApprovalWorkflowDefined", "BrokenPermissionInheritance", "Admins", "Owners" }; Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, outputHeaders))); foreach (var item in this.PublishingWebScanResults) { outfile.Write(string.Format("{0}\r\n", string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(item.Value.WebRelativeUrl), ToCsv(item.Value.WebTemplate), item.Value.Level.ToString(), item.Value.PageCount.ToString(), item.Value.Language.ToString(), ToCsv(item.Value.VariationLabels), ToCsv(item.Value.VariationSourceLabel), ToCsv(item.Value.SiteMasterPage), ToCsv(item.Value.SystemMasterPage), ToCsv(item.Value.AlternateCSS), ToCsv(item.Value.AllowedPageLayouts), ToCsv(item.Value.PageLayoutsConfiguration), ToCsv(item.Value.DefaultPageLayout), ToCsv(item.Value.GlobalNavigationType), item.Value.GlobalStructuralNavigationShowSubSites.HasValue ? item.Value.GlobalStructuralNavigationShowSubSites.Value.ToString() : "", item.Value.GlobalStructuralNavigationShowPages.HasValue ? item.Value.GlobalStructuralNavigationShowPages.Value.ToString() : "", item.Value.GlobalStructuralNavigationShowSiblings.HasValue ? item.Value.GlobalStructuralNavigationShowSiblings.Value.ToString() : "", item.Value.GlobalStructuralNavigationMaxCount.HasValue ? item.Value.GlobalStructuralNavigationMaxCount.Value.ToString() : "", ToCsv(item.Value.GlobalManagedNavigationTermSetId), ToCsv(item.Value.CurrentNavigationType), item.Value.CurrentStructuralNavigationShowSubSites.HasValue ? item.Value.CurrentStructuralNavigationShowSubSites.Value.ToString() : "", item.Value.CurrentStructuralNavigationShowPages.HasValue ? item.Value.CurrentStructuralNavigationShowPages.Value.ToString() : "", item.Value.CurrentStructuralNavigationShowSiblings.HasValue ? item.Value.CurrentStructuralNavigationShowSiblings.Value.ToString() : "", item.Value.CurrentStructuralNavigationMaxCount.HasValue ? item.Value.CurrentStructuralNavigationMaxCount.Value.ToString() : "", ToCsv(item.Value.CurrentManagedNavigationTermSetId), item.Value.ManagedNavigationAddNewPages.HasValue ? item.Value.ManagedNavigationAddNewPages.ToString() : "", item.Value.ManagedNavigationCreateFriendlyUrls.HasValue ? item.Value.ManagedNavigationCreateFriendlyUrls.ToString() : "", item.Value.LibraryItemScheduling.ToString(), item.Value.LibraryEnableModeration.ToString(), item.Value.LibraryEnableVersioning.ToString(), item.Value.LibraryEnableMinorVersions.ToString(), item.Value.LibraryApprovalWorkflowDefined.ToString(), item.Value.BrokenPermissionInheritance.ToString(), ToCsv(SiteScanResult.FormatUserList(item.Value.Admins, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)), ToCsv(SiteScanResult.FormatUserList(item.Value.Owners, this.EveryoneClaim, this.EveryoneExceptExternalUsersClaim)) ))); } } if (Options.IncludePublishingWithPages(this.Mode)) { // Export the page publishing data outputfile = string.Format("{0}\\ModernizationPublishingPageScanResults.csv", this.OutputFolder); outputHeaders = new string[] { "SiteCollectionUrl", "SiteUrl", "WebRelativeUrl", "PageRelativeUrl", "PageName", "ContentType", "ContentTypeId", "PageLayout", "PageLayoutFile", "GlobalAudiences", "SecurityGroupAudiences", "SharePointGroupAudiences", "ModifiedAt", "ModifiedBy", "Mapping %" }; string header1 = string.Join(this.Separator, outputHeaders); string header2 = ""; for (int i = 1; i <= 20; i++) { if (ExportWebPartProperties) { header2 = header2 + $"{this.Separator}WPType{i}{this.Separator}WPTitle{i}{this.Separator}WPData{i}"; } else { header2 = header2 + $"{this.Separator}WPType{i}{this.Separator}WPTitle{i}"; } } Console.WriteLine("Outputting scan results to {0}", outputfile); using (StreamWriter outfile = new StreamWriter(outputfile)) { outfile.Write(string.Format("{0}\r\n", header1 + header2)); foreach (var item in this.PublishingPageScanResults) { var part1 = string.Join(this.Separator, ToCsv(item.Value.SiteColUrl), ToCsv(item.Value.SiteURL), ToCsv(item.Value.WebRelativeUrl), ToCsv(item.Value.PageRelativeUrl), ToCsv(item.Value.PageName), ToCsv(item.Value.ContentType), ToCsv(item.Value.ContentTypeId), ToCsv(item.Value.PageLayout), ToCsv(item.Value.PageLayoutFile), ToCsv(PublishingPageScanResult.FormatList(item.Value.GlobalAudiences)), ToCsv(PublishingPageScanResult.FormatList(item.Value.SecurityGroupAudiences, "|")), ToCsv(PublishingPageScanResult.FormatList(item.Value.SharePointGroupAudiences)), item.Value.ModifiedAt, ToCsv(item.Value.ModifiedBy), "{MappingPercentage}" ); string part2 = ""; if (item.Value.WebParts != null) { int webPartsOnPage = item.Value.WebParts.Count(); int webPartsOnPageMapped = 0; List <string> nonMappedWebParts = new List <string>(); foreach (var webPart in item.Value.WebParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { var found = this.PageTransformation.WebParts.Where(p => p.Type.Equals(webPart.Type, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (found != null && found.Mappings != null) { webPartsOnPageMapped++; } else { var t = webPart.Type.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0]; if (!nonMappedWebParts.Contains(t)) { nonMappedWebParts.Add(t); } } if (ExportWebPartProperties) { part2 = part2 + $"{this.Separator}{ToCsv(webPart.TypeShort())}{this.Separator}{ToCsv(webPart.Title)}{this.Separator}{ToCsv(webPart.Json())}"; } else { part2 = part2 + $"{this.Separator}{ToCsv(webPart.TypeShort())}{this.Separator}{ToCsv(webPart.Title)}"; } } part1 = part1.Replace("{MappingPercentage}", webPartsOnPage == 0 ? "100" : String.Format("{0:0}", (((double)webPartsOnPageMapped / (double)webPartsOnPage) * 100))).Replace("{UnmappedWebParts}", SiteScanResult.FormatList(nonMappedWebParts)); } else { part1 = part1.Replace("{MappingPercentage}", "").Replace("{UnmappedWebParts}", ""); } outfile.Write(string.Format("{0}\r\n", part1 + (!string.IsNullOrEmpty(part2) ? part2 : ""))); } } } } Console.WriteLine("====================================================="); Console.WriteLine("All done. Took {0} for {1} sites", (DateTime.Now - start).ToString(), this.ScannedSites); Console.WriteLine("====================================================="); return(start); }