From 2af3bf39894bfd245a758a8d609031f1476b48c2 Mon Sep 17 00:00:00 2001 From: Alek Date: Thu, 2 Sep 2021 11:00:16 -0500 Subject: [PATCH] initial code commit --- .gitattributes | 63 + Analysis/Analysis.cs | 13 + Analysis/Analysis.csproj | 52 + Analysis/Properties/AssemblyInfo.cs | 36 + Common/Common.csproj | 248 ++ Common/CompareWorkflows.cs | 19 + Common/DiscoverBase.cs | 66 + Common/Extensions.cs | 124 + Common/IBaseAnalyzer.cs | 19 + Common/Logging.cs | 175 ++ Common/Properties/AssemblyInfo.cs | 36 + Common/Scan.cs | 18 + Common/WebpartMappingLoader.cs | 44 + Common/WorkFlowActions.cs | 43 + Common/WorkflowActionAnalysis.cs | 23 + Common/WorkflowCommon.cs | 1854 +++++++++++ Common/WorkflowScanResult.cs | 130 + Common/WorkflowTriggerAnalysis.cs | 20 + Common/app.config | 47 + Common/packages.config | 40 + Common/sp2010wfmodel.cs | 2514 +++++++++++++++ Common/sp2010wfmodel.xml | 1589 ++++++++++ Common/sp2010wfmodel.xsd | 445 +++ Common/sp2013wfmodel.cs | 3069 +++++++++++++++++++ Common/sp2013wfmodel.xml | 1919 ++++++++++++ Common/sp2013wfmodel.xsd | 552 ++++ Discovery/Discovery.csproj | 222 ++ Discovery/DiscoveryBase.cs | 66 + Discovery/Properties/AssemblyInfo.cs | 36 + Discovery/Scan.cs | 14 + Discovery/SiteScanResult.cs | 620 ++++ Discovery/WFDiscovery.cs | 781 +++++ Discovery/WorkflowManager.cs | 359 +++ Discovery/app.config | 47 + Discovery/packages.config | 39 + Discovery/sp2010wfmodel.xml | 1589 ++++++++++ Discovery/sp2013wfmodel.xml | 1919 ++++++++++++ Microsoft.Services.WorkflowAssessment.sln | 43 + Root/CmdCompareDownloadWorkflows.cs | 57 + Root/CmdGetWorkflowAssociationsForOnprem.cs | 309 ++ Root/CmdGetWorkflowAssociationsForSPO.cs | 184 ++ Root/GetWorkflowForSPOnline.cs | 649 ++++ Root/GetWorkflowsforOnPrem.cs | 370 +++ Root/Properties/AssemblyInfo.cs | 36 + Root/Root.csproj | 241 ++ Root/app.config | 59 + Root/packages.config | 41 + 47 files changed, 20839 insertions(+) create mode 100644 .gitattributes create mode 100644 Analysis/Analysis.cs create mode 100644 Analysis/Analysis.csproj create mode 100644 Analysis/Properties/AssemblyInfo.cs create mode 100644 Common/Common.csproj create mode 100644 Common/CompareWorkflows.cs create mode 100644 Common/DiscoverBase.cs create mode 100644 Common/Extensions.cs create mode 100644 Common/IBaseAnalyzer.cs create mode 100644 Common/Logging.cs create mode 100644 Common/Properties/AssemblyInfo.cs create mode 100644 Common/Scan.cs create mode 100644 Common/WebpartMappingLoader.cs create mode 100644 Common/WorkFlowActions.cs create mode 100644 Common/WorkflowActionAnalysis.cs create mode 100644 Common/WorkflowCommon.cs create mode 100644 Common/WorkflowScanResult.cs create mode 100644 Common/WorkflowTriggerAnalysis.cs create mode 100644 Common/app.config create mode 100644 Common/packages.config create mode 100644 Common/sp2010wfmodel.cs create mode 100644 Common/sp2010wfmodel.xml create mode 100644 Common/sp2010wfmodel.xsd create mode 100644 Common/sp2013wfmodel.cs create mode 100644 Common/sp2013wfmodel.xml create mode 100644 Common/sp2013wfmodel.xsd create mode 100644 Discovery/Discovery.csproj create mode 100644 Discovery/DiscoveryBase.cs create mode 100644 Discovery/Properties/AssemblyInfo.cs create mode 100644 Discovery/Scan.cs create mode 100644 Discovery/SiteScanResult.cs create mode 100644 Discovery/WFDiscovery.cs create mode 100644 Discovery/WorkflowManager.cs create mode 100644 Discovery/app.config create mode 100644 Discovery/packages.config create mode 100644 Discovery/sp2010wfmodel.xml create mode 100644 Discovery/sp2013wfmodel.xml create mode 100644 Microsoft.Services.WorkflowAssessment.sln create mode 100644 Root/CmdCompareDownloadWorkflows.cs create mode 100644 Root/CmdGetWorkflowAssociationsForOnprem.cs create mode 100644 Root/CmdGetWorkflowAssociationsForSPO.cs create mode 100644 Root/GetWorkflowForSPOnline.cs create mode 100644 Root/GetWorkflowsforOnPrem.cs create mode 100644 Root/Properties/AssemblyInfo.cs create mode 100644 Root/Root.csproj create mode 100644 Root/app.config create mode 100644 Root/packages.config diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Analysis/Analysis.cs b/Analysis/Analysis.cs new file mode 100644 index 0000000..353f32b --- /dev/null +++ b/Analysis/Analysis.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Analysis +{ + public class Analysis + { + + } +} diff --git a/Analysis/Analysis.csproj b/Analysis/Analysis.csproj new file mode 100644 index 0000000..c136baf --- /dev/null +++ b/Analysis/Analysis.csproj @@ -0,0 +1,52 @@ + + + + + Debug + AnyCPU + {11F9C187-6E26-43CC-AA57-B82049101ECC} + Library + Properties + Analysis + Analysis + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\Common\ReferenceDLLs\Microsoft.SharePoint.Client.dll + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Analysis/Properties/AssemblyInfo.cs b/Analysis/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d8e2a55 --- /dev/null +++ b/Analysis/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Analysis")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Analysis")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("11f9c187-6e26-43cc-aa57-b82049101ecc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Common.csproj b/Common/Common.csproj new file mode 100644 index 0000000..5c1a9a4 --- /dev/null +++ b/Common/Common.csproj @@ -0,0 +1,248 @@ + + + + + Debug + AnyCPU + {04A36617-4353-4779-92F9-36BAFFE6A5F6} + Library + Properties + Common + Microsoft.Services.WorkflowAssessment.Common + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\AngleSharp.0.9.9\lib\net45\AngleSharp.dll + + + ..\packages\Microsoft.Azure.ActiveDirectory.GraphClient.2.1.0\lib\portable-net4+sl5+win+wpa+wp8\Microsoft.Azure.ActiveDirectory.GraphClient.dll + + + ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll + + + ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll + + + ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll + + + ..\packages\Microsoft.Graph.1.9.0\lib\net45\Microsoft.Graph.dll + + + ..\packages\Microsoft.Graph.Core.1.9.0\lib\net45\Microsoft.Graph.Core.dll + + + ..\packages\Microsoft.IdentityModel.7.0.0\lib\net35\microsoft.identitymodel.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.5.2.4\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.5.2.4\lib\net451\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.5.2.4\lib\net451\Microsoft.IdentityModel.Tokens.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.Policy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.TranslationServices.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.SharePoint.Tools.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Online.SharePoint.Client.Tenant.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.ProjectServer.Client.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.dll + True + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.DocumentManagement.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Publishing.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.dll + True + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.Windows.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.Applications.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Taxonomy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.UserProfiles.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.WorkflowServices.dll + + + ..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\SharePointPnPCoreOnline.3.24.2008.1\lib\net461\OfficeDevPnP.Core.dll + + + ..\packages\SharePointPnP.IdentityModel.Extensions.1.2.4\lib\net45\SharePointPnP.IdentityModel.Extensions.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.5.2.4\lib\net451\System.IdentityModel.Tokens.Jwt.dll + + + False + ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Net.Http.4.3.1\lib\net46\System.Net.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + + ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + + + + + + + + + + + + + sp2010wfmodel.xsd + + + sp2013wfmodel.xsd + + + + + + + + + + + + + + + Designer + + + Designer + + + + + + + + + + + \ No newline at end of file diff --git a/Common/CompareWorkflows.cs b/Common/CompareWorkflows.cs new file mode 100644 index 0000000..ba760db --- /dev/null +++ b/Common/CompareWorkflows.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + public class CompareWorkflows + { + public void CompareWorkflowsToPowerAutomate(string outputDirectory) + { + try + { } + catch (Exception ex) + { } + } + } +} diff --git a/Common/DiscoverBase.cs b/Common/DiscoverBase.cs new file mode 100644 index 0000000..e1fb043 --- /dev/null +++ b/Common/DiscoverBase.cs @@ -0,0 +1,66 @@ +using Microsoft.SharePoint.Client; +using System; + +namespace Common +{ + public abstract class DiscoverBase : IBaseAnalyzer + { + private string url; + private string siteColUrl; + + + /// + /// Base constructor + /// + /// Url of the current web + /// url of the current site collection + public DiscoverBase(string url, string siteColUrl) + { + this.url = url; + this.siteColUrl = siteColUrl; + } + + /// + /// Scan start time + /// + public DateTime StartTime { get; set; } + + /// + /// Scan stop time + /// + public DateTime StopTime { get; set; } + + /// + /// Site collection url being scanned + /// + public string SiteCollectionUrl + { + get + { + return this.siteColUrl; + } + } + + /// + /// Site being scanned + /// + public string SiteUrl + { + get + { + return this.url; + } + } + + /// + /// Virtual Analyze method + /// + /// ClientContext of the web to be analyzed + /// Duration of the analysis + public virtual TimeSpan Analyze(ClientContext cc) + { + this.StartTime = DateTime.Now; + return new TimeSpan(); + } + } +} diff --git a/Common/Extensions.cs b/Common/Extensions.cs new file mode 100644 index 0000000..2facd8c --- /dev/null +++ b/Common/Extensions.cs @@ -0,0 +1,124 @@ +using Microsoft.SharePoint.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Common +{ + public static partial class WebExtensions + { + + /// + /// Gets a list of SharePoint lists to scan for modern compatibility + /// + /// Web to check + /// List of SharePoint lists to scan + public static List GetListsToScan(this Microsoft.SharePoint.Client.Web web, bool showHidden = false) + { + List lists = new List(10); + + // Ensure timeout is set on current context as this can be an operation that times out + web.Context.RequestTimeout = Timeout.Infinite; + + ListCollection listCollection = web.Lists; + listCollection.EnsureProperties(coll => coll.Include(li => li.Id, li => li.ForceCheckout, li => li.Title, li => li.Hidden, li => li.DefaultViewUrl, + li => li.BaseTemplate, li => li.RootFolder, li => li.ListExperienceOptions, li => li.ItemCount, + li => li.UserCustomActions, li => li.LastItemUserModifiedDate)); + // Let's process the visible lists + IQueryable listsToReturn = null; + + if (showHidden) + { + listsToReturn = listCollection; + } + else + { + listsToReturn = listCollection.Where(p => p.Hidden == false); + } + + foreach (List list in listsToReturn) + { + if (list.DefaultViewUrl.Contains("_catalogs")) + { + // skip catalogs + continue; + } + + if (list.BaseTemplate == 544) + { + // skip MicroFeed (544) + continue; + } + + lists.Add(list); + } + + return lists; + } + } + public static class SiteExtensions + { + /// + /// Gets all sub sites for a given site + /// + /// Site to find all sub site for + /// IEnumerable of strings holding the sub site urls + public static IEnumerable GetAllSubSites(this Site site) + { + var siteContext = site.Context; + siteContext.Load(site, s => s.Url); + + try + { + siteContext.ExecuteQueryRetry(); + } + catch (System.Net.WebException clientException) + { + Console.WriteLine(clientException.Message.ToString()); + yield break; + } + catch (Microsoft.SharePoint.Client.ServerUnauthorizedAccessException unauthorizedException) + { + Console.WriteLine(unauthorizedException.Message.ToString()); + yield break; + } + + var queue = new Queue(); + queue.Enqueue(site.Url); + while (queue.Count > 0) + { + var currentUrl = queue.Dequeue(); + try + { + using (var webContext = siteContext.Clone(currentUrl)) + { + webContext.Load(webContext.Web, web => web.Webs.Include(w => w.Url, w => w.WebTemplate)); + webContext.ExecuteQueryRetry(); + foreach (var subWeb in webContext.Web.Webs) + { + // Ensure these props are loaded...sometimes the initial load did not handle this + subWeb.EnsureProperties(s => s.Url, s => s.WebTemplate); + + // Don't dive into App webs and Access Services web apps + if (!subWeb.WebTemplate.Equals("App", StringComparison.InvariantCultureIgnoreCase) && + !subWeb.WebTemplate.Equals("ACCSVC", StringComparison.InvariantCultureIgnoreCase)) + { + queue.Enqueue(subWeb.Url); + } + } + } + } + catch (Exception) + { + // Eat exceptions when certain subsites aren't accessible, better this then breaking the complete fMedium + } + + yield return currentUrl; + } + } + } + +} diff --git a/Common/IBaseAnalyzer.cs b/Common/IBaseAnalyzer.cs new file mode 100644 index 0000000..c236682 --- /dev/null +++ b/Common/IBaseAnalyzer.cs @@ -0,0 +1,19 @@ +using Microsoft.SharePoint.Client; +using System; + +namespace Common +{ + /// + /// Interface that all analyzers need to implement + /// + public interface IBaseAnalyzer + { + + /// + /// Analyzer run + /// + /// ClientContext of the web to be analyzed + /// Duration of the analysis + TimeSpan Analyze(ClientContext cc); + } +} diff --git a/Common/Logging.cs b/Common/Logging.cs new file mode 100644 index 0000000..5c599d0 --- /dev/null +++ b/Common/Logging.cs @@ -0,0 +1,175 @@ +using System.Web; +using System.Data; +//using System.Web.Security; +//using System.Web.UI; +//using System.Web.UI.WebControls; +//using System.Web.UI.HtmlControls; +//using Microsoft.SharePoint; +using System.Text; +using System.Collections.Generic; +using System; +using System.Globalization; +using System.ComponentModel; +using System.IO; +using System.Xml; +using System.Collections; +using System.Configuration; +using System.Diagnostics; +using System.Security; +using System.Security.Policy; +using System.Security.Principal; +using System.Security.Permissions; +using System.Runtime.InteropServices; + +namespace Common +{ + public class Logging + { + + #region class properties + public static string LOG_DIRECTORY { get; set; } + //public string LOG_DIRECTORY { get; set; } + public const string Info = "INFO"; + public const string Error = "ERROR"; + private string logFolderPath = LOG_DIRECTORY; + + private string LogFolderPath + { + get + { + return logFolderPath; + } + set + { + if (Directory.Exists(value)) + { + logFolderPath = value; + if (logFolderPath.EndsWith("\\")) + { + logFolderPath = logFolderPath.Remove(logFolderPath.Length); + } + } + else + { + throw new DirectoryNotFoundException(); + } + } + } + private string logFileName = ""; + private string LogFileName + { + get + { + return logFileName; + } + set + { + logFileName = value; + } + } + private string LogFilePath + { + get + { + return this.LogFolderPath + "\\" + this.LogFileName; + } + } + private static Logging _log; + #endregion + + public static Logging GetInstance() + { + if (_log == null) + _log = new Logging(LOG_DIRECTORY, "Log_", true, false); + if(!_log.logFolderPath.Equals(LOG_DIRECTORY)) + _log = new Logging(LOG_DIRECTORY, "Log_", true, false); + return _log; + } + + #region Constructor + /// + /// Create a HTMLFileLogging object + /// + /// The path of the folder that will hold the log file (no file name) + /// The name of the file to create + /// When this is set to true and the folder does not exist, the code will create the folder. + /// When this is set to true and the file exists, the code will delete the file and create a new one + private Logging(string folderPath, string fileName, bool createPath, bool deleteFile) + { + this.LogFileName = fileName + DateString() + ".log"; + + if (createPath && !Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + this.LogFolderPath = folderPath; + if (File.Exists(this.LogFilePath) && deleteFile) + { + File.Delete(this.LogFilePath); + } + } + + #endregion + + #region custom code + /// + /// Writes a string to the log file. + /// + /// a string to write. supports html tags. + public void WriteToLogFile(string level, string message) + { + try + { + //string rowFormat = "
{0} {2}
"; + StreamWriter sw = new StreamWriter(this.LogFilePath, true); + string logMesg = String.Format(DateTime.Now.ToString(), "\t", level, "\t", message, "\n"); + logMesg = string.Concat(DateTime.Now.ToString(), "\t", level, "\t", message, "\n"); + sw.WriteLine(logMesg); + sw.Flush(); + sw.Close(); + } + catch + { + } + } + + public string DateString() + { + string dateString = string.Empty; + + if (DateTime.Now.Month < 10) + dateString += "0"; + dateString += DateTime.Now.Month; + + if (DateTime.Now.Day < 10) + dateString += "0"; + dateString += DateTime.Now.Day; + + dateString += DateTime.Now.Year.ToString(); + + dateString += "_"; + + if (DateTime.Now.Hour < 10) + dateString += "0"; + dateString += DateTime.Now.Hour; + + dateString += "_"; + + if (DateTime.Now.Minute < 10) + dateString += "0"; + dateString += DateTime.Now.Minute; + + dateString += "_"; + + if (DateTime.Now.Second < 10) + dateString += "0"; + dateString += DateTime.Now.Second; + + + return dateString; + } + + #endregion + + } +} \ No newline at end of file diff --git a/Common/Properties/AssemblyInfo.cs b/Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0a8dbfa --- /dev/null +++ b/Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Common")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("04a36617-4353-4779-92f9-36baffe6a5f6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Scan.cs b/Common/Scan.cs new file mode 100644 index 0000000..940dc0b --- /dev/null +++ b/Common/Scan.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + + /// + /// Base class for scan results + /// + public class Scan + { + public string SiteURL { get; set; } + public string SiteColUrl { get; set; } + } +} diff --git a/Common/WebpartMappingLoader.cs b/Common/WebpartMappingLoader.cs new file mode 100644 index 0000000..c67058b --- /dev/null +++ b/Common/WebpartMappingLoader.cs @@ -0,0 +1,44 @@ +using System.IO; + +namespace Common +{ + /// + /// Class to support the embedded webpartmapping.xml file + /// + public static class WebpartMappingLoader + { + /// + /// Load the webpartmapping file from the embedded resources + /// + /// Fully qualified path to file + /// String contents + public static string LoadFile(string fileName) + { + var fileContent = ""; + using (Stream stream = typeof(WebpartMappingLoader).Assembly.GetManifestResourceStream(fileName)) + { + using (StreamReader reader = new StreamReader(stream)) + { + fileContent = reader.ReadToEnd(); + } + } + + return fileContent; + } + + /// + /// Transforms a string into a stream + /// + /// String to transform + /// Stream + public static Stream GenerateStreamFromString(string s) + { + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; + } + } +} diff --git a/Common/WorkFlowActions.cs b/Common/WorkFlowActions.cs new file mode 100644 index 0000000..a91b6a4 --- /dev/null +++ b/Common/WorkFlowActions.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + + /// + /// Workflow types + /// + public enum WorkflowTypes + { + SP2010, + SP2013 + } + + /// + /// Workflow action class + /// + public class WorkflowAction + { + public string ActionName { get; set; } + public string ActionNameShort { get; set; } + } + + /// + /// Class holding the default workflow actions for 2010/2013 SharePoint workflow + /// + public class WorkflowActions + { + public WorkflowActions() + { + SP2010DefaultActions = new List(); + SP2013DefaultActions = new List(); + } + + public List SP2010DefaultActions { get; set; } + public List SP2013DefaultActions { get; set; } + + } +} diff --git a/Common/WorkflowActionAnalysis.cs b/Common/WorkflowActionAnalysis.cs new file mode 100644 index 0000000..3783786 --- /dev/null +++ b/Common/WorkflowActionAnalysis.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + public class WorkflowActionAnalysis + { + + public WorkflowActionAnalysis() + { + this.WorkflowActions = new List(); + this.UnsupportedActions = new List(); + } + + public List WorkflowActions { get; set; } + public int ActionCount { get; set; } + public List UnsupportedActions { get; set; } + public int UnsupportedAccountCount { get; set; } + } +} diff --git a/Common/WorkflowCommon.cs b/Common/WorkflowCommon.cs new file mode 100644 index 0000000..1283a86 --- /dev/null +++ b/Common/WorkflowCommon.cs @@ -0,0 +1,1854 @@ +//using Microsoft.Deployment.Compression.Cab; +//using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using System.Data; +using Microsoft.SharePoint.Client; +using System.Security; +using System.Management.Automation; +using Microsoft.Online.SharePoint.TenantAdministration; + +namespace Common +{ + + public class Operations + + { + /// + /// SPO Properties + /// + public string DownloadPath { get; set; } + public bool DownloadForms { get; set; } + public string summaryFile = @"\WorkflowDiscovery.csv"; + public string logFolder = @"\Logs"; + public string downloadedFormsFolder = @"\DownloadedWorkflows"; + public string analysisFolder = @"\Analysis"; + public string summaryFolder = @"\Summary"; + public string analysisOutputFile = @"\WorkflowComparisonDetails.csv"; + public string compOutputFile = @"\WorkflowComparison.csv"; + public DataTable dt = new DataTable(); + + + public void SaveXamlFile(string xamlContent, Web web, string wfName, string scope, string folderPath) + { + try + { + string fileName = web.Id + "-" + wfName + "-" + scope+".xoml"; + string filePath = folderPath + "\\"+ fileName; + System.IO.File.WriteAllText(filePath, xamlContent); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + /// + /// Create Data Table + /// + /// + public void CreateDataTableColumns(DataTable dt) + { + try + { + dt.Columns.Add("SiteColID"); + dt.Columns.Add("SiteURL"); + dt.Columns.Add("ListTitle"); + dt.Columns.Add("ListUrl"); + dt.Columns.Add("ContentTypeId"); + dt.Columns.Add("ContentTypeName"); + dt.Columns.Add("ItemCount"); + dt.Columns.Add("Scope"); + dt.Columns.Add("Version"); + dt.Columns.Add("WFTemplateName"); + dt.Columns.Add("IsOOBWorkflow"); + dt.Columns.Add("RelativePath"); + dt.Columns.Add("WFID"); + dt.Columns.Add("WebID"); + dt.Columns.Add("WebURL"); + + //dt.Columns.Add("ListorLibID"); + //dt.Columns.Add("RelativePath"); + //dt.Columns.Add("IpTemplateName"); + //dt.Columns.Add("InfoPathUsage"); + //dt.Columns.Add("IpID"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + + /// + /// Create Data Table + /// + /// + public void AddRowToDataTable(WorkflowScanResult workflowScanResult, DataTable dt, string version, string scope, string wfName, string wfID, bool IsOOBWF, Web web) + { + DataRow dr = dt.NewRow(); + try + { + if (workflowScanResult.SiteColUrl == null && web.Url != null) + { + dr["SiteURL"] = web.Url; + dr["SiteColID"] = web.Id; + } + else + dr["SiteURL"] = workflowScanResult.SiteColUrl; + //dr["WebURL"] = workflowScanResult.SiteURL; + dr["CreatedBy"] = workflowScanResult.CreatedBy; + dr["ModifiedBy"] = workflowScanResult.ModifiedBy; + dr["WebURL"] = web.Url; + dr["ListTitle"] = workflowScanResult.ListTitle; + dr["ListUrl"] = workflowScanResult.ListUrl; + dr["ContentTypeId"] = workflowScanResult.ContentTypeId; + dr["ContentTypeName"] = workflowScanResult.ContentTypeName; + dr["ItemCount"] = workflowScanResult.ActionCount; + dr["Scope"] = scope; + dr["Version"] = version; + dr["WFTemplateName"] = wfName; + dr["IsOOBWorkflow"] = IsOOBWF; + dr["ItemCount"] = workflowScanResult.ActionCount; + dr["WFID"] = wfID; + dr["WebID"] = web.Id; + dt.Rows.Add(dr); + //dt.Columns.Add("SiteColID"); + //dt.Columns.Add("SiteURL"); + //dt.Columns.Add("ListTitle"); + //dt.Columns.Add("ListUrl"); + //dt.Columns.Add("ContentTypeId"); + //dt.Columns.Add("ContentTypeName"); + //dt.Columns.Add("ItemCount"); + //dt.Columns.Add("Scope"); + //dt.Columns.Add("Version"); + //dt.Columns.Add("WFTemplateName"); + //dt.Columns.Add("IsOOBWorkflow"); + //dt.Columns.Add("RelativePath"); + //dt.Columns.Add("WFID"); + //dt.Columns.Add("WebID"); + //dt.Columns.Add("WebURL"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + + /// + /// Creates 3 levels of folder at the downloaded path provided by the user + /// 1. Analysis + /// 2. DownloadedForms + /// 3. Summary + /// + /// + public void CreateDirectoryStructure(string downloadPath) + { + try + { + if (!Directory.Exists(string.Concat(downloadPath, analysisFolder))) + { + DirectoryInfo analysisFolder1 = System.IO.Directory.CreateDirectory(string.Concat(downloadPath, analysisFolder)); + Logging.GetInstance().WriteToLogFile(Logging.Info, "Analysis folder created"); + } + if (!Directory.Exists(string.Concat(downloadPath, downloadedFormsFolder))) + { + DirectoryInfo downloadedFormsFolder1 = System.IO.Directory.CreateDirectory(string.Concat(downloadPath, downloadedFormsFolder)); + Logging.GetInstance().WriteToLogFile(Logging.Info, "DownloadedForms folder created"); + + } + if (!Directory.Exists(string.Concat(downloadPath, summaryFolder))) + { + DirectoryInfo summaryFolder1 = System.IO.Directory.CreateDirectory(string.Concat(downloadPath, summaryFolder)); + Logging.GetInstance().WriteToLogFile(Logging.Info, "Summary folder created"); + + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + + public DataTable ConvertCSVToDataTable(string csvLocation) + { + DataTable dt = new DataTable(); + try + { + var Lines = System.IO.File.ReadAllLines(csvLocation); + string[] Fields; + Fields = Lines[0].Split(new char[] { ',' }); + int Cols = Fields.GetLength(0); + for (int i = 0; i < Cols; i++) + dt.Columns.Add(Fields[i].ToLower(), typeof(string)); + DataRow Row; + for (int i = 1; i < Lines.GetLength(0); i++) + { + Fields = Lines[i].Split(new char[] { ',' }); + Row = dt.NewRow(); + for (int f = 0; f < Cols; f++) + Row[f] = Fields[f].Split('"')[1]; + dt.Rows.Add(Row); + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return dt; + } + + + /// + /// The DataSet returned from the content database is stored in a datatable + /// The datatable is then saved into a CSV file that gets stored in the Summary folder + /// that gets created at the location of download path supplied by the users + /// + /// + /// + public void WriteToCsvFile(DataTable dataTable, string filePath) + { + try + { + Logging.GetInstance().WriteToLogFile(Logging.Info, "Preparing to create the CSV at " + filePath); + StringBuilder fileContent = new StringBuilder(); + + foreach (var col in dataTable.Columns) + { + fileContent.Append(col.ToString() + ","); + } + + fileContent.Replace(",", System.Environment.NewLine, fileContent.Length - 1, 1); + + foreach (DataRow dr in dataTable.Rows) + { + foreach (var column in dr.ItemArray) + { + fileContent.Append("\"" + column.ToString() + "\","); + } + + fileContent.Replace(",", System.Environment.NewLine, fileContent.Length - 1, 1); + } + + System.IO.File.WriteAllText(filePath, fileContent.ToString()); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("CSV File created at {0}", filePath)); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + + /// + /// + /// + /// + /// + /// + public void WriteProgress(string s, int x, int y) + { + int origRow = Console.CursorTop; + int origCol = Console.CursorLeft; + // Console.WindowWidth = 10; // this works. + int width = Console.WindowWidth; + //x = x % width; + try + { + Console.SetCursorPosition(x, y); + //Console.SetCursorPosition(origCol, origRow); + Console.Write(s); + } + catch (ArgumentOutOfRangeException e) + { + + } + finally + { + try + { + Console.SetCursorPosition(origRow, origCol); + } + catch (ArgumentOutOfRangeException e) + { + } + } + } + + internal ClientContext CreateClientContext(string url, string username, SecureString password) + { + try + { + var credentials = new SharePointOnlineCredentials( + username, + password); + + return new ClientContext(url) + { + Credentials = credentials + }; + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + return new ClientContext(url) + { + }; + } + + + } + + + public List GetAllTenantSites(string TenantName, PSCredential Credential) + { + List sites = new List(); + try + { + string tenantAdminUrl = "https://" + TenantName + "-admin.sharepoint.com/"; + ClientContext ctx = null; + ctx = CreateClientContext(tenantAdminUrl, Credential.UserName, Credential.Password); + Tenant tenant = new Tenant(ctx); + SPOSitePropertiesEnumerable siteProps = tenant.GetSitePropertiesFromSharePoint("0", true); + ctx.Load(siteProps); + ctx.ExecuteQuery(); + int count = 0; + foreach (var site in siteProps) + { + sites.Add(site.Url); + count++; + } + Console.WriteLine("Total Site {0}", count); + return sites; + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + return sites; + } + + /// + /// Open the site collection file and store in a collection variable + /// Read the file and display it line by line. + /// + /// + public void ReadInfoPathOnlineSiteCollection(List sitecollectionUrls, string filePath) + { + try + { + int counter = 0; + string line; + System.IO.StreamReader file = + new System.IO.StreamReader(filePath); + while ((line = file.ReadLine()) != null) + { + //removes all extra spaces etc. + sitecollectionUrls.Add(line.TrimEnd()); + //System.Console.WriteLine(line); + counter++; + } + file.Close(); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + } + + + + + /* + public class InfoPathScanResult + { + public string SiteColUrl { get; set; } + public string SiteURL { get; set; } + public string InfoPathUsage { get; set; } + public string ListTitle { get; set; } + public string ListId { get; set; } + public string ListUrl { get; set; } + public bool Enabled { get; set; } + public string InfoPathTemplate { get; set; } + public int ItemCount { get; set; } + public DateTime LastItemUserModifiedDate { get; set; } + + public string strDirName { get; set; } + + public string strLeafName { get; set; } + + public string SiteID { get; set; } + + public string WebID { get; set; } + } + + + public class Config + { + public string Rule { get; set; } + public Complexity Complexity { get; set; } + public bool MigrationPathExists { get; set; } + public bool CustomConnector { get; set; } + + } + public enum Complexity { Low, Medium, High, Critical }; + + public enum Scope { Farm, WebApp, SiteCol }; + + public abstract class InfoPathFeature + { + #region Useful XNamespace values + protected static XNamespace xdNamespace = @"http://schemas.microsoft.com/office/infopath/2003"; + protected static XNamespace xsfNamespace = @"http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"; + protected static XNamespace xsf2Namespace = @"http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"; + protected static XNamespace xsf3Namespace = @"http://schemas.microsoft.com/office/infopath/2009/solutionDefinition/extensions"; + protected static XNamespace xslNamespace = @"http://www.w3.org/1999/XSL/Transform"; + #endregion + + #region Public interface + public string FeatureName { get { return this.GetType().Name; } } + // need virtuals for formatting as a string, and an xml, or something ... + public override string ToString() + { + return FeatureName; + } + #endregion + public Complexity Complexity { get; set; } + public bool CustomConnector { get; set; } + public bool MigrationPathExists { get; set; } + public List Rules { get; set; } + + private void GetConfigFromJSON(JArray configuration) + { + foreach (dynamic dataconnection in configuration) + { + try + { + Rules.Add(new Config() + { + Rule = dataconnection.name, + Complexity = dataconnection.Complexity, + MigrationPathExists = dataconnection.migrationPathExists, + CustomConnector = dataconnection.CustomConnector + }); + } + catch(Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + } + + internal static string LoadDebugJSON() + { + string json = string.Empty; + string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + + using (StreamReader r = new StreamReader(dir + @"\infopathrules.json")) + + //using (StreamReader r = new StreamReader(@"C:\Users\rmeure\source\repos\InfoPathScrapper\InfoPathScrapper\settings.json")) + { + json = r.ReadToEnd(); + } + return json; + } + public InfoPathFeature() + { + Rules = new List(); + + var settings = LoadDebugJSON(); + JObject configuration = JObject.Parse(settings); + dynamic obj = JObject.Parse(settings); + + GetConfigFromJSON((JArray)obj["dataConnections"]["dataConnection"]); + GetConfigFromJSON((JArray)obj["dataRules"]["dataRule"]); + GetConfigFromJSON((JArray)obj["dataRules"]["actions"]["action"]); + GetConfigFromJSON((JArray)obj["controls"]["Control"]); + } + + #region Abstract method(s) + /// + /// This method returns a commaseparated list of the interesting values a particular feature has collected. + /// + /// + public abstract string ToCSV(); + #endregion + } + + public class Control : InfoPathFeature + { + #region Private stuff + private const string xctName = @"xctname"; + + private Control() { } + #endregion + + #region Public interface + public string Name { get; private set; } + public int Count { get; private set; } + + /// + /// Instead of logging on feature per control, I do 1 feature per control type along with the number of occurrences + /// + /// + /// + public static IEnumerable ParseFeature(XDocument document) + { + IEnumerable allElements = document.Descendants(); + BucketCounter counter = new BucketCounter(); + // collect the control counts + foreach (XElement element in allElements) + { + XAttribute xctAttribute = element.Attribute(xdNamespace + xctName); + if (xctAttribute != null) + { + counter.IncrementKey(xctAttribute.Value); + } + } + + // then create Control objects for each control + foreach (KeyValuePair kvp in counter.Buckets) + { + Control c = new Control(); + c.Name = kvp.Key; + c.Count = kvp.Value; + yield return c; + } + // nothing left + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + Name + "[" + Count + "]"; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + Name + "[" + Count + "]"; + } + + public override string ToCSV() + { + return Name + "," + Count; + } + #endregion + } + + + + public class InfoPathLocation + { + public string SiteId { get; set; } + public string WebId { get; set; } + public string DocId { get; set; } + public string DirName { get; set; } + public string LeafName { get; set; } + + } + + // Data Connection Classes + public class DataConnection : InfoPathFeature + { + #region Constants + private const string query = @"query"; + private const string spListConnection = @"sharepointListAdapter"; + private const string spListConnectionRW = @"sharepointListAdapterRW"; + private const string soapConnection = @"webServiceAdapter"; + private const string xmlConnection = @"xmlFileAdapter"; // also used for REST! + private const string adoConnection = @"adoAdapter"; + #endregion + + #region Public interface + public string ConnectionType { get; private set; } + public static IEnumerable ParseFeature(XDocument document) + { + + IEnumerable allDataConnections = document.Descendants(xsfNamespace + query); + foreach (XElement queryElement in allDataConnections) + { + yield return ParseDataConnection(queryElement); + } + + // nothing left + yield break; + } + + public string Connection + { get; private set; } + + + + public override string ToString() + { + return FeatureName + ": " + ConnectionType; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + ConnectionType; + } + + public override string ToCSV() + { + return ConnectionType; + } + #endregion + + #region Private helpers + /// + /// This should return DataConnection since every query element represents exactly one connection + /// In special cases (SPList, Soap) we defer to a subclass to mine more data. + /// + /// + /// + private static DataConnection ParseDataConnection(XElement queryElement) + { + XElement dataConnection = queryElement.Element(xsfNamespace + spListConnection); + if (dataConnection != null) + return SPListConnection.Parse(dataConnection); + else if ((dataConnection = queryElement.Element(xsfNamespace + spListConnectionRW)) != null) + return SPListConnection.Parse(dataConnection); + else if ((dataConnection = queryElement.Element(xsfNamespace + soapConnection)) != null) + return SoapConnection.Parse(dataConnection); + else if ((dataConnection = queryElement.Element(xsfNamespace + xmlConnection)) != null) + return XmlConnection.Parse(dataConnection); + else if ((dataConnection = queryElement.Element(xsfNamespace + adoConnection)) != null) + return AdoConnection.Parse(dataConnection); + + // else just grab the type and log that. Nothing else to do here. + foreach (XElement x in queryElement.Elements()) + { + if (dataConnection != null) throw new ArgumentException("More than one adapter found under a query node"); + dataConnection = x; + } + + if (dataConnection == null) throw new ArgumentException("No adapter found under query node"); + DataConnection dc = new DataConnection(); + dc.ConnectionType = dataConnection.Name.LocalName; + return dc; + } + #endregion + } + + /// + /// Subclass specifically for mining SP List connections + /// + class SPListConnection : DataConnection + { + #region Constants + private const string siteUrlAttribute = @"siteUrl"; + private const string siteURLAttribute = @"siteURL"; + private const string listGuidAttribute = @"sharePointListID"; + private const string sharepointGuidAttribute = @"sharepointGuid"; + private const string submitAllowedAttribute = @"submitAllowed"; + private const string relativeListUrlAttribute = @"relativeListUrl"; + private const string field = @"field"; + private const string typeAttribute = @"type"; + private static string[] validTypes = + { + "Counter", + "Integer", + "Number", + "Currency", + "Text", + "Choice", + "Plain", + "Compatible", + "FullHTML", + "DateTime", + "Boolean", + "Lookup", + "LookupMulti", + "MultiChoice", + "URL", + "User", + "UserMulti", + "Calculated", + "Attachments", + "HybridUser", + }; + private BucketCounter _bucketCounter; + #endregion + + private SPListConnection() + { + + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + + _bucketCounter = new BucketCounter(); + foreach (string type in validTypes) + _bucketCounter.DefineKey(type); + } + + #region Public interface + + public string SiteUrl { get; private set; } + public string ListGuid { get; private set; } + public string SubmitAllowed { get; private set; } + public string RelativeListUrl { get; private set; } + public IEnumerable> ColumnTypes + { + get + { + foreach (KeyValuePair kvp in _bucketCounter.Buckets) + yield return kvp; + yield break; + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + //sb.Append("Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " "); + sb.Append(FeatureName).Append(": "); + sb.Append("{").Append(SiteUrl).Append(", ").Append(RelativeListUrl).Append("} "); + if (IsV2) + { + sb.Append("Types: {"); + foreach (KeyValuePair kvp in ColumnTypes) + { + // for humanreadable, just emit nonzero counts + if (kvp.Value > 0) + sb.Append(kvp.Key).Append("=").Append(kvp.Value).Append(" "); + } + sb.Append("}"); + } + return sb.ToString().Trim(); + } + + public override string ToCSV() + { + StringBuilder sb = new StringBuilder(); + sb.Append(SiteUrl).Append(",").Append(RelativeListUrl).Append(","); + if (IsV2) + { + foreach (KeyValuePair kvp in ColumnTypes) + { + sb.Append(kvp.Key).Append(",").Append(kvp.Value).Append(","); + } + } + return sb.ToString(); + } + + private bool IsV2 { get; set; } + + /// + /// Selfexplanatory + /// + /// + /// + public static SPListConnection Parse(XElement dataConnection) + { + SPListConnection spl = new SPListConnection(); + spl.IsV2 = dataConnection.Name.LocalName.Equals("sharepointListAdapterRW"); + if (spl.IsV2) + { + spl.SiteUrl = dataConnection.Attribute(siteURLAttribute).Value; + spl.ListGuid = dataConnection.Attribute(listGuidAttribute).Value; + spl.SubmitAllowed = dataConnection.Attribute(submitAllowedAttribute).Value; + spl.RelativeListUrl = dataConnection.Attribute(relativeListUrlAttribute).Value; + + // we should also scrape out the queried column types, this shows us what types of data we consume from lists + foreach (XElement fieldElement in dataConnection.Elements(xsfNamespace + field)) + { + string fieldType = fieldElement.Attribute(typeAttribute).Value; + spl._bucketCounter.IncrementKey(fieldType); + } + } + else // if (dataConnection.Name.LocalName.Equals("sharepointListAdapter")) + { + spl.SiteUrl = dataConnection.Attribute(siteUrlAttribute).Value; + spl.ListGuid = dataConnection.Attribute(sharepointGuidAttribute).Value; + spl.SubmitAllowed = dataConnection.Attribute(submitAllowedAttribute).Value; + } + + + return spl; + } + #endregion + } + + /// + /// Subclass of DataConnection specifically for Soap web service calls. + /// + class SoapConnection : DataConnection + { + #region Constants + private const string wsdlUrlAttribute = @"wsdlUrl"; + private const string serviceUrlAttribute = @"serviceUrl"; + private const string nameAttribute = @"name"; + private const string operation = @"operation"; + private const string input = @"input"; + private const string sourceAttribute = @"source"; + + private const string webServiceAdapterExtension = @"webServiceAdapterExtension"; + private const string refAttribute = @"ref"; + private const string connectoid = @"connectoid"; + private const string udcxExt = @".udcx"; + #endregion + + private SoapConnection() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + #region Public interface + public string ServiceUrl { get; private set; } + public string ServiceMethod { get; private set; } + + public static DataConnection Parse(XElement dataConnection) + { + XElement udcExtension = null; + if (IsConnectionUDCX(dataConnection, out udcExtension) && udcExtension != null) + { + return UdcConnection.Parse(dataConnection, udcExtension); + } + return ParseInternal(dataConnection); + } + + public override string ToString() + { + return FeatureName + ": " + ServiceUrl + "::" + ServiceMethod; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + ServiceUrl + "::" + ServiceMethod; + } + + public override string ToCSV() + { + return ServiceUrl + "," + ServiceMethod; + } + #endregion + + #region Private helpers + private static SoapConnection ParseInternal(XElement dataConnection) + { + SoapConnection sc = new SoapConnection(); + XElement op = dataConnection.Element(xsfNamespace + operation); + if (op == null) + { + sc.ServiceUrl = dataConnection.Attribute(wsdlUrlAttribute).Value; + sc.ServiceMethod = dataConnection.Attribute(nameAttribute).Value; + } + else + { + sc.ServiceUrl = op.Attribute(serviceUrlAttribute).Value; + sc.ServiceMethod = op.Attribute(nameAttribute).Value; + XElement inp = op.Element(xsfNamespace + input); + if (inp != null && sc.ServiceUrl.Equals("")) + { + sc.ServiceUrl = inp.Attribute(sourceAttribute).Value; + sc.ServiceMethod = "?"; + } + } + + + if (sc.ServiceUrl.Equals("")) Console.WriteLine(dataConnection.ToString()); + return sc; + } + + + /// + /// Need to find the xsf2:webServiceAdapterExtension node elsewhere in the XDocument + /// Need to find the one that has ref the same as our connection name + /// + /// + /// + private static bool IsConnectionUDCX(XElement dataConnection, out XElement udcExtension) + { + udcExtension = null; + XAttribute name = dataConnection.Attribute(nameAttribute); + if (name == null) return false; + + string connectionName = name.Value; + foreach (XElement webServiceExt in dataConnection.Document.Descendants(xsf2Namespace + webServiceAdapterExtension)) + { + XAttribute refAtt = webServiceExt.Attribute(refAttribute); + if (refAtt == null) continue; // No name = no match + if (!refAtt.Value.Equals(connectionName)) continue; // These are not the extensions you are looking for ... *waves hand* + + XElement connect = webServiceExt.Element(xsf2Namespace + connectoid); + if (connect == null) return false; + XAttribute source = connect.Attribute(sourceAttribute); + if (source == null) return false; + + if (Path.GetExtension(source.Value) != udcxExt) return false; + + udcExtension = webServiceExt; + return true; + } + return false; + } + #endregion + } + + /// + /// Subclass of DataConnection specifically for UDCX Soap web service calls. + /// + class UdcConnection : DataConnection + { + #region Constants + private const string connectoid = @"connectoid"; + private const string nameAttribute = @"name"; + private const string sourceAttribute = @"source"; + #endregion + + //private UdcConnection() { } + + #region Public interface + public string SourceUrl { get; private set; } + public string MethodName { get; private set; } + + public static UdcConnection Parse(XElement dataConnection, XElement udcExtension) + { + UdcConnection uc = new UdcConnection(); + + XElement connect = udcExtension.Element(xsf2Namespace + connectoid); + + uc.MethodName = connect.Attribute(nameAttribute).Value; + uc.SourceUrl = connect.Attribute(sourceAttribute).Value; + + + return uc; + } + + protected UdcConnection() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + public override string ToString() + { + return FeatureName + ": " + SourceUrl + "::" + MethodName; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + SourceUrl + "::" + MethodName; + } + + public override string ToCSV() + { + return SourceUrl + "," + MethodName; + } + #endregion + } + + /// + /// Identifies a connection to an Xml file + /// + class XmlConnection : DataConnection + { + #region Constants + private const string fileUrlAttribute = @"fileUrl"; + private const string nameAttribute = @"name"; + private const string refAttribute = @"ref"; + private const string xmlFileAdapterExtension = @"xmlFileAdapterExtension"; + private const string isRestAttribute = @"isRest"; + #endregion + + protected XmlConnection() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + #region Public interface + public string Url { get; private set; } + + public static DataConnection Parse(XElement dataConnection) + { + XmlConnection xc = null; + bool isRest = IsConnectionRest(dataConnection); + xc = isRest ? new RESTConnection() : new XmlConnection(); + + string fileUrl = dataConnection.Attribute(fileUrlAttribute).Value; + + if (!String.IsNullOrEmpty(fileUrl)) + { + // We have an embedded XmlConnection + xc.Url = dataConnection.Attribute(fileUrlAttribute).Value; + return xc; + } + else + { + // The XmlConnection is stored in a UDCX connection file + XElement udcExtension = FindChild(dataConnection); + return UdcConnection.Parse(dataConnection, udcExtension); + } + } + + public override string ToString() + { + return FeatureName + ": " + Url; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + Url; + } + + public override string ToCSV() + { + return Url; + } + #endregion + + #region Private helpers + private static XElement FindChild(XElement dataConnection) + { + XAttribute name = dataConnection.Attribute(nameAttribute); + if (name == null) return null; + + string connectionName = name.Value; + foreach (XElement xmlExt in dataConnection.Document.Descendants(xsf2Namespace + xmlFileAdapterExtension)) + { + XAttribute refAtt = xmlExt.Attribute(refAttribute); + if (refAtt == null) continue; // No name = no match + if (!refAtt.Value.Equals(connectionName)) continue; // These are not the extensions you are looking for ... *waves hand* + return xmlExt; + } + return null; + } + + /// + /// Need to find the xsf2:xmlFileAdapterExtension node elsewhere in the XDocument + /// Need to find the one that has ref the same as our connection name, then look for isRest="[bool]" in there + /// + /// + /// + private static bool IsConnectionRest(XElement dataConnection) + { + XElement xmlExt = FindChild(dataConnection); + if (xmlExt == null) return false; + + XAttribute isRest = xmlExt.Attribute(isRestAttribute); + if (isRest == null) return false; + + return isRest.Value.Equals("yes"); + } + #endregion + } + + class RESTConnection : XmlConnection + { + //private RestConnection() + //{ + /// this.Complexity =Complexity.High; + // this.CustomConnector = true; + //} + } + + class AdoConnection : DataConnection + { + #region Constants + private const string connectionStringAttribute = @"connectionString"; + #endregion + + private AdoConnection() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + #region Public interface + public string ConnectionString { get; private set; } + + public static AdoConnection Parse(XElement dataConnection) + { + AdoConnection ac = new AdoConnection(); + ac.ConnectionString = dataConnection.Attribute(connectionStringAttribute).Value; + ac.Complexity = Complexity.High; + return ac; + } + + public override string ToString() + { + return FeatureName + ": " + ConnectionString; + // return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + ConnectionString; + } + + public override string ToCSV() + { + return ConnectionString; + } + #endregion + } + + + // Data Rules Classess + + public class DataRule : InfoPathFeature + { + #region Constants + private const string rule = @"rule"; + #endregion + + #region Public interface + public string ActionType { get; private set; } + + public DataRule() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + public static IEnumerable ParseFeature(XDocument document) + { + IEnumerable allRules = document.Descendants(xsfNamespace + rule); + foreach (XElement ruleElement in allRules) + { + foreach (DataRule feature in ParseRuleElement(ruleElement)) + yield return feature; + } + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + ActionType; + // return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + ActionType; + } + + public override string ToCSV() + { + return ActionType; + } + #endregion + + #region Private helpers + private static IEnumerable ParseRuleElement(XElement ruleElement) + { + foreach (XElement ruleAction in ruleElement.Elements()) + { + DataRule feature = new DataRule(); + feature.ActionType = ruleAction.Name.LocalName; + // we can be any one of many types of rules: dialogbox, assignment, query, submit, switch view + // we could parse further if that turns out to be interesting + yield return feature; + } + } + #endregion + } + + // Data Validation Class + + public class DataValidation : InfoPathFeature + { + #region Constants + private const string customValidation = @"customValidation"; + #endregion + + #region Public interface + public string ValidationType { get; private set; } + private DataValidation() + { + var rule = (from r in Rules + where r.Rule == this.GetType().Name + select r).First(); + this.Complexity = rule.Complexity; + this.MigrationPathExists = rule.MigrationPathExists; + this.CustomConnector = rule.CustomConnector; + } + + public static IEnumerable ParseFeature(XDocument document) + { + // we don't care about the condition details, just "any custom validation" vs "native cbb" + IEnumerable allValidations = document.Descendants(xsfNamespace + customValidation); + foreach (XElement validationElement in allValidations) + { + DataValidation validation = new DataValidation(); + validation.ValidationType = "Custom validation"; + yield return validation; + } + + allValidations = document.Descendants(xsf3Namespace + customValidation); + foreach (XElement validationElement in allValidations) + { + DataValidation validation = new DataValidation(); + validation.ValidationType = "Cannot be blank"; + yield return validation; + } + + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + ValidationType; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + ValidationType; + } + + public override string ToCSV() + { + return ValidationType; + } + #endregion + } + + // Formatting Class + + public class FormattingRule : InfoPathFeature + { + #region Constants + private const string xslAttribute = @"attribute"; + private const string nameAttribute = @"name"; + private const string contentEditable = @"contentEditable"; // readonly + private const string style = @"style"; // adjusting the look and feel (colors, hiding, etc ...) + private const string when = @"when"; + #endregion + + private FormattingRule() + { + this.Complexity = Complexity.Medium; + this.CustomConnector = false; + this.MigrationPathExists = true; + } + + #region Public interface + public string FormatType { get; private set; } + public string SubDetails { get; private set; } + + public static IEnumerable ParseFeature(XDocument document) + { + IEnumerable allElements = document.Descendants(xslNamespace + xslAttribute); + foreach (XElement element in allElements) + { + XAttribute name = element.Attribute(nameAttribute); + // these are the html attributes that we try to set. + // specifically for conditional hide we have to look under a style for an xsl:when with .Text() contains "DISPLAY: none" + if (name.Value.Equals(contentEditable)) + { + FormattingRule rule = new FormattingRule(); + rule.FormatType = "Readonly"; + yield return rule; + } + else if (name.Value.Equals(style)) + { + BucketCounter counter = new BucketCounter(); + FormattingRule rule = new FormattingRule(); + rule.FormatType = "Style"; + // now let's count all the things we're affecting. + // Overloading BucketCounter to filter the noise of multiple touches to same style + foreach (XElement xslWhen in element.Descendants(xslNamespace + when)) + { + string[] styles = xslWhen.Value.Split(new char[] { ';' }); + foreach (string s in styles) + { + if (s.Trim().StartsWith("caption:")) continue; + string affectedStyle = s.Split(':')[0].Trim().ToUpper(); + counter.IncrementKey(affectedStyle); + } + } + StringBuilder sb = new StringBuilder(); + foreach (KeyValuePair kvp in counter.Buckets) + { + sb.Append(kvp.Key).Append(" "); + } + rule.SubDetails = sb.ToString().Trim(); + yield return rule; + } + } + + // nothing left + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + FormatType + (SubDetails == null ? "" : "," + SubDetails); + // return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + FormatType + (SubDetails == null ? "" : " " + SubDetails); + } + + public override string ToCSV() + { + return FormatType + (SubDetails == null ? "" : "," + SubDetails); + } + #endregion + } + + // Managed Code Class + + class ManagedCode : InfoPathFeature + { + private const string enabledAttribute = @"enabled"; + private const string languageAttribute = @"language"; + private const string versionAttribute = @"version"; + private const string managedCode = @"managedCode"; + + private ManagedCode() + { + this.Complexity = Complexity.High; + this.CustomConnector = false; + this.MigrationPathExists = false; + } + + public string Language { get; private set; } + public string Version { get; private set; } + + public static IEnumerable ParseFeature(XDocument document) + { + IEnumerable allElements = document.Descendants(xsf2Namespace + managedCode); + foreach (XElement element in allElements) + { + //The enabled attribute is typically null, so check for that. + //If the attribute exists, then we can also check the value to make sure there's not an enabled="no" scenario. + if (element.Attribute(enabledAttribute) == null + || !string.Equals(element.Attribute(enabledAttribute).Value, "yes", StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + //Return an object if enabled="yes" + ManagedCode mc = new ManagedCode(); + mc.Language = element.Attribute(languageAttribute).Value; + mc.Version = element.Attribute(versionAttribute).Value; + yield return mc; + } + + // nothing left + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + Language + " " + Version; + //return "Complexity: " + Complexity + " CustomConnector: " + CustomConnector + " MigrationPathExists: " + MigrationPathExists + " " + FeatureName + ": " + Language + " " + Version; + } + + public override string ToCSV() + { + return Language + "," + Version; + } + } + + //Mode Class + + class Mode : InfoPathFeature + { + private const string modeAttribute = @"mode"; + private const string solutionFormatVersionAttribute = @"solutionFormatVersion"; + private const string solutionMode = @"solutionMode"; + private const string solutionDefinition = @"solutionDefinition"; + private const string solutionPropertiesExtension = @"solutionPropertiesExtension"; + private const string branchAttribute = @"branch"; + private const string runtimeCompatibilityAttribute = @"runtimeCompatibility"; + private const string xDocumentClass = @"xDocumentClass"; + + public string ModeName { get; private set; } + public string Compatibility { get; private set; } + + private Mode() { } + + public static IEnumerable ParseFeature(XDocument document) + { + + Mode m = new Mode(); + string mode = null; + + // look for fancy new modes first (these were new for xsf3 / IP2010) + IEnumerable allModeElements = document.Descendants(xsf3Namespace + solutionMode); + foreach (XElement element in allModeElements) + { + if (mode != null) throw new ArgumentException("Found more than one mode!"); + XAttribute name = element.Attribute(modeAttribute); + mode = name.Value; + } + + // and if we didn't find the above, fall back to client v server in xsf2:solutionDefinition + if (mode == null) + { + IEnumerable allSolutionDefs = document.Descendants(xsf2Namespace + solutionDefinition); + foreach (XElement solutionDef in allSolutionDefs) + { + if (mode != null) throw new ArgumentException("Found more than one xsf2:solutionDefition!"); + XElement extension = solutionDef.Element(xsf2Namespace + solutionPropertiesExtension); + if (extension != null && extension.Attribute(branchAttribute) != null && extension.Attribute(branchAttribute).Equals("contentType")) + { + mode = "Document Information Panel"; + } + else + { + XAttribute compat = solutionDef.Attribute(runtimeCompatibilityAttribute); + mode = compat.Value; + } + } + } + + // and if we still found nothing, it's a 2003 form and must be client: + if (mode == null) + mode = "client"; + + m.ModeName = mode; + + string compatibility = null; + foreach (XElement xDoc in document.Descendants(xsfNamespace + xDocumentClass)) + { + if (compatibility != null) throw new ArgumentException("Multiple xDocumentClass nodes found!"); + compatibility = xDoc.Attribute(solutionFormatVersionAttribute).Value; + } + m.Compatibility = compatibility; + + yield return m; + yield break; + } + + + public override string ToString() + { + return FeatureName + ": " + ModeName + " " + Compatibility; + } + + public override string ToCSV() + { + return ModeName + "," + Compatibility; + } + } + + //Product Version Class + + class ProductVersion : InfoPathFeature + { + private const string productVersionAttribute = @"productVersion"; + + public string Version { get; private set; } + + public static IEnumerable ParseFeature(XDocument document) + { + //ProductVersion is off the root node, so grab that value and return the value. + XAttribute attribute = document.Root.Attribute(productVersionAttribute); + + if (attribute != null) + { + ProductVersion pv = new ProductVersion(); + pv.Version = attribute.Value; + yield return pv; + } + + // nothing left + yield break; + } + + public override string ToString() + { + return FeatureName + ": " + Version; + } + + public override string ToCSV() + { + return Version; + } + } + + //Publish Class + + class PublishUrl : InfoPathFeature + { + #region Private stuff + private const string baseUrl = @"baseUrl"; + private const string relativeUrlBaseAttribute = @"relativeUrlBase"; + private const string publishUrlAttribute = @"publishUrl"; + private const string xDocumentClass = @"xDocumentClass"; + + private PublishUrl() { } + #endregion + + #region Public interface + public string Publish { get; private set; } + public string RelativeBase { get; private set; } + + /// + /// Instead of logging on feature per control, I do 1 feature per control type along with the number of occurrences + /// + /// + /// + public static IEnumerable ParseFeature(XDocument document) + { + PublishUrl pubRule = new PublishUrl(); + IEnumerable allElements = document.Descendants(xsf3Namespace + baseUrl); + // collect the control counts + foreach (XElement element in allElements) + { + if (pubRule.RelativeBase != null) throw new ArgumentException("Should only see one xsf3:baseUrl node"); + XAttribute pathAttribute = element.Attribute(relativeUrlBaseAttribute); + if (pathAttribute != null) // this attribute is technically optional per xsf3 spec + { + pubRule.RelativeBase = pathAttribute.Value; + } + } + + allElements = document.Descendants(xsfNamespace + xDocumentClass); + foreach (XElement element in allElements) + { + if (pubRule.Publish != null) throw new ArgumentException("Should only see one xsf:xDocumentClass node"); + XAttribute pubUrl = element.Attribute(publishUrlAttribute); + if (pubUrl != null) + { + pubRule.Publish = pubUrl.Value; + } + } + + yield return pubRule; + // nothing left + yield break; + } + + public override string ToString() + { + return FeatureName + ": RelativeBase=" + RelativeBase + ", PublishUrl=" + Publish; + } + + public override string ToCSV() + { + return RelativeBase + "," + Publish; + } + #endregion + } + + // InfoPath File Class + + public abstract class InfoPathFile + { + private XDocument _xDocument; + private List _features; + + #region Public interface + public CabFileInfo CabFileInfo { get; protected set; } + public XDocument XDocument { get { InitializeXDocument(); return _xDocument; } } + + /// + /// Enumerates the features found in this InfoPathFile. + /// + public IEnumerable Features + { + get + { + InitializeFeatures(); + foreach (InfoPathFeature feature in _features) + yield return feature; + yield break; + } + } + #endregion + + #region Abstract methods + protected abstract IEnumerable>> FeatureDiscoverers { get; } + #endregion + + #region Private helpers + /// + /// Loads the XDocument that is the file from the cab. All parseable InfoPath files are xml documents. + /// + private void InitializeXDocument() + { + try + { + if (_xDocument != null) return; + + Stream content = CabFileInfo.OpenRead(); + // use the 3.5compatible Load API that takes an XmlReader, that way this will work when targeting either .NET3.5 or later + System.Xml.XmlReader reader = System.Xml.XmlReader.Create(content); + _xDocument = XDocument.Load(reader); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + + /// + /// Run all the FeatureDiscoverers for this file type. Each deriving InfoPathFile type + /// defines what features it *might* contain. + /// + private void InitializeFeatures() + { + try + { + if (_features != null) return; + _features = new List(); + foreach (Func> discoverer in FeatureDiscoverers) + foreach (InfoPathFeature feature in discoverer.Invoke(XDocument)) + _features.Add(feature); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + #endregion + } + + // InfoPath Manifestv Class + + public class InfoPathManifest : InfoPathFile + { + #region Private members + private static XNamespace xsfNamespace = @"http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"; + private static XNamespace xsf2Namespace = @"http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"; + private static XNamespace xsf3Namespace = @"http://schemas.microsoft.com/office/infopath/2009/solutionDefinition/extensions"; + private const string viewNode = @"mainpane"; + private const string viewNameAttribute = @"transform"; + private const string xDocumentClass = @"xDocumentClass"; + private const string uniqueUrn = @"name"; + + private XElement _xDocumentNode; + private List _viewNames; + private InfoPathManifest() { } + #endregion + + #region Public stuff + public List ViewNames { get { InitializeViewNames(); return _viewNames; } } + public string Name + { + get + { + InitializeXDocumentNode(); + + //InfoPath 2003 forms don't have a Name attribute, so return an empty string instead of throwing an exception. + return (_xDocumentNode.Attribute(uniqueUrn) == null) ? string.Empty : _xDocumentNode.Attribute(uniqueUrn).Value; + } + } + public static InfoPathManifest Create(CabFileInfo cabFileInfo) + { + InfoPathManifest manifest = new InfoPathManifest(); + manifest.CabFileInfo = cabFileInfo; + return manifest; + } + #endregion + + #region Override implementations + protected override IEnumerable>> FeatureDiscoverers + { + get + { + yield return Mode.ParseFeature; + yield return PublishUrl.ParseFeature; + yield return DataConnection.ParseFeature; + yield return ManagedCode.ParseFeature; + yield return ProductVersion.ParseFeature; + yield return DataRule.ParseFeature; + yield return DataValidation.ParseFeature; + yield break; + } + } + + #endregion + + #region Private helpers + /// + /// This is the root node of the manifest.xsf file from which get a few interesting properties. + /// + private void InitializeXDocumentNode() + { + if (_xDocumentNode != null) return; + IEnumerable elements = XDocument.Descendants(xsfNamespace + xDocumentClass); + foreach (XElement element in elements) + { + if (_xDocumentNode != null) throw new ArgumentException("Manifest has multiple xDocumentClass nodes"); + _xDocumentNode = element; + } + } + + /// + /// An xsn can have many resource files in it. The only reliable way to know which ones are views is to + /// parse the manifest for those that are called out as such. We just need string names of them because + /// the Microsoft.Deployment.Compression.Cab code will happily find them by name. + /// + private void InitializeViewNames() + { + if (_viewNames != null) return; + _viewNames = new List(); + + foreach (XElement mainpane in XDocument.Descendants(xsfNamespace + viewNode)) + { + _viewNames.Add(mainpane.Attribute(viewNameAttribute).Value); + } + } + #endregion + + } + + //InfoPath Template Class + + + public class InfoPathTemplate + { + #region Members and Basics + public CabInfo CabInfo { get; private set; } + public List _infoPathViews; + private InfoPathManifest _infoPathManifest; + + public static InfoPathTemplate CreateTemplate(string path) + { + // Lazy Init + CabInfo cabInfo = new CabInfo(path); + InfoPathTemplate template = new InfoPathTemplate(); + template.CabInfo = cabInfo; + return template; + } + #endregion + + + #region Various Properties we should support + public List InfoPathViews { get { InitializeViews(); return _infoPathViews; } } + public InfoPathManifest InfoPathManifest { get { InitializeManifest(); return _infoPathManifest; } } + public IEnumerable FeaturedFiles { get { yield return InfoPathManifest; foreach (InfoPathView view in InfoPathViews) yield return view; yield break; } } + public IEnumerable Features { get { foreach (InfoPathFile file in FeaturedFiles) { foreach (InfoPathFeature feature in file.Features) yield return feature; } yield break; } } + #endregion + + #region Private helpers to compute things + private void InitializeManifest() + { + if (_infoPathManifest != null) return; + + // get the files named manifest.xsf (there should be one) + IList cbInfos = null; + try + { + cbInfos = CabInfo.GetFiles("manifest.xsf"); + } + catch (Exception error) + { + Console.WriteLine(error.Message.ToString()); + } + + // TODO check for corrupt infopath forms + if (cbInfos == null) + throw new ArgumentException("Invalid InfoPath xsn"); + if (cbInfos.Count != 1) throw new ArgumentException("Invalid InfoPath xsn"); + _infoPathManifest = InfoPathManifest.Create(cbInfos[0]); + } + + private void InitializeViews() + { + if (_infoPathViews != null) return; + _infoPathViews = new List(); + + foreach (string name in InfoPathManifest.ViewNames) + { + IList cbInfos = CabInfo.GetFiles(name); + if (cbInfos.Count != 1) throw new ArgumentException(String.Format("Malformed template file: view {0} not found", name)); + InfoPathView viewFile = InfoPathView.Create(cbInfos[0]); + _infoPathViews.Add(viewFile); + } + } + #endregion + } + + //InfoPath View Class + + /// + /// Selfexplanatory implementation + /// + public class InfoPathView : InfoPathFile + { + #region Private stuff + private InfoPathView() { } + #endregion + + #region Public stuff + public static InfoPathView Create(CabFileInfo cabFileInfo) + { + InfoPathView view = new InfoPathView(); + view.CabFileInfo = cabFileInfo; + return view; + } + #endregion + + #region Override implementations + protected override IEnumerable>> FeatureDiscoverers + { + get + { + yield return Control.ParseFeature; + yield return FormattingRule.ParseFeature; + yield break; + } + } + #endregion + + } + + public class BucketCounter + { + private Dictionary _dictionary; + + public BucketCounter() + { + _dictionary = new Dictionary(); + } + + /// + /// Creates a key and initializes it to a count of zero. + /// + /// + public void DefineKey(string key) + { + if (!_dictionary.ContainsKey(key)) + _dictionary.Add(key, 0); + } + + /// + /// Make sure we have a counter for the key and increment it. + /// Note that this is why I use Int32 objects instead of int + /// + /// + public void IncrementKey(string key) + { + DefineKey(key); + _dictionary[key]++; + } + + /// + /// For each KeyValuePair, return it. I create new ones here so that + /// a caller can't accidentally mess up the values in the Dictionary + /// The buckets are returned in sortedbykey order because that's more useful than a random order + // + public IEnumerable> Buckets + { + get + { + List orderedKeys = new List(); + foreach (string key in _dictionary.Keys) + orderedKeys.Add(key); + orderedKeys.Sort(); + + foreach (string key in orderedKeys) + yield return new KeyValuePair(key, _dictionary[key]); + yield break; + } + } + } + */ +} + diff --git a/Common/WorkflowScanResult.cs b/Common/WorkflowScanResult.cs new file mode 100644 index 0000000..dd1af84 --- /dev/null +++ b/Common/WorkflowScanResult.cs @@ -0,0 +1,130 @@ +using OfficeDevPnP.Core.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + public class WorkflowScanResult : Scan + { + + public WorkflowScanResult() + { + this.UsedActions = new List(); + this.UnsupportedActionsInFlow = new List(); + this.UsedTriggers = new List(); + this.LastSubscriptionEdit = DateTime.MinValue; + this.LastDefinitionEdit = DateTime.MinValue; + } + + public string CreatedBy { get; set; } + + public string ModifiedBy { get; set; } + + public DateTime CreatedOn { get; set; } + + public DateTime ModifiedOn { get; set; } + + public DateTime LastRun { get; set; } + + public string ListUrl { get; set; } + + public string ListTitle { get; set; } + + public Guid ListId { get; set; } + + public string ContentTypeName { get; set; } + public string ContentTypeId { get; set; } + + public Guid DefinitionId { get; set; } + + public Guid SubscriptionId { get; set; } + + /// + /// 2010 or 2013 workflow engine + /// + public string Version { get; set; } + + public bool IsOOBWorkflow { get; set; } + + /// + /// Site, List, ContentType + /// + public string Scope { get; set; } + + /// + /// Site, List or Universal workflow (2013) or N/A (2010) + /// + public string RestrictToType { get; set; } + + public bool Enabled { get; set; } + + /// + /// Calculation showing if one should consider upgrading this workflow + /// + public bool ConsiderUpgradingToFlow + { + get + { + if ((Scope == "List" || Scope == "ContentType" || Scope == "Site") && + Enabled && !IsOOBWorkflow && HasSubscriptions) + { + return true; + } + else + { + return false; + } + } + } + + public string DefinitionName { get; set; } + + public string DefinitionDescription { get; set; } + + public string SubscriptionName { get; set; } + + public bool HasSubscriptions { get; set; } + + public int ActionCount { get; set; } + + public List UsedActions { get; set; } + + public int ToFLowMappingPercentage + { + get + { + if (ActionCount == 0) + { + return -1; + } + else + { + return (int)(((double)(ActionCount - UnsupportedActionCount) / (double)ActionCount) * 100); + } + } + } + + public int UnsupportedActionCount { get; set; } + + public List UnsupportedActionsInFlow { get; set; } + + public List UsedTriggers { get; set; } + + public DateTime LastSubscriptionEdit { get; set; } + + public DateTime LastDefinitionEdit { get; set; } + + /// + /// Site administrators + /// + public List Admins { get; set; } + /// + /// Site owners + /// + public List Owners { get; set; } + + } +} diff --git a/Common/WorkflowTriggerAnalysis.cs b/Common/WorkflowTriggerAnalysis.cs new file mode 100644 index 0000000..7c71c68 --- /dev/null +++ b/Common/WorkflowTriggerAnalysis.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Common +{ + public class WorkflowTriggerAnalysis + { + public WorkflowTriggerAnalysis() + { + this.WorkflowTriggers = new List(); + this.UnSupportedTriggers = new List(); + } + + public List WorkflowTriggers { get; set; } + public List UnSupportedTriggers { get; set; } + } +} diff --git a/Common/app.config b/Common/app.config new file mode 100644 index 0000000..ca263be --- /dev/null +++ b/Common/app.config @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Common/packages.config b/Common/packages.config new file mode 100644 index 0000000..da13d58 --- /dev/null +++ b/Common/packages.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Common/sp2010wfmodel.cs b/Common/sp2010wfmodel.cs new file mode 100644 index 0000000..601a962 --- /dev/null +++ b/Common/sp2010wfmodel.cs @@ -0,0 +1,2514 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// +// This source code was auto-generated by xsd, Version=4.8.3928.0. +// +namespace Common.SP2010 { + using System.Xml.Serialization; + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] + public partial class WorkflowInfo { + + private WorkflowInfoConditions conditionsField; + + private WorkflowInfoActions actionsField; + + private WorkflowInfoCompositeSteps compositeStepsField; + + private WorkflowInfoVariableTypes variableTypesField; + + private WorkflowInfoAssemblyRedirects assemblyRedirectsField; + + private WorkflowInfoCoercions coercionsField; + + private string languageField; + + /// + public WorkflowInfoConditions Conditions { + get { + return this.conditionsField; + } + set { + this.conditionsField = value; + } + } + + /// + public WorkflowInfoActions Actions { + get { + return this.actionsField; + } + set { + this.actionsField = value; + } + } + + /// + public WorkflowInfoCompositeSteps CompositeSteps { + get { + return this.compositeStepsField; + } + set { + this.compositeStepsField = value; + } + } + + /// + public WorkflowInfoVariableTypes VariableTypes { + get { + return this.variableTypesField; + } + set { + this.variableTypesField = value; + } + } + + /// + public WorkflowInfoAssemblyRedirects AssemblyRedirects { + get { + return this.assemblyRedirectsField; + } + set { + this.assemblyRedirectsField = value; + } + } + + /// + public WorkflowInfoCoercions Coercions { + get { + return this.coercionsField; + } + set { + this.coercionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditions { + + private WorkflowInfoConditionsDefault defaultField; + + private WorkflowInfoConditionsCondition[] conditionField; + + private string andField; + + private string orField; + + private string whenField; + + private string elseField; + + private string notField; + + /// + public WorkflowInfoConditionsDefault Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Condition")] + public WorkflowInfoConditionsCondition[] Condition { + get { + return this.conditionField; + } + set { + this.conditionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string And { + get { + return this.andField; + } + set { + this.andField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Or { + get { + return this.orField; + } + set { + this.orField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string When { + get { + return this.whenField; + } + set { + this.whenField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Else { + get { + return this.elseField; + } + set { + this.elseField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Not { + get { + return this.notField; + } + set { + this.notField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditionsDefault { + + private ruleDesignerType ruleDesignerField; + + private WorkflowInfoConditionsDefaultItemKeyType itemKeyTypeField; + + public WorkflowInfoConditionsDefault() { + this.itemKeyTypeField = WorkflowInfoConditionsDefaultItemKeyType.SystemInt32; + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(WorkflowInfoConditionsDefaultItemKeyType.SystemInt32)] + public WorkflowInfoConditionsDefaultItemKeyType ItemKeyType { + get { + return this.itemKeyTypeField; + } + set { + this.itemKeyTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ruleDesignerType { + + private ruleDesignerTypeFieldBind[] fieldBindField; + + private string sentenceField; + + /// + [System.Xml.Serialization.XmlElementAttribute("FieldBind")] + public ruleDesignerTypeFieldBind[] FieldBind { + get { + return this.fieldBindField; + } + set { + this.fieldBindField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Sentence { + get { + return this.sentenceField; + } + set { + this.sentenceField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBind { + + private object[] itemsField; + + private string fieldField; + + private string textField; + + private string idField; + + private ruleDesignerTypeFieldBindDesignerType designerTypeField; + + private string operatorTypeFromField; + + private string typeFromField; + + private bool functionField; + + private string valueField; + + public ruleDesignerTypeFieldBind() { + this.functionField = false; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("DataSourceRef", typeof(ruleDesignerTypeFieldBindDataSourceRef))] + [System.Xml.Serialization.XmlElementAttribute("Option", typeof(ruleDesignerTypeFieldBindOption))] + public object[] Items { + get { + return this.itemsField; + } + set { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Field { + get { + return this.fieldField; + } + set { + this.fieldField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Text { + get { + return this.textField; + } + set { + this.textField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="positiveInteger")] + public string Id { + get { + return this.idField; + } + set { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ruleDesignerTypeFieldBindDesignerType DesignerType { + get { + return this.designerTypeField; + } + set { + this.designerTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string OperatorTypeFrom { + get { + return this.operatorTypeFromField; + } + set { + this.operatorTypeFromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeFrom { + get { + return this.typeFromField; + } + set { + this.typeFromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Function { + get { + return this.functionField; + } + set { + this.functionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBindDataSourceRef { + + private string refField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Ref { + get { + return this.refField; + } + set { + this.refField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class dataSourceType { + + private dataSourceTypeSchemaSource schemaSourceField; + + private dataSourceTypeEvaluation evaluationField; + + private string internalNameField; + + private string nameField; + + private string namePropertyField; + + /// + public dataSourceTypeSchemaSource SchemaSource { + get { + return this.schemaSourceField; + } + set { + this.schemaSourceField = value; + } + } + + /// + public dataSourceTypeEvaluation Evaluation { + get { + return this.evaluationField; + } + set { + this.evaluationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName { + get { + return this.internalNameField; + } + set { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string NameProperty { + get { + return this.namePropertyField; + } + set { + this.namePropertyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSource { + + private object itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ContentType", typeof(dataSourceTypeSchemaSourceContentType))] + [System.Xml.Serialization.XmlElementAttribute("Dictionary", typeof(dataSourceTypeSchemaSourceDictionary))] + [System.Xml.Serialization.XmlElementAttribute("Fields", typeof(dataSourceTypeSchemaSourceFields))] + [System.Xml.Serialization.XmlElementAttribute("NestedInitiationFieldNodes", typeof(object))] + public object Item { + get { + return this.itemField; + } + set { + this.itemField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceContentType { + + private string iDFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string IDFrom { + get { + return this.iDFromField; + } + set { + this.iDFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceDictionary { + + private string valueFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ValueFrom { + get { + return this.valueFromField; + } + set { + this.valueFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFields { + + private dataSourceTypeSchemaSourceFieldsField[] fieldField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Field")] + public dataSourceTypeSchemaSourceFieldsField[] Field { + get { + return this.fieldField; + } + set { + this.fieldField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFieldsField { + + private dataSourceTypeSchemaSourceFieldsFieldCHOICE[] cHOICESField; + + private string nameField; + + private string displayNameField; + + private string typeField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("CHOICE", IsNullable=false)] + public dataSourceTypeSchemaSourceFieldsFieldCHOICE[] CHOICES { + get { + return this.cHOICESField; + } + set { + this.cHOICESField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFieldsFieldCHOICE { + + private string displayNameField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluation { + + private object itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ActivitySource", typeof(dataSourceTypeEvaluationActivitySource))] + [System.Xml.Serialization.XmlElementAttribute("HashtableSource", typeof(dataSourceTypeEvaluationHashtableSource))] + public object Item { + get { + return this.itemField; + } + set { + this.itemField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluationActivitySource { + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluationHashtableSource { + + private string hashtableFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string HashtableFrom { + get { + return this.hashtableFromField; + } + set { + this.hashtableFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class defaultElementType { + + private ruleDesignerType ruleDesignerField; + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBindOption { + + private string nameField; + + private string valueField; + + private string typeFilterField; + + private string unaryHidesField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeFilter { + get { + return this.typeFilterField; + } + set { + this.typeFilterField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string UnaryHides { + get { + return this.unaryHidesField; + } + set { + this.unaryHidesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum ruleDesignerTypeFieldBindDesignerType { + + /// + AddPermission, + + /// + Assignment, + + /// + Bool, + + /// + CheckPermission, + + /// + ChooseDoclibItem, + + /// + ChooseListItem, + + /// + CreateListItem, + + /// + DataSourceFieldNames, + + /// + DataSourceValues, + + /// + Date, + + /// + Dependent, + + /// + Dropdown, + + /// + Email, + + /// + FieldNames, + + /// + Float, + + /// + Hyperlink, + + /// + Integer, + + /// + ListNames, + + /// + Operator, + + /// + ParameterNames, + + /// + Person, + + /// + RemovePermission, + + /// + ReplacePermission, + + /// + SinglePerson, + + /// + StatusDropdown, + + /// + StringBuilder, + + /// + Survey, + + /// + TaskSummary, + + /// + Text, + + /// + TextBox, + + /// + TextArea, + + /// + UpdateListItem, + + /// + WritableFieldNames, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsDefaultItemKeyType { + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Int32")] + SystemInt32, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Microsoft.SharePoint.Workflow.SPItemKey")] + MicrosoftSharePointWorkflowSPItemKey, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditionsCondition { + + private ruleDesignerType ruleDesignerField; + + private parametersTypeParameter[] parametersField; + + private WorkflowInfoConditionsConditionType typeField; + + private bool typeFieldSpecified; + + private string nameField; + + private appliesToTypes appliesToField; + + private bool usesCurrentItemField; + + private WorkflowInfoConditionsConditionItemKeyType itemKeyTypeField; + + private string functionNameField; + + private string assemblyField; + + private string classNameField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + public WorkflowInfoConditionsCondition() { + this.usesCurrentItemField = false; + this.itemKeyTypeField = WorkflowInfoConditionsConditionItemKeyType.SystemInt32; + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public parametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public WorkflowInfoConditionsConditionType Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool TypeSpecified { + get { + return this.typeFieldSpecified; + } + set { + this.typeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool UsesCurrentItem { + get { + return this.usesCurrentItemField; + } + set { + this.usesCurrentItemField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(WorkflowInfoConditionsConditionItemKeyType.SystemInt32)] + public WorkflowInfoConditionsConditionItemKeyType ItemKeyType { + get { + return this.itemKeyTypeField; + } + set { + this.itemKeyTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FunctionName { + get { + return this.functionNameField; + } + set { + this.functionNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class parametersTypeParameter { + + private string nameField; + + private string typeField; + + private parametersTypeParameterDirection directionField; + + private string descriptionField; + + private parametersTypeParameterDesignerType designerTypeField; + + private bool designerTypeFieldSpecified; + + private bool showLookupForDropdownField; + + private string displayNameField; + + private string initialValueField; + + private string initialBindingField; + + public parametersTypeParameter() { + this.showLookupForDropdownField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parametersTypeParameterDirection Direction { + get { + return this.directionField; + } + set { + this.directionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parametersTypeParameterDesignerType DesignerType { + get { + return this.designerTypeField; + } + set { + this.designerTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool DesignerTypeSpecified { + get { + return this.designerTypeFieldSpecified; + } + set { + this.designerTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ShowLookupForDropdown { + get { + return this.showLookupForDropdownField; + } + set { + this.showLookupForDropdownField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InitialValue { + get { + return this.initialValueField; + } + set { + this.initialValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InitialBinding { + get { + return this.initialBindingField; + } + set { + this.initialBindingField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum parametersTypeParameterDirection { + + /// + In, + + /// + Out, + + /// + Optional, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum parametersTypeParameterDesignerType { + + /// + ContentType, + + /// + DataSourceFieldNames, + + /// + DataSourceValues, + + /// + Date, + + /// + Dependent, + + /// + Dropdown, + + /// + FieldNames, + + /// + Hide, + + /// + Integer, + + /// + ItemProperties, + + /// + ListItem, + + /// + ListNames, + + /// + ParameterNames, + + /// + Person, + + /// + SinglePerson, + + /// + StatusDropdown, + + /// + StringBuilder, + + /// + TextArea, + + /// + TextBox, + + /// + WritableFieldNames, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsConditionType { + + /// + Advanced, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + public enum appliesToTypes { + + /// + none, + + /// + list, + + /// + doclib, + + /// + all, + + /// + displayonly, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsConditionItemKeyType { + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Int32")] + SystemInt32, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Microsoft.SharePoint.Workflow.SPItemKey")] + MicrosoftSharePointWorkflowSPItemKey, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActions { + + private defaultElementType defaultField; + + private WorkflowInfoActionsAction[] actionField; + + private string sequentialField; + + private string parallelField; + + /// + public defaultElementType Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Action")] + public WorkflowInfoActionsAction[] Action { + get { + return this.actionField; + } + set { + this.actionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Sequential { + get { + return this.sequentialField; + } + set { + this.sequentialField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Parallel { + get { + return this.parallelField; + } + set { + this.parallelField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsAction { + + private parametersTypeParameter[] parametersField; + + private ruleDesignerType ruleDesignerField; + + private dataSourceType[] dataSourcesField; + + private WorkflowInfoActionsActionModification[] modificationsField; + + private WorkflowInfoActionsActionActionVariables actionVariablesField; + + private WorkflowInfoActionsActionActionBody actionBodyField; + + private WorkflowInfoActionsActionActionConditions actionConditionsField; + + private string nameField; + + private string classNameField; + + private string assemblyField; + + private string functionNameField; + + private string categoryField; + + private bool createsTaskField; + + private string createsInListField; + + private appliesToTypes appliesToField; + + private bool isErrorField; + + private bool listModerationField; + + private bool usesCurrentItemField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + private WorkflowInfoActionsActionCreatedTaskFormType createdTaskFormTypeField; + + private bool createdTaskFormTypeFieldSpecified; + + private string @__SolutionIdField; + + private bool sandboxedFunctionField; + + public WorkflowInfoActionsAction() { + this.functionNameField = ""; + this.createsTaskField = false; + this.isErrorField = false; + this.listModerationField = false; + this.usesCurrentItemField = false; + this.sandboxedFunctionField = false; + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public parametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DataSource", IsNullable=false)] + public dataSourceType[] DataSources { + get { + return this.dataSourcesField; + } + set { + this.dataSourcesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Modification", IsNullable=false)] + public WorkflowInfoActionsActionModification[] Modifications { + get { + return this.modificationsField; + } + set { + this.modificationsField = value; + } + } + + /// + public WorkflowInfoActionsActionActionVariables ActionVariables { + get { + return this.actionVariablesField; + } + set { + this.actionVariablesField = value; + } + } + + /// + public WorkflowInfoActionsActionActionBody ActionBody { + get { + return this.actionBodyField; + } + set { + this.actionBodyField = value; + } + } + + /// + public WorkflowInfoActionsActionActionConditions ActionConditions { + get { + return this.actionConditionsField; + } + set { + this.actionConditionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute("")] + public string FunctionName { + get { + return this.functionNameField; + } + set { + this.functionNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Category { + get { + return this.categoryField; + } + set { + this.categoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool CreatesTask { + get { + return this.createsTaskField; + } + set { + this.createsTaskField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string CreatesInList { + get { + return this.createsInListField; + } + set { + this.createsInListField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool IsError { + get { + return this.isErrorField; + } + set { + this.isErrorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ListModeration { + get { + return this.listModerationField; + } + set { + this.listModerationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool UsesCurrentItem { + get { + return this.usesCurrentItemField; + } + set { + this.usesCurrentItemField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public WorkflowInfoActionsActionCreatedTaskFormType CreatedTaskFormType { + get { + return this.createdTaskFormTypeField; + } + set { + this.createdTaskFormTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool CreatedTaskFormTypeSpecified { + get { + return this.createdTaskFormTypeFieldSpecified; + } + set { + this.createdTaskFormTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string @__SolutionId { + get { + return this.@__SolutionIdField; + } + set { + this.@__SolutionIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool SandboxedFunction { + get { + return this.sandboxedFunctionField; + } + set { + this.sandboxedFunctionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionModification { + + private string typeIdField; + + private string nameFormatField; + + private string formURNField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeId { + get { + return this.typeIdField; + } + set { + this.typeIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string NameFormat { + get { + return this.nameFormatField; + } + set { + this.nameFormatField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FormURN { + get { + return this.formURNField; + } + set { + this.formURNField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionVariables { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionBody { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionConditions { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoActionsActionCreatedTaskFormType { + + /// + DataCollectTask, + + /// + GroupAssignedTask, + + /// + TodoItemTask, + + /// + TaskProcess, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCompositeSteps { + + private WorkflowInfoCompositeStepsCompositeStep[] compositeStepField; + + /// + [System.Xml.Serialization.XmlElementAttribute("CompositeStep")] + public WorkflowInfoCompositeStepsCompositeStep[] CompositeStep { + get { + return this.compositeStepField; + } + set { + this.compositeStepField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCompositeStepsCompositeStep { + + private dataSourceType[] dataSourcesField; + + private string nameField; + + private string classNameField; + + private string assemblyField; + + private appliesToTypes appliesToField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + private string orderField; + + private string descriptionField; + + public WorkflowInfoCompositeStepsCompositeStep() { + this.orderField = "0"; + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DataSource", IsNullable=false)] + public dataSourceType[] DataSources { + get { + return this.dataSourcesField; + } + set { + this.dataSourcesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="nonNegativeInteger")] + [System.ComponentModel.DefaultValueAttribute("0")] + public string Order { + get { + return this.orderField; + } + set { + this.orderField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoVariableTypes { + + private WorkflowInfoVariableTypesVariableType[] variableTypeField; + + /// + [System.Xml.Serialization.XmlElementAttribute("VariableType")] + public WorkflowInfoVariableTypesVariableType[] VariableType { + get { + return this.variableTypeField; + } + set { + this.variableTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoVariableTypesVariableType { + + private string typeField; + + private string displayNameField; + + private string assemblyField; + + private string coercionActivityField; + + private bool defaultField; + + private bool itemIdTypeField; + + private bool hiddenField; + + public WorkflowInfoVariableTypesVariableType() { + this.defaultField = false; + this.itemIdTypeField = false; + this.hiddenField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string CoercionActivity { + get { + return this.coercionActivityField; + } + set { + this.coercionActivityField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ItemIdType { + get { + return this.itemIdTypeField; + } + set { + this.itemIdTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Hidden { + get { + return this.hiddenField; + } + set { + this.hiddenField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoAssemblyRedirects { + + private WorkflowInfoAssemblyRedirectsAssemblyRedirect[] assemblyRedirectField; + + /// + [System.Xml.Serialization.XmlElementAttribute("AssemblyRedirect")] + public WorkflowInfoAssemblyRedirectsAssemblyRedirect[] AssemblyRedirect { + get { + return this.assemblyRedirectField; + } + set { + this.assemblyRedirectField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoAssemblyRedirectsAssemblyRedirect { + + private string fromField; + + private string toField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string From { + get { + return this.fromField; + } + set { + this.fromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string To { + get { + return this.toField; + } + set { + this.toField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCoercions { + + private WorkflowInfoCoercionsCoercion[] coercionField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Coercion")] + public WorkflowInfoCoercionsCoercion[] Coercion { + get { + return this.coercionField; + } + set { + this.coercionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCoercionsCoercion { + + private string nameField; + + private string assemblyField; + + private string displayNameField; + + private bool catchAllField; + + private string rankDefaultField; + + private string sourceTypeField; + + private string sourceFieldTypeField; + + private string destinationTypeField; + + private string destinationFieldTypeField; + + private string classNameField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool CatchAll { + get { + return this.catchAllField; + } + set { + this.catchAllField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="integer")] + public string RankDefault { + get { + return this.rankDefaultField; + } + set { + this.rankDefaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceType { + get { + return this.sourceTypeField; + } + set { + this.sourceTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceFieldType { + get { + return this.sourceFieldTypeField; + } + set { + this.sourceFieldTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DestinationType { + get { + return this.destinationTypeField; + } + set { + this.destinationTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DestinationFieldType { + get { + return this.destinationFieldTypeField; + } + set { + this.destinationFieldTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + } +} diff --git a/Common/sp2010wfmodel.xml b/Common/sp2010wfmodel.xml new file mode 100644 index 0000000..d2c4a70 --- /dev/null +++ b/Common/sp2010wfmodel.xml @@ -0,0 +1,1589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Common/sp2010wfmodel.xsd b/Common/sp2010wfmodel.xsd new file mode 100644 index 0000000..847f9f3 --- /dev/null +++ b/Common/sp2010wfmodel.xsd @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Common/sp2013wfmodel.cs b/Common/sp2013wfmodel.cs new file mode 100644 index 0000000..68ced81 --- /dev/null +++ b/Common/sp2013wfmodel.cs @@ -0,0 +1,3069 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// +// This source code was auto-generated by xsd, Version=4.8.3928.0. +// +namespace Common.SP2013 { + using System.Xml.Serialization; + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)] + public partial class WorkflowInfo { + + private WorkflowInfoConditions conditionsField; + + private WorkflowInfoActions actionsField; + + private WorkflowInfoCompositeSteps compositeStepsField; + + private WorkflowInfoVariableTypes variableTypesField; + + private WorkflowInfoAssemblyRedirects assemblyRedirectsField; + + private WorkflowInfoCoercion[] coercionsField; + + private WorkflowInfoEvent[] eventsField; + + private WorkflowInfoFlow[] flowsField; + + private propertiesType[] blocksField; + + private string languageField; + + /// + public WorkflowInfoConditions Conditions { + get { + return this.conditionsField; + } + set { + this.conditionsField = value; + } + } + + /// + public WorkflowInfoActions Actions { + get { + return this.actionsField; + } + set { + this.actionsField = value; + } + } + + /// + public WorkflowInfoCompositeSteps CompositeSteps { + get { + return this.compositeStepsField; + } + set { + this.compositeStepsField = value; + } + } + + /// + public WorkflowInfoVariableTypes VariableTypes { + get { + return this.variableTypesField; + } + set { + this.variableTypesField = value; + } + } + + /// + public WorkflowInfoAssemblyRedirects AssemblyRedirects { + get { + return this.assemblyRedirectsField; + } + set { + this.assemblyRedirectsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Coercion", IsNullable=false)] + public WorkflowInfoCoercion[] Coercions { + get { + return this.coercionsField; + } + set { + this.coercionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Event", IsNullable=false)] + public WorkflowInfoEvent[] Events { + get { + return this.eventsField; + } + set { + this.eventsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Flow", IsNullable=false)] + public WorkflowInfoFlow[] Flows { + get { + return this.flowsField; + } + set { + this.flowsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Block", IsNullable=false)] + public propertiesType[] Blocks { + get { + return this.blocksField; + } + set { + this.blocksField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditions { + + private WorkflowInfoConditionsDefault defaultField; + + private WorkflowInfoConditionsCondition[] conditionField; + + private string andField; + + private string orField; + + private string whenField; + + private string elseField; + + private string notField; + + /// + public WorkflowInfoConditionsDefault Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Condition")] + public WorkflowInfoConditionsCondition[] Condition { + get { + return this.conditionField; + } + set { + this.conditionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string And { + get { + return this.andField; + } + set { + this.andField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Or { + get { + return this.orField; + } + set { + this.orField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string When { + get { + return this.whenField; + } + set { + this.whenField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Else { + get { + return this.elseField; + } + set { + this.elseField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Not { + get { + return this.notField; + } + set { + this.notField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditionsDefault { + + private ruleDesignerType ruleDesignerField; + + private WorkflowInfoConditionsDefaultItemKeyType itemKeyTypeField; + + public WorkflowInfoConditionsDefault() { + this.itemKeyTypeField = WorkflowInfoConditionsDefaultItemKeyType.SystemInt32; + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(WorkflowInfoConditionsDefaultItemKeyType.SystemInt32)] + public WorkflowInfoConditionsDefaultItemKeyType ItemKeyType { + get { + return this.itemKeyTypeField; + } + set { + this.itemKeyTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ruleDesignerType { + + private ruleDesignerTypeFieldBind[] fieldBindField; + + private string sentenceField; + + /// + [System.Xml.Serialization.XmlElementAttribute("FieldBind")] + public ruleDesignerTypeFieldBind[] FieldBind { + get { + return this.fieldBindField; + } + set { + this.fieldBindField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Sentence { + get { + return this.sentenceField; + } + set { + this.sentenceField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBind { + + private object[] itemsField; + + private string fieldField; + + private string textField; + + private string idField; + + private ruleDesignerTypeFieldBindDesignerType designerTypeField; + + private string operatorTypeFromField; + + private string typeFromField; + + private bool functionField; + + private string valueField; + + private string eventCategoryField; + + private string displayNameField; + + public ruleDesignerTypeFieldBind() { + this.functionField = false; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("DataSourceRef", typeof(ruleDesignerTypeFieldBindDataSourceRef))] + [System.Xml.Serialization.XmlElementAttribute("Option", typeof(ruleDesignerTypeFieldBindOption))] + public object[] Items { + get { + return this.itemsField; + } + set { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Field { + get { + return this.fieldField; + } + set { + this.fieldField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Text { + get { + return this.textField; + } + set { + this.textField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="positiveInteger")] + public string Id { + get { + return this.idField; + } + set { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ruleDesignerTypeFieldBindDesignerType DesignerType { + get { + return this.designerTypeField; + } + set { + this.designerTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string OperatorTypeFrom { + get { + return this.operatorTypeFromField; + } + set { + this.operatorTypeFromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeFrom { + get { + return this.typeFromField; + } + set { + this.typeFromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Function { + get { + return this.functionField; + } + set { + this.functionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string EventCategory { + get { + return this.eventCategoryField; + } + set { + this.eventCategoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBindDataSourceRef { + + private string refField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Ref { + get { + return this.refField; + } + set { + this.refField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class propertiesType { + + private propertiesTypeProperty[] propertyField; + + private string nameField; + + private string displayNameField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Property")] + public propertiesTypeProperty[] Property { + get { + return this.propertyField; + } + set { + this.propertyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class propertiesTypeProperty { + + private string nameField; + + private string designerTypeField; + + private string displayNameField; + + private string descriptionField; + + private string typeFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DesignerType { + get { + return this.designerTypeField; + } + set { + this.designerTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeFrom { + get { + return this.typeFromField; + } + set { + this.typeFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class dataSourceType { + + private dataSourceTypeSchemaSource schemaSourceField; + + private dataSourceTypeEvaluation evaluationField; + + private string internalNameField; + + private string nameField; + + private string namePropertyField; + + /// + public dataSourceTypeSchemaSource SchemaSource { + get { + return this.schemaSourceField; + } + set { + this.schemaSourceField = value; + } + } + + /// + public dataSourceTypeEvaluation Evaluation { + get { + return this.evaluationField; + } + set { + this.evaluationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName { + get { + return this.internalNameField; + } + set { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string NameProperty { + get { + return this.namePropertyField; + } + set { + this.namePropertyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSource { + + private object itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ContentType", typeof(dataSourceTypeSchemaSourceContentType))] + [System.Xml.Serialization.XmlElementAttribute("Dictionary", typeof(dataSourceTypeSchemaSourceDictionary))] + [System.Xml.Serialization.XmlElementAttribute("Fields", typeof(dataSourceTypeSchemaSourceFields))] + [System.Xml.Serialization.XmlElementAttribute("NestedInitiationFieldNodes", typeof(object))] + public object Item { + get { + return this.itemField; + } + set { + this.itemField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceContentType { + + private string iDFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string IDFrom { + get { + return this.iDFromField; + } + set { + this.iDFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceDictionary { + + private string valueFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ValueFrom { + get { + return this.valueFromField; + } + set { + this.valueFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFields { + + private dataSourceTypeSchemaSourceFieldsField[] fieldField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Field")] + public dataSourceTypeSchemaSourceFieldsField[] Field { + get { + return this.fieldField; + } + set { + this.fieldField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFieldsField { + + private dataSourceTypeSchemaSourceFieldsFieldCHOICE[] cHOICESField; + + private string nameField; + + private string displayNameField; + + private string typeField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("CHOICE", IsNullable=false)] + public dataSourceTypeSchemaSourceFieldsFieldCHOICE[] CHOICES { + get { + return this.cHOICESField; + } + set { + this.cHOICESField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeSchemaSourceFieldsFieldCHOICE { + + private string displayNameField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluation { + + private object itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ActivitySource", typeof(dataSourceTypeEvaluationActivitySource))] + [System.Xml.Serialization.XmlElementAttribute("HashtableSource", typeof(dataSourceTypeEvaluationHashtableSource))] + public object Item { + get { + return this.itemField; + } + set { + this.itemField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluationActivitySource { + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class dataSourceTypeEvaluationHashtableSource { + + private string hashtableFromField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string HashtableFrom { + get { + return this.hashtableFromField; + } + set { + this.hashtableFromField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class defaultElementType { + + private ruleDesignerType ruleDesignerField; + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class ruleDesignerTypeFieldBindOption { + + private string nameField; + + private string valueField; + + private string typeFilterField; + + private string unaryHidesField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeFilter { + get { + return this.typeFilterField; + } + set { + this.typeFilterField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string UnaryHides { + get { + return this.unaryHidesField; + } + set { + this.unaryHidesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum ruleDesignerTypeFieldBindDesignerType { + + /// + AddPermission, + + /// + Assignment, + + /// + Bool, + + /// + CheckPermission, + + /// + ChooseDoclibItem, + + /// + ChooseListItem, + + /// + ChooseListWorkflow, + + /// + ChooseSiteWorkflow, + + /// + CompositeTaskAction, + + /// + CreateListItem, + + /// + DataSourceFieldNames, + + /// + DataSourceValues, + + /// + Date, + + /// + Dependent, + + /// + Dictionary, + + /// + DocLibNames, + + /// + Dropdown, + + /// + EnterpriseProjectType, + + /// + EventDropdown, + + /// + Email, + + /// + FieldNames, + + /// + Float, + + /// + Hyperlink, + + /// + Integer, + + /// + ListItemEvent, + + /// + ListNames, + + /// + Operator, + + /// + ParameterNames, + + /// + Person, + + /// + ProjectFields, + + /// + PropertyGrid, + + /// + RemovePermission, + + /// + ReplacePermission, + + /// + RestCall, + + /// + SinglePerson, + + /// + SingleTaskAction, + + /// + Stages, + + /// + StatusDropdown, + + /// + StringBuilder, + + /// + Survey, + + /// + TaskSummary, + + /// + Text, + + /// + TextBox, + + /// + TextArea, + + /// + TextOnly, + + /// + UpdateListItem, + + /// + WorkflowParameters, + + /// + WritableFieldNames, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsDefaultItemKeyType { + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Guid")] + SystemGuid, + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Int32")] + SystemInt32, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoConditionsCondition { + + private ruleDesignerType ruleDesignerField; + + private parametersTypeParameter[] parametersField; + + private WorkflowInfoConditionsConditionType typeField; + + private bool typeFieldSpecified; + + private string nameField; + + private appliesToTypes appliesToField; + + private bool usesCurrentItemField; + + private bool requiresPWAField; + + private WorkflowInfoConditionsConditionItemKeyType itemKeyTypeField; + + private string functionNameField; + + private string assemblyField; + + private string classNameField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + private string shapeImageUrlField; + + public WorkflowInfoConditionsCondition() { + this.usesCurrentItemField = false; + this.requiresPWAField = false; + this.itemKeyTypeField = WorkflowInfoConditionsConditionItemKeyType.SystemInt32; + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public parametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public WorkflowInfoConditionsConditionType Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool TypeSpecified { + get { + return this.typeFieldSpecified; + } + set { + this.typeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool UsesCurrentItem { + get { + return this.usesCurrentItemField; + } + set { + this.usesCurrentItemField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool RequiresPWA { + get { + return this.requiresPWAField; + } + set { + this.requiresPWAField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(WorkflowInfoConditionsConditionItemKeyType.SystemInt32)] + public WorkflowInfoConditionsConditionItemKeyType ItemKeyType { + get { + return this.itemKeyTypeField; + } + set { + this.itemKeyTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FunctionName { + get { + return this.functionNameField; + } + set { + this.functionNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ShapeImageUrl { + get { + return this.shapeImageUrlField; + } + set { + this.shapeImageUrlField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class parametersTypeParameter { + + private string nameField; + + private string typeField; + + private parametersTypeParameterDirection directionField; + + private string descriptionField; + + private parametersTypeParameterDesignerType designerTypeField; + + private bool designerTypeFieldSpecified; + + private bool showLookupForDropdownField; + + private string displayNameField; + + private string initialValueField; + + private string initialBindingField; + + private string eventCategoryField; + + public parametersTypeParameter() { + this.showLookupForDropdownField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parametersTypeParameterDirection Direction { + get { + return this.directionField; + } + set { + this.directionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parametersTypeParameterDesignerType DesignerType { + get { + return this.designerTypeField; + } + set { + this.designerTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool DesignerTypeSpecified { + get { + return this.designerTypeFieldSpecified; + } + set { + this.designerTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ShowLookupForDropdown { + get { + return this.showLookupForDropdownField; + } + set { + this.showLookupForDropdownField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InitialValue { + get { + return this.initialValueField; + } + set { + this.initialValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InitialBinding { + get { + return this.initialBindingField; + } + set { + this.initialBindingField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string EventCategory { + get { + return this.eventCategoryField; + } + set { + this.eventCategoryField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum parametersTypeParameterDirection { + + /// + In, + + /// + Out, + + /// + Optional, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum parametersTypeParameterDesignerType { + + /// + ContentType, + + /// + DataSourceFieldNames, + + /// + DataSourceValues, + + /// + Date, + + /// + Dependent, + + /// + DocLibNames, + + /// + Dropdown, + + /// + EventDropdown, + + /// + FieldNames, + + /// + Float, + + /// + HttpMethod, + + /// + Hide, + + /// + Integer, + + /// + ItemProperties, + + /// + ListItem, + + /// + ListNames, + + /// + ParameterNames, + + /// + Password, + + /// + Person, + + /// + SinglePerson, + + /// + Stages, + + /// + StatusDropdown, + + /// + StringBuilder, + + /// + TaskContentType, + + /// + TextArea, + + /// + TextBox, + + /// + WritableFieldNames, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsConditionType { + + /// + Advanced, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + public enum appliesToTypes { + + /// + none, + + /// + list, + + /// + doclib, + + /// + all, + + /// + displayonly, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoConditionsConditionItemKeyType { + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Guid")] + SystemGuid, + + /// + [System.Xml.Serialization.XmlEnumAttribute("System.Int32")] + SystemInt32, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActions { + + private defaultElementType defaultField; + + private WorkflowInfoActionsAction[] actionField; + + private string sequentialField; + + private string parallelField; + + /// + public defaultElementType Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Action")] + public WorkflowInfoActionsAction[] Action { + get { + return this.actionField; + } + set { + this.actionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Sequential { + get { + return this.sequentialField; + } + set { + this.sequentialField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Parallel { + get { + return this.parallelField; + } + set { + this.parallelField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsAction { + + private parametersTypeParameter[] parametersField; + + private ruleDesignerType ruleDesignerField; + + private dataSourceType[] dataSourcesField; + + private WorkflowInfoActionsActionModification[] modificationsField; + + private WorkflowInfoActionsActionActionVariables actionVariablesField; + + private WorkflowInfoActionsActionActionBody actionBodyField; + + private WorkflowInfoActionsActionActionConditions actionConditionsField; + + private string nameField; + + private string classNameField; + + private string idField; + + private string assemblyField; + + private string functionNameField; + + private string categoryField; + + private bool createsTaskField; + + private string createsInListField; + + private appliesToTypes appliesToField; + + private bool isErrorField; + + private bool listModerationField; + + private bool usesCurrentItemField; + + private bool requiresPWAField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + private WorkflowInfoActionsActionCreatedTaskFormType createdTaskFormTypeField; + + private bool createdTaskFormTypeFieldSpecified; + + private string @__SolutionIdField; + + private bool sandboxedFunctionField; + + private string shapeImageUrlField; + + public WorkflowInfoActionsAction() { + this.functionNameField = ""; + this.createsTaskField = false; + this.isErrorField = false; + this.listModerationField = false; + this.usesCurrentItemField = false; + this.requiresPWAField = false; + this.sandboxedFunctionField = false; + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public parametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DataSource", IsNullable=false)] + public dataSourceType[] DataSources { + get { + return this.dataSourcesField; + } + set { + this.dataSourcesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Modification", IsNullable=false)] + public WorkflowInfoActionsActionModification[] Modifications { + get { + return this.modificationsField; + } + set { + this.modificationsField = value; + } + } + + /// + public WorkflowInfoActionsActionActionVariables ActionVariables { + get { + return this.actionVariablesField; + } + set { + this.actionVariablesField = value; + } + } + + /// + public WorkflowInfoActionsActionActionBody ActionBody { + get { + return this.actionBodyField; + } + set { + this.actionBodyField = value; + } + } + + /// + public WorkflowInfoActionsActionActionConditions ActionConditions { + get { + return this.actionConditionsField; + } + set { + this.actionConditionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID { + get { + return this.idField; + } + set { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute("")] + public string FunctionName { + get { + return this.functionNameField; + } + set { + this.functionNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Category { + get { + return this.categoryField; + } + set { + this.categoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool CreatesTask { + get { + return this.createsTaskField; + } + set { + this.createsTaskField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string CreatesInList { + get { + return this.createsInListField; + } + set { + this.createsInListField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool IsError { + get { + return this.isErrorField; + } + set { + this.isErrorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ListModeration { + get { + return this.listModerationField; + } + set { + this.listModerationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool UsesCurrentItem { + get { + return this.usesCurrentItemField; + } + set { + this.usesCurrentItemField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool RequiresPWA { + get { + return this.requiresPWAField; + } + set { + this.requiresPWAField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public WorkflowInfoActionsActionCreatedTaskFormType CreatedTaskFormType { + get { + return this.createdTaskFormTypeField; + } + set { + this.createdTaskFormTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool CreatedTaskFormTypeSpecified { + get { + return this.createdTaskFormTypeFieldSpecified; + } + set { + this.createdTaskFormTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string @__SolutionId { + get { + return this.@__SolutionIdField; + } + set { + this.@__SolutionIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool SandboxedFunction { + get { + return this.sandboxedFunctionField; + } + set { + this.sandboxedFunctionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ShapeImageUrl { + get { + return this.shapeImageUrlField; + } + set { + this.shapeImageUrlField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionModification { + + private string typeIdField; + + private string nameFormatField; + + private string formURNField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string TypeId { + get { + return this.typeIdField; + } + set { + this.typeIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string NameFormat { + get { + return this.nameFormatField; + } + set { + this.nameFormatField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FormURN { + get { + return this.formURNField; + } + set { + this.formURNField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionVariables { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionBody { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoActionsActionActionConditions { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum WorkflowInfoActionsActionCreatedTaskFormType { + + /// + DataCollectTask, + + /// + GroupAssignedTask, + + /// + TodoItemTask, + + /// + TaskProcess, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCompositeSteps { + + private WorkflowInfoCompositeStepsCompositeStep[] compositeStepField; + + /// + [System.Xml.Serialization.XmlElementAttribute("CompositeStep")] + public WorkflowInfoCompositeStepsCompositeStep[] CompositeStep { + get { + return this.compositeStepField; + } + set { + this.compositeStepField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCompositeStepsCompositeStep { + + private dataSourceType[] dataSourcesField; + + private string nameField; + + private string classNameField; + + private string assemblyField; + + private appliesToTypes appliesToField; + + private string requiredInvocationTagsField; + + private string invocationTagsField; + + private string prohibitedInvocationTagsField; + + private string prohibitedDirectParentInvocationTagsField; + + private string orderField; + + private string descriptionField; + + public WorkflowInfoCompositeStepsCompositeStep() { + this.orderField = "0"; + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DataSource", IsNullable=false)] + public dataSourceType[] DataSources { + get { + return this.dataSourcesField; + } + set { + this.dataSourcesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public appliesToTypes AppliesTo { + get { + return this.appliesToField; + } + set { + this.appliesToField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RequiredInvocationTags { + get { + return this.requiredInvocationTagsField; + } + set { + this.requiredInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InvocationTags { + get { + return this.invocationTagsField; + } + set { + this.invocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedInvocationTags { + get { + return this.prohibitedInvocationTagsField; + } + set { + this.prohibitedInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProhibitedDirectParentInvocationTags { + get { + return this.prohibitedDirectParentInvocationTagsField; + } + set { + this.prohibitedDirectParentInvocationTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="nonNegativeInteger")] + [System.ComponentModel.DefaultValueAttribute("0")] + public string Order { + get { + return this.orderField; + } + set { + this.orderField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoVariableTypes { + + private WorkflowInfoVariableTypesVariableType[] variableTypeField; + + /// + [System.Xml.Serialization.XmlElementAttribute("VariableType")] + public WorkflowInfoVariableTypesVariableType[] VariableType { + get { + return this.variableTypeField; + } + set { + this.variableTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoVariableTypesVariableType { + + private string typeField; + + private string displayNameField; + + private string assemblyField; + + private bool defaultField; + + private bool itemIdTypeField; + + private bool hiddenField; + + public WorkflowInfoVariableTypesVariableType() { + this.defaultField = false; + this.itemIdTypeField = false; + this.hiddenField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Default { + get { + return this.defaultField; + } + set { + this.defaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ItemIdType { + get { + return this.itemIdTypeField; + } + set { + this.itemIdTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool Hidden { + get { + return this.hiddenField; + } + set { + this.hiddenField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoAssemblyRedirects { + + private WorkflowInfoAssemblyRedirectsAssemblyRedirect[] assemblyRedirectField; + + /// + [System.Xml.Serialization.XmlElementAttribute("AssemblyRedirect")] + public WorkflowInfoAssemblyRedirectsAssemblyRedirect[] AssemblyRedirect { + get { + return this.assemblyRedirectField; + } + set { + this.assemblyRedirectField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoAssemblyRedirectsAssemblyRedirect { + + private string fromField; + + private string toField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string From { + get { + return this.fromField; + } + set { + this.fromField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string To { + get { + return this.toField; + } + set { + this.toField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoCoercion { + + private coercionParametersTypeParameter[] parametersField; + + private string nameField; + + private string assemblyField; + + private string displayNameField; + + private bool catchAllField; + + private string rankDefaultField; + + private string sourceTypeField; + + private string sourceFieldTypeField; + + private string destinationTypeField; + + private string destinationFieldTypeField; + + private string classNameField; + + private string idField; + + private string sourcePropertyField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public coercionParametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Assembly { + get { + return this.assemblyField; + } + set { + this.assemblyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool CatchAll { + get { + return this.catchAllField; + } + set { + this.catchAllField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType="integer")] + public string RankDefault { + get { + return this.rankDefaultField; + } + set { + this.rankDefaultField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceType { + get { + return this.sourceTypeField; + } + set { + this.sourceTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceFieldType { + get { + return this.sourceFieldTypeField; + } + set { + this.sourceFieldTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DestinationType { + get { + return this.destinationTypeField; + } + set { + this.destinationTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DestinationFieldType { + get { + return this.destinationFieldTypeField; + } + set { + this.destinationFieldTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ClassName { + get { + return this.classNameField; + } + set { + this.classNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Id { + get { + return this.idField; + } + set { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SourceProperty { + get { + return this.sourcePropertyField; + } + set { + this.sourcePropertyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class coercionParametersTypeParameter { + + private coercionParametersTypeParameterActivityBody activityBodyField; + + private string nameField; + + private string typeField; + + private string valueField; + + /// + public coercionParametersTypeParameterActivityBody ActivityBody { + get { + return this.activityBodyField; + } + set { + this.activityBodyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class coercionParametersTypeParameterActivityBody { + + private System.Xml.XmlElement[] anyField; + + /// + [System.Xml.Serialization.XmlAnyElementAttribute()] + public System.Xml.XmlElement[] Any { + get { + return this.anyField; + } + set { + this.anyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoEvent { + + private string nameField; + + private string displayNameField; + + private string eventGroupField; + + private string categoryField; + + private string rankDefaultField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DisplayName { + get { + return this.displayNameField; + } + set { + this.displayNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string EventGroup { + get { + return this.eventGroupField; + } + set { + this.eventGroupField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Category { + get { + return this.categoryField; + } + set { + this.categoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RankDefault { + get { + return this.rankDefaultField; + } + set { + this.rankDefaultField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public partial class WorkflowInfoFlow { + + private ruleDesignerType ruleDesignerField; + + private parametersTypeParameter[] parametersField; + + private string nameField; + + private string categoryField; + + /// + public ruleDesignerType RuleDesigner { + get { + return this.ruleDesignerField; + } + set { + this.ruleDesignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Parameter", IsNullable=false)] + public parametersTypeParameter[] Parameters { + get { + return this.parametersField; + } + set { + this.parametersField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Category { + get { + return this.categoryField; + } + set { + this.categoryField = value; + } + } + } +} diff --git a/Common/sp2013wfmodel.xml b/Common/sp2013wfmodel.xml new file mode 100644 index 0000000..7936fa5 --- /dev/null +++ b/Common/sp2013wfmodel.xml @@ -0,0 +1,1919 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Common/sp2013wfmodel.xsd b/Common/sp2013wfmodel.xsd new file mode 100644 index 0000000..6cd3d3c --- /dev/null +++ b/Common/sp2013wfmodel.xsd @@ -0,0 +1,552 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Discovery/Discovery.csproj b/Discovery/Discovery.csproj new file mode 100644 index 0000000..832db75 --- /dev/null +++ b/Discovery/Discovery.csproj @@ -0,0 +1,222 @@ + + + + + Debug + AnyCPU + {66180571-9292-4411-8B01-B31DCE2CC0E8} + Library + Properties + Discovery + Discovery + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\AngleSharp.0.9.9\lib\net45\AngleSharp.dll + + + ..\packages\Microsoft.Azure.ActiveDirectory.GraphClient.2.1.0\lib\portable-net4+sl5+win+wpa+wp8\Microsoft.Azure.ActiveDirectory.GraphClient.dll + + + ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll + + + ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll + + + ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll + + + ..\packages\Microsoft.Graph.1.9.0\lib\net45\Microsoft.Graph.dll + + + ..\packages\Microsoft.Graph.Core.1.9.0\lib\net45\Microsoft.Graph.Core.dll + + + ..\packages\Microsoft.IdentityModel.7.0.0\lib\net35\microsoft.identitymodel.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.5.2.4\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.5.2.4\lib\net451\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.5.2.4\lib\net451\Microsoft.IdentityModel.Tokens.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.Policy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.TranslationServices.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.SharePoint.Tools.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Online.SharePoint.Client.Tenant.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.ProjectServer.Client.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.DocumentManagement.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Publishing.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.Windows.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.Applications.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Taxonomy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.UserProfiles.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.WorkflowServices.dll + + + ..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\SharePointPnPCoreOnline.3.24.2008.1\lib\net461\OfficeDevPnP.Core.dll + + + ..\packages\SharePointPnP.IdentityModel.Extensions.1.2.4\lib\net45\SharePointPnP.IdentityModel.Extensions.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.5.2.4\lib\net451\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Net.Http.4.3.1\lib\net46\System.Net.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + + ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + + + + + + + + + + + + + + + + {04a36617-4353-4779-92f9-36baffe6a5f6} + Common + + + + + + + + \ No newline at end of file diff --git a/Discovery/DiscoveryBase.cs b/Discovery/DiscoveryBase.cs new file mode 100644 index 0000000..659f482 --- /dev/null +++ b/Discovery/DiscoveryBase.cs @@ -0,0 +1,66 @@ +using Microsoft.SharePoint.Client; +using System; + + +namespace Discovery +{ + public abstract class DiscoveryBase + { + private string url; + private string siteColUrl; + + /// + /// Base constructor + /// + /// Url of the current web + /// url of the current site collection + public DiscoveryBase(string url, string siteColUrl) + { + this.url = url; + this.siteColUrl = siteColUrl; + } + + /// + /// Scan start time + /// + public DateTime StartTime { get; set; } + + /// + /// Scan stop time + /// + public DateTime StopTime { get; set; } + + /// + /// Site collection url being scanned + /// + public string SiteCollectionUrl + { + get + { + return this.siteColUrl; + } + } + + /// + /// Site being scanned + /// + public string SiteUrl + { + get + { + return this.url; + } + } + + /// + /// Virtual Analyze method + /// + /// ClientContext of the web to be analyzed + /// Duration of the analysis + public virtual TimeSpan Analyze(ClientContext cc) + { + this.StartTime = DateTime.Now; + return new TimeSpan(); + } + } +} diff --git a/Discovery/Properties/AssemblyInfo.cs b/Discovery/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..70350e9 --- /dev/null +++ b/Discovery/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Discovery")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Discovery")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("66180571-9292-4411-8b01-b31dce2cc0e8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Discovery/Scan.cs b/Discovery/Scan.cs new file mode 100644 index 0000000..b6ef9ca --- /dev/null +++ b/Discovery/Scan.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discovery +{ + public class Scan + { + public string SiteURL { get; set; } + public string SiteColUrl { get; set; } + } +} diff --git a/Discovery/SiteScanResult.cs b/Discovery/SiteScanResult.cs new file mode 100644 index 0000000..aae63ae --- /dev/null +++ b/Discovery/SiteScanResult.cs @@ -0,0 +1,620 @@ +using OfficeDevPnP.Core.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discovery +{ + public class SiteScanResult : Scan + { + /// + /// Web template (e.g. STS#0) + /// + public string WebTemplate { get; set; } + + /// + /// Modern lists was disabled due to the site scoped blocking feature + /// + public bool ModernListSiteBlockingFeatureEnabled { get; set; } + + /// + /// Does this site collection have sub sites? + /// + public bool SubSites { get; set; } + + /// + /// Does this web have a modern home page? + /// + public bool ModernHomePage { get; set; } + + /// + /// Is this the root site of the tenant + /// + public bool IsRootSite { get; set; } + + /// + /// Does this site collection have sub sites with broken permission inheritance + /// + public bool SubSitesWithBrokenPermissionInheritance { get; set; } + + /// + /// Is the publishing web feature enabled? + /// + public bool WebPublishingFeatureEnabled { get; set; } + /// + /// Does this site collection have the site pusblishing feature enabled? + /// + public bool SitePublishingFeatureEnabled { get; set; } + + /// + /// Are there publishing pages used in any of the webs in this site? + /// + public bool PublishingPagesUsed { get; set; } + /// + /// Modern page feature was disabled + /// + public bool ModernPageWebFeatureDisabled { get; set; } + + /// + /// Was the modern page feature enabled + /// + public bool ModernPageFeatureWasEnabledBySPO { get; set; } + + /// + /// Modern lists was disabled due to the web scoped blocking feature + /// + public bool ModernListWebBlockingFeatureEnabled { get; set; } + + /// + /// This site uses a non OOB master page + /// + public bool MasterPage { get; set; } + + /// + /// This site uses alternate css + /// + public bool AlternateCSS { get; set; } + + /// + /// User custom actions which are ignored on modern UI + /// + ///public List SiteUserCustomActions { get; set; } + + /// + /// User custom actions which are ignored on modern UI + /// + //public List WebUserCustomActions { get; set; } + + /// + /// Site administrators + /// + public List Admins { get; set; } + /// + /// Site owners + /// + public List Owners { get; set; } + + /// + /// Site members + /// + public List Members { get; set; } + + /// + /// Site visitors + /// + public List Visitors { get; set; } + + /// + /// Is the everyone or every one except external users claim used to directly grant access + /// + public bool EveryoneClaimsGranted { get; set; } + + /// + /// ID of the connected Office 365 group + /// + public Guid Office365GroupId { get; set; } + + /// + /// Is there a Teams team connected to the same Office 365 group as this site collection + /// + public bool? HasTeamsTeam { get; set; } + + /// + /// Site sharing capabilities + /// + public string SharingCapabilities { get; set; } + + /// + /// Views in the last 14 days for this site + /// + public int ViewsRecent { get; set; } + + /// + /// Number of unique users that viewed this site in the last 14 days + /// + public int ViewsRecentUniqueUsers { get; set; } + + /// + /// Total number of views for this site + /// + public int ViewsLifeTime { get; set; } + + /// + /// Total number of unique visitors for this site + /// + public int ViewsLifeTimeUniqueUsers { get; set; } + + /// + /// Site collection ID + /// + public string SiteId { get; set; } + + /// + /// Search center url for the site + /// + public string SearchCenterUrl { get; set; } + + #region Cloning + /// + /// Clone this object, keep in sync when new props are added to this class + /// + /// + public SiteScanResult Clone() + { + return new SiteScanResult() + { + SiteColUrl = this.SiteColUrl, + SiteURL = this.SiteURL, + ModernListSiteBlockingFeatureEnabled = this.ModernListSiteBlockingFeatureEnabled, + ModernHomePage = this.ModernHomePage, + IsRootSite = this.IsRootSite, + SitePublishingFeatureEnabled = this.SitePublishingFeatureEnabled, + WebPublishingFeatureEnabled = this.WebPublishingFeatureEnabled, + PublishingPagesUsed = this.PublishingPagesUsed, + ModernPageWebFeatureDisabled = this.ModernPageWebFeatureDisabled, + ModernPageFeatureWasEnabledBySPO = this.ModernPageFeatureWasEnabledBySPO, + ModernListWebBlockingFeatureEnabled = this.ModernListWebBlockingFeatureEnabled, + WebTemplate = this.WebTemplate, + SubSites = this.SubSites, + SubSitesWithBrokenPermissionInheritance = this.SubSitesWithBrokenPermissionInheritance, + MasterPage = this.MasterPage, + //SiteUserCustomActions = this.SiteUserCustomActions, + // WebUserCustomActions = this.WebUserCustomActions, + AlternateCSS = this.AlternateCSS, + Admins = this.Admins, + Owners = this.Owners, + Members = this.Members, + Visitors = this.Visitors, + EveryoneClaimsGranted = this.EveryoneClaimsGranted, + Office365GroupId = this.Office365GroupId, + HasTeamsTeam = this.HasTeamsTeam, + SharingCapabilities = this.SharingCapabilities, + ViewsLifeTime = this.ViewsLifeTime, + ViewsLifeTimeUniqueUsers = this.ViewsLifeTimeUniqueUsers, + ViewsRecent = this.ViewsRecent, + ViewsRecentUniqueUsers = this.ViewsRecentUniqueUsers, + SiteId = this.SiteId, + SearchCenterUrl = this.SearchCenterUrl + }; + } + #endregion + + #region Groupify readiness + /// + /// Lists the reasons for not (yet) groupifying this site + /// + /// List of groupify blockers + public List GroupifyBlockers() + { + List groupifyBlockReasons = new List(); + + // Don't use this as a blocker as it overlaps with the publishingFeature blocker and as such is confusing + //var blocker = SiteTemplateCheck(true); + //if (!String.IsNullOrEmpty(blocker)) + //{ + // groupifyBlockReasons.Add(blocker); + //} + + if (Office365GroupId != Guid.Empty) + { + groupifyBlockReasons.Add("SiteHasOffice365Group"); + } + + if ((SitePublishingFeatureEnabled || WebPublishingFeatureEnabled) && DefineAsPublishingPortal()) + { + groupifyBlockReasons.Add("PublishingFeatureEnabled"); + } + + // We prevent a root site from being group connected + if (IsRootSite) + { + groupifyBlockReasons.Add("IsTenantRootSite"); + } + + return groupifyBlockReasons; + } + + /// + /// Lists the reasons for not (yet) groupifying this site + /// + /// List of groupify warnings + public List GroupifyWarnings(string everyoneClaim, string everyoneExceptExternalUsersClaim) + { + List groupifyWarningReasons = new List(); + + var permissionWarnings = this.PermissionModel(everyoneClaim, everyoneExceptExternalUsersClaim); + if (permissionWarnings.Item2 != null && permissionWarnings.Item2.Count > 0) + { + groupifyWarningReasons.Add("PermissionWarnings"); + } + + if (SubSites) + { + groupifyWarningReasons.Add("SiteHasSubSites"); + } + + if (this.ModernWarnings().Count > 0) + { + groupifyWarningReasons.Add("ModernUIWarnings"); + } + + var warning = SiteTemplateCheck(false); + if (!String.IsNullOrEmpty(warning)) + { + groupifyWarningReasons.Add(warning); + } + + return groupifyWarningReasons; + } + + private bool DefineAsPublishingPortal() + { + // Check web template + if (WebTemplate.Equals("BICENTERSITE#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("BLANKINTERNET#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("ENTERWIKI#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("SRCHCEN#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("SRCHCENTERLITE#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("POINTPUBLISHINGHUB#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("POINTPUBLISHINGTOPIC#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("CMSPUBLISHING#0", StringComparison.InvariantCultureIgnoreCase)) + { + return true; + } + + // Check publishing page library usage + if (PublishingPagesUsed) + { + return true; + } + + return false; + } + + private string SiteTemplateCheck(bool blocker) + { + if (WebTemplate.Equals("STS#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("DEV#0", StringComparison.InvariantCultureIgnoreCase)) + { + // We're good with these + return null; + } + else if (WebTemplate.Equals("BICENTERSITE#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("BLANKINTERNET#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("ENTERWIKI#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("SRCHCEN#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("SRCHCENTERLITE#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("POINTPUBLISHINGHUB#0", StringComparison.InvariantCultureIgnoreCase) || + WebTemplate.Equals("POINTPUBLISHINGTOPIC#0", StringComparison.InvariantCultureIgnoreCase) || WebTemplate.Equals("CMSPUBLISHING#0", StringComparison.InvariantCultureIgnoreCase) || + SiteColUrl.EndsWith("/sites/contenttypehub", StringComparison.InvariantCultureIgnoreCase)) + { + // Block these + if (blocker) + { + return "IncompatibleWebTemplate"; + } + } + else + { + // Provide a warning + if (!blocker) + { + return "DefaultHomePageImpacted"; + } + } + + return null; + } + + /// + /// Proposed permission model and permission delta for the created group + /// + /// PRIVATE or PUBLIC + public Tuple> PermissionModel(string claim1, string claim2) + { + // Do we have a public claim in Members, Owners or Admins? ==> PUBLIC site + bool hasPublicClaimWithEditPermissions = HasClaim(Admins, claim1, claim2); + if (!hasPublicClaimWithEditPermissions) + { + hasPublicClaimWithEditPermissions = HasClaim(Owners, claim1, claim2); + } + if (!hasPublicClaimWithEditPermissions) + { + hasPublicClaimWithEditPermissions = HasClaim(Members, claim1, claim2); + } + + List permissionDelta = new List(); + // Potential issue 1: private group, but public claim has been used outside of Site Admins, Owners, Members + //if (EveryoneClaimsGranted && !hasPublicClaimWithEditPermissions) + //{ + // permissionDelta.Add("PrivateGroupButEveryoneUsedOutsideOfAdminOwnerMemberGroups"); + //} + + //// Potential issue 2: public claim in visitors group will lead to private site while still allow everyone view access + //if (HasClaim(Visitors, claim1, claim2) && !hasPublicClaim) + //{ + // permissionDelta.Add("PrivateGroupButEveryoneInVisitors"); + //} + + // Potential issue 3: external sharing disabled, but will be possible by default on groups + if (!String.IsNullOrEmpty(SharingCapabilities)) + { + if (SharingCapabilities.Equals("Disabled", StringComparison.InvariantCultureIgnoreCase)) + { + permissionDelta.Add("SharingDisabledForSiteButGroupWillAllowExternalSharing"); + } + } + + // Potential issue 4: sub site has broken permission inheritance + if (SubSitesWithBrokenPermissionInheritance) + { + permissionDelta.Add("SubSiteWithBrokenPermissionInheritance"); + } + + // Potential issue 5: ad groups used which will not expand into the Office 365 group + if (ContainsADGroup(Owners) || ContainsADGroup(Admins) || ContainsADGroup(Members)) + { + permissionDelta.Add("ADGroupWillNotBeExpanded"); + } + + return new Tuple>(hasPublicClaimWithEditPermissions ? "PUBLIC" : "PRIVATE", permissionDelta); + } + + /// + /// Lists the modern UI disablements + /// + /// List of modern UI disablements + public List ModernWarnings() + { + List modernWarnings = new List(); + + if (ModernPageWebFeatureDisabled) + { + modernWarnings.Add("ModernPageFeatureDisabled"); + } + if (ModernListSiteBlockingFeatureEnabled) + { + modernWarnings.Add("ModernListsBlockedAtSiteLevel"); + } + if (ModernListWebBlockingFeatureEnabled) + { + modernWarnings.Add("ModernListsBlockedAtWebLevel"); + } + if (MasterPage) + { + modernWarnings.Add("MasterPageUsed"); + } + if (AlternateCSS) + { + modernWarnings.Add("AlternateCSSUsed"); + } + /*if ((SiteUserCustomActions != null && SiteUserCustomActions.Count > 0) || (WebUserCustomActions != null && WebUserCustomActions.Count > 0)) + { + modernWarnings.Add("UserCustomActionUsed"); + }*/ + if (SitePublishingFeatureEnabled || WebPublishingFeatureEnabled) + { + modernWarnings.Add("PublishingFeatureEnabled"); + } + + return modernWarnings; + } + + #endregion + + #region Security helpers + /// + /// Does the given user list contain the given claim + /// + /// List of users + /// Claim to check + /// True if found, false otherwise + public bool HasClaim(List users, string claim) + { + if (users == null) + { + return false; + } + + return users.Where(p => p.LoginName.ToLower() == claim.ToLower()).Any(); + } + + /// + /// Does the given user list contain any of the 2 given claims + /// + /// List of users + /// Claim to check + /// Claim to check + /// True if found, false otherwise + public bool HasClaim(List users, string claim1, string claim2) + { + if (users == null) + { + return false; + } + + return users.Where(p => p.LoginName.ToLower() == claim1.ToLower() || p.LoginName.ToLower() == claim2.ToLower()).Any(); + } + + /// + /// Is the given claim used for this site? + /// + /// Claim to check + /// True if found, false otherwise + public bool HasClaim(string claim) + { + if (HasClaim(Admins, claim)) + { + return true; + } + if (HasClaim(Owners, claim)) + { + return true; + } + if (HasClaim(Members, claim)) + { + return true; + } + if (HasClaim(Visitors, claim)) + { + return true; + } + + return false; + } + + /// + /// Is one of the given claims used for this site? + /// + /// Claim to check + /// Claim to check + /// True if found, false otherwise + public bool HasClaim(string claim1, string claim2) + { + if (HasClaim(Admins, claim1, claim2)) + { + return true; + } + if (HasClaim(Owners, claim1, claim2)) + { + return true; + } + if (HasClaim(Members, claim1, claim2)) + { + return true; + } + if (HasClaim(Visitors, claim1, claim2)) + { + return true; + } + + return false; + } + + /// + /// Does this user list contain a AD group? + /// + /// List of users + /// True if it contains an AD group, false otherwise + public bool ContainsADGroup(List users) + { + if (users == null) + { + return false; + } + + return users.Where(p => p.LoginName.ToLower().StartsWith("c:0-.f|rolemanager|s-")).Any(); + } + + /// + /// Does this site use AD groups to grant permissions + /// + /// True or false + public bool ContainsADGroup() + { + if (ContainsADGroup(Admins)) + { + return true; + } + if (ContainsADGroup(Owners)) + { + return true; + } + if (ContainsADGroup(Members)) + { + return true; + } + if (ContainsADGroup(Visitors)) + { + return true; + } + + return false; + } + #endregion + + #region output formatting + public string IsTeamified() + { + if (this.HasTeamsTeam.HasValue) + { + if (this.HasTeamsTeam.Value) + { + return "True"; + } + else + { + return "False"; + } + } + else + { + return ""; + } + } + + public static string FormatUserList(List users, string everyoneClaim = null, string everyoneExceptExternalUsersClaim = null) + { + string userList = ""; + + // Bail out if we've no data + if (users == null || users.Count == 0) + { + return userList; + } + + foreach (var user in users) + { + string userToAdd = (!string.IsNullOrEmpty(user.Email) && user.Email.Contains("@")) ? user.Email : user.LoginName; + + if (!userToAdd.Equals("SHAREPOINT\\system", StringComparison.InvariantCultureIgnoreCase)) + { + if (!string.IsNullOrEmpty(everyoneClaim) && userToAdd.Equals(everyoneClaim, StringComparison.InvariantCultureIgnoreCase)) + { + userToAdd = "{everyone}"; + } + else if (!string.IsNullOrEmpty(everyoneExceptExternalUsersClaim) && userToAdd.Equals(everyoneExceptExternalUsersClaim, StringComparison.InvariantCultureIgnoreCase)) + { + userToAdd = "{everyoneexceptexternalusers}"; + } + + userList = userList + (!string.IsNullOrEmpty(userList) ? $",{userToAdd}" : $"{userToAdd}"); + } + } + return userList; + } + + public static string FormatList(List list) + { + string formattedList = ""; + if (list == null || list.Count == 0) + { + return ""; + } + + foreach (var item in list) + { + formattedList = formattedList + (!string.IsNullOrEmpty(formattedList) ? $",{item}" : $"{item}"); + } + + return formattedList; + } + + #endregion + + } +} diff --git a/Discovery/WFDiscovery.cs b/Discovery/WFDiscovery.cs new file mode 100644 index 0000000..443679c --- /dev/null +++ b/Discovery/WFDiscovery.cs @@ -0,0 +1,781 @@ +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Workflow; +using Microsoft.SharePoint.Client.WorkflowServices; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using Common; +using System.Data; + +namespace Discovery +{ + public class WorkflowDiscovery + { + private string url; + private string siteColUrl; + + /// + /// Site collection url being scanned + /// + public string SiteCollectionUrl + { + get + { + return this.siteColUrl; + } + } + + /// + /// Site being scanned + /// + public string SiteUrl + { + get + { + return this.url; + } + } + + private class SP2010WorkFlowAssociation + { + public string Scope { get; set; } + public WorkflowAssociation WorkflowAssociation { get; set; } + public List AssociatedList { get; set; } + public ContentType AssociatedContentType { get; set; } + } + + private static readonly string[] OOBWorkflowIDStarts = new string[] + { + "e43856d2-1bb4-40ef-b08b-016d89a00", // Publishing approval + "3bfb07cb-5c6a-4266-849b-8d6711700409", // Collect feedback - 2010 + "46c389a4-6e18-476c-aa17-289b0c79fb8f", // Collect feedback + "77c71f43-f403-484b-bcb2-303710e00409", // Collect signatures - 2010 + "2f213931-3b93-4f81-b021-3022434a3114", // Collect signatures + "8ad4d8f0-93a7-4941-9657-cf3706f00409", // Approval - 2010 + "b4154df4-cc53-4c4f-adef-1ecf0b7417f6", // Translation management + "c6964bff-bf8d-41ac-ad5e-b61ec111731a", // Three state + "c6964bff-bf8d-41ac-ad5e-b61ec111731c", // Approval + "dd19a800-37c1-43c0-816d-f8eb5f4a4145", // Disposition approval + }; + + List sp2010WorkflowAssociations = new List(20); + private List workflowList; + + + + + + //public void DiscoverWorkflows(ClientContext cc, DataTable dt, string folderPath) + public void DiscoverWorkflows(ClientContext cc, DataTable dt) + + { + try + { + //List wfLastRun = new List; + + Web web = cc.Web; + + // Pre-load needed properties in a single call + cc.Load(web, w => w.Id, w => w.ServerRelativeUrl, w => w.Url, w => w.WorkflowTemplates, w => w.WorkflowAssociations); + cc.Load(web, p => p.ContentTypes.Include(ct => ct.WorkflowAssociations, ct => ct.Name, ct => ct.StringId)); + cc.Load(web, p => p.Lists.Include(li => li.Id, li => li.Title, li => li.Hidden, li => li.DefaultViewUrl, li => li.BaseTemplate, li => li.RootFolder.ServerRelativeUrl, li => li.ItemCount, li => li.WorkflowAssociations)); + /* + foreach (List list in web.Lists) + { + cc.Load(list, l => l.ContentTypes.Equals("Workflow History")); + } + foreach(WorkflowAssociation wf in web.WorkflowAssociations) + { + cc.Load + }*/ + cc.ExecuteQuery(); + + //yList.Each(x => { x.Enabled = false; }); + //w => w.WorkflowAssociations.Each(x => x.HistoryListTitle) + var lists = web.Lists; + + + + #region Site, reusable and list level 2013 workflow + // ******************************************* + // Site, reusable and list level 2013 workflow + // ******************************************* + + // Retrieve the 2013 site level workflow definitions (including unpublished ones) + WorkflowDefinition[] siteWFDefinitions = null; + // Retrieve the 2013 site level workflow subscriptions + WorkflowSubscription[] siteWFSubscriptions = null; + Operations ops = new Operations(); + //ops.CreateDataTableColumns(dt); + DataRow row = dt.NewRow(); + try + { + var servicesManager = new WorkflowServicesManager(web.Context, web); + var deploymentService = servicesManager.GetWorkflowDeploymentService(); + var subscriptionService = servicesManager.GetWorkflowSubscriptionService(); + + var definitions = deploymentService.EnumerateDefinitions(false); + web.Context.Load(definitions); + + var subscriptions = subscriptionService.EnumerateSubscriptions(); + web.Context.Load(subscriptions); + //for each subscription + // Get History List => SubscriptionID, HstoryListID + //Load Hstory list Item where item = listitems[ListItems.Length - 1]["Occurred"] + + + web.Context.ExecuteQuery(); + + siteWFDefinitions = definitions.ToArray(); + siteWFSubscriptions = subscriptions.ToArray(); + } + catch (ServerException ex) + { + // If there is no workflow service present in the farm this method will throw an error. + // Swallow the exception + } + #endregion + + #region If SP2013 site scoped workflows are found + // We've found SP2013 site scoped workflows + if (siteWFDefinitions != null && siteWFDefinitions.Count() > 0) + { + foreach (var siteWFDefinition in siteWFDefinitions.Where(p => p.RestrictToType != null && (p.RestrictToType.Equals("site", StringComparison.InvariantCultureIgnoreCase) || p.RestrictToType.Equals("universal", StringComparison.InvariantCultureIgnoreCase)))) + { + // Check if this workflow is also in use + var siteWorkflowSubscriptions = siteWFSubscriptions.Where(p => p.DefinitionId.Equals(siteWFDefinition.Id)); + + // Perform workflow analysis + var workFlowAnalysisResult = WorkflowManager.Instance.ParseWorkflowDefinition(siteWFDefinition.Xaml, WorkflowTypes.SP2013); + //if (siteWFDefinition.Xaml != null) + //{ + // ops.SaveXamlFile(siteWFDefinition.Xaml, web, siteWFDefinition.DisplayName, "site", folderPath); + //} + var workFlowTriggerAnalysisResult = WorkflowManager.Instance.ParseWorkflowTriggers(GetWorkflowPropertyBool(siteWFDefinition.Properties, "SPDConfig.StartOnCreate"), GetWorkflowPropertyBool(siteWFDefinition.Properties, "SPDConfig.StartOnChange"), GetWorkflowPropertyBool(siteWFDefinition.Properties, "SPDConfig.StartManually")); + + if (siteWorkflowSubscriptions.Count() > 0) + { + foreach (var siteWorkflowSubscription in siteWorkflowSubscriptions) + { + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = "", + ListUrl = "", + ContentTypeId = "", + ContentTypeName = "", + Version = "2013", + Scope = "Site", + RestrictToType = siteWFDefinition.RestrictToType, + DefinitionName = siteWFDefinition.DisplayName, + DefinitionDescription = siteWFDefinition.Description, + SubscriptionName = siteWorkflowSubscription.Name, + HasSubscriptions = true, + Enabled = siteWorkflowSubscription.Enabled, + DefinitionId = siteWFDefinition.Id, + IsOOBWorkflow = false, + SubscriptionId = siteWorkflowSubscription.Id, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + UnsupportedActionsInFlow = workFlowAnalysisResult?.UnsupportedActions, + CreatedBy = siteWFDefinition.Properties["vti_author"], + ModifiedBy = siteWFDefinition.Properties["ModifiedBy"], + UnsupportedActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.UnsupportedAccountCount : 0, + LastDefinitionEdit = GetWorkflowPropertyDateTime(siteWFDefinition.Properties, "Definition.ModifiedDateUTC"), + LastSubscriptionEdit = GetWorkflowPropertyDateTime(siteWorkflowSubscription.PropertyDefinitions, "SharePointWorkflowContext.Subscription.ModifiedDateUTC"), + }; + //Add admin owners + //TBD + //Create a data row function + ops.AddRowToDataTable(workflowScanResult, dt, "2013","Site", siteWFDefinition.DisplayName,siteWFDefinition.Id.ToString(), false, web); + + + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2013 site workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + else + { + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = "", + ListUrl = "", + ContentTypeId = "", + ContentTypeName = "", + Version = "2013", + Scope = "Site", + RestrictToType = siteWFDefinition.RestrictToType, + DefinitionName = siteWFDefinition.DisplayName, + DefinitionDescription = siteWFDefinition.Description, + SubscriptionName = "", + HasSubscriptions = false, + Enabled = false, + DefinitionId = siteWFDefinition.Id, + IsOOBWorkflow = false, + SubscriptionId = Guid.Empty, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UnsupportedActionsInFlow = workFlowAnalysisResult?.UnsupportedActions, + UnsupportedActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.UnsupportedAccountCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + LastDefinitionEdit = GetWorkflowPropertyDateTime(siteWFDefinition.Properties, "Definition.ModifiedDateUTC"), + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2013", "Site",siteWFDefinition.DisplayName,siteWFDefinition.Id.ToString(), false,web); + + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2013 site workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + } + #endregion + + #region If SP2013 list scoped workflows are found + // We've found SP2013 list scoped workflows + if (siteWFDefinitions != null && siteWFDefinitions.Count() > 0) + { + foreach (var listWFDefinition in siteWFDefinitions.Where(p => p.RestrictToType != null && (p.RestrictToType.Equals("list", StringComparison.InvariantCultureIgnoreCase) || p.RestrictToType.Equals("universal", StringComparison.InvariantCultureIgnoreCase)))) + { + // Check if this workflow is also in use + var listWorkflowSubscriptions = siteWFSubscriptions.Where(p => p.DefinitionId.Equals(listWFDefinition.Id)); + + // Perform workflow analysis + var workFlowAnalysisResult = WorkflowManager.Instance.ParseWorkflowDefinition(listWFDefinition.Xaml, WorkflowTypes.SP2013); + //if (listWFDefinition.Xaml != null) + //{ + // ops.SaveXamlFile(listWFDefinition.Xaml, web, listWFDefinition.DisplayName,"list", folderPath); + //} + var workFlowTriggerAnalysisResult = WorkflowManager.Instance.ParseWorkflowTriggers(GetWorkflowPropertyBool(listWFDefinition.Properties, "SPDConfig.StartOnCreate"), GetWorkflowPropertyBool(listWFDefinition.Properties, "SPDConfig.StartOnChange"), GetWorkflowPropertyBool(listWFDefinition.Properties, "SPDConfig.StartManually")); + + if (listWorkflowSubscriptions.Count() > 0) + { + foreach (var listWorkflowSubscription in listWorkflowSubscriptions) + { + Guid associatedListId = Guid.Empty; + string associatedListTitle = ""; + string associatedListUrl = ""; + if (Guid.TryParse(GetWorkflowProperty(listWorkflowSubscription, "Microsoft.SharePoint.ActivationProperties.ListId"), out Guid associatedListIdValue)) + { + associatedListId = associatedListIdValue; + + // Lookup this list and update title and url + var listLookup = lists.Where(p => p.Id.Equals(associatedListId)).FirstOrDefault(); + if (listLookup != null) + { + associatedListTitle = listLookup.Title; + associatedListUrl = listLookup.RootFolder.ServerRelativeUrl; + } + } + + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = associatedListTitle, + ListUrl = associatedListUrl, + ListId = associatedListId, + ContentTypeId = "", + ContentTypeName = "", + Version = "2013", + Scope = "List", + RestrictToType = listWFDefinition.RestrictToType, + DefinitionName = listWFDefinition.DisplayName, + DefinitionDescription = listWFDefinition.Description, + SubscriptionName = listWorkflowSubscription.Name, + HasSubscriptions = true, + Enabled = listWorkflowSubscription.Enabled, + DefinitionId = listWFDefinition.Id, + IsOOBWorkflow = false, + SubscriptionId = listWorkflowSubscription.Id, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + UnsupportedActionsInFlow = workFlowAnalysisResult?.UnsupportedActions, + CreatedBy = listWFDefinition.Properties["vti_author"], + ModifiedBy = listWFDefinition.Properties["ModifiedBy"], + UnsupportedActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.UnsupportedAccountCount : 0, + LastDefinitionEdit = GetWorkflowPropertyDateTime(listWFDefinition.Properties, "Definition.ModifiedDateUTC"), + LastSubscriptionEdit = GetWorkflowPropertyDateTime(listWorkflowSubscription.PropertyDefinitions, "SharePointWorkflowContext.Subscription.ModifiedDateUTC"), + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2013", "List",listWFDefinition.DisplayName,listWFDefinition.Id.ToString(), false,web); + + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2013 list workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + else + { + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = "", + ListUrl = "", + ListId = Guid.Empty, + ContentTypeId = "", + ContentTypeName = "", + Version = "2013", + Scope = "List", + RestrictToType = listWFDefinition.RestrictToType, + DefinitionName = listWFDefinition.DisplayName, + DefinitionDescription = listWFDefinition.Description, + SubscriptionName = "", + HasSubscriptions = false, + Enabled = false, + DefinitionId = listWFDefinition.Id, + IsOOBWorkflow = false, + SubscriptionId = Guid.Empty, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + UnsupportedActionsInFlow = workFlowAnalysisResult?.UnsupportedActions, + UnsupportedActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.UnsupportedAccountCount : 0, + LastDefinitionEdit = GetWorkflowPropertyDateTime(listWFDefinition.Properties, "Definition.ModifiedDateUTC"), + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2013", "Site",listWFDefinition.DisplayName,listWFDefinition.Id.ToString(), false,web); + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2013 list workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + } + #endregion + + #region Find all Site, list and content type level 2010 workflows + // *********************************************** + // Site, list and content type level 2010 workflow + // *********************************************** + + // Find all places where we have workflows associated (=subscribed) to SharePoint objects + if (web.WorkflowAssociations.Count > 0) + { + foreach (var workflowAssociation in web.WorkflowAssociations) + { + this.sp2010WorkflowAssociations.Add(new SP2010WorkFlowAssociation() { Scope = "Site", WorkflowAssociation = workflowAssociation }); + } + } + + foreach (var list in lists.Where(p => p.WorkflowAssociations.Count > 0)) + { + foreach (var workflowAssociation in list.WorkflowAssociations) + { + this.sp2010WorkflowAssociations.Add(new SP2010WorkFlowAssociation() { Scope = "List", WorkflowAssociation = workflowAssociation, AssociatedList = list }); + } + } + + foreach (var ct in web.ContentTypes.Where(p => p.WorkflowAssociations.Count > 0)) + { + foreach (var workflowAssociation in ct.WorkflowAssociations) + { + this.sp2010WorkflowAssociations.Add(new SP2010WorkFlowAssociation() { Scope = "ContentType", WorkflowAssociation = workflowAssociation, AssociatedContentType = ct }); + } + } + #endregion + + #region Process 2010 Workflows + // Process 2010 worflows + List processedWorkflowAssociations = new List(this.sp2010WorkflowAssociations.Count); + + if (web.WorkflowTemplates.Count > 0) + { + + // Process the templates + foreach (var workflowTemplate in web.WorkflowTemplates) + { + // do we have workflows associated for this template? + var associatedWorkflows = this.sp2010WorkflowAssociations.Where(p => p.WorkflowAssociation.BaseId.Equals(workflowTemplate.Id)); + if (associatedWorkflows.Count() > 0) + { + // Perform workflow analysis + // If returning null than this workflow template was an OOB workflow one + WorkflowActionAnalysis workFlowAnalysisResult = null; + var loadedWorkflow = LoadWorkflowDefinition(cc, workflowTemplate); + if (!string.IsNullOrEmpty(loadedWorkflow?.Item1)) + { + workFlowAnalysisResult = WorkflowManager.Instance.ParseWorkflowDefinition(loadedWorkflow.Item1, WorkflowTypes.SP2010); + } + + foreach (var associatedWorkflow in associatedWorkflows) + { + processedWorkflowAssociations.Add(associatedWorkflow.WorkflowAssociation.Id); + + // Skip previous versions of a workflow + // TODO: non-english sites will use another string + if (associatedWorkflow.WorkflowAssociation.Name.Contains("(Previous Version:")) + { + continue; + } + + var workFlowTriggerAnalysisResult = WorkflowManager.Instance.ParseWorkflowTriggers(associatedWorkflow.WorkflowAssociation.AutoStartCreate, associatedWorkflow.WorkflowAssociation.AutoStartChange, associatedWorkflow.WorkflowAssociation.AllowManual); + + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.Title : "", + ListUrl = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.RootFolder.ServerRelativeUrl : "", + ListId = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.Id : Guid.Empty, + ContentTypeId = associatedWorkflow.AssociatedContentType != null ? associatedWorkflow.AssociatedContentType.StringId : "", + ContentTypeName = associatedWorkflow.AssociatedContentType != null ? associatedWorkflow.AssociatedContentType.Name : "", + Version = "2010", + Scope = associatedWorkflow.Scope, + RestrictToType = "N/A", + DefinitionName = workflowTemplate.Name, + DefinitionDescription = workflowTemplate.Description, + SubscriptionName = associatedWorkflow.WorkflowAssociation.Name, + HasSubscriptions = true, + Enabled = associatedWorkflow.WorkflowAssociation.Enabled, + DefinitionId = workflowTemplate.Id, + IsOOBWorkflow = IsOOBWorkflow(workflowTemplate.Id.ToString()), + SubscriptionId = associatedWorkflow.WorkflowAssociation.Id, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + UnsupportedActionsInFlow = workFlowAnalysisResult?.UnsupportedActions, + UnsupportedActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.UnsupportedAccountCount : 0, + LastDefinitionEdit = loadedWorkflow != null ? loadedWorkflow.Item2 : associatedWorkflow.WorkflowAssociation.Modified, + LastSubscriptionEdit = associatedWorkflow.WorkflowAssociation.Modified, + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2010", associatedWorkflow.Scope, workflowTemplate.Name, workflowTemplate.Id.ToString(), IsOOBWorkflow(workflowTemplate.Id.ToString()),web); + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2010 {associatedWorkflow.Scope} type workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + else + { + // Only add non OOB workflow templates when there's no associated workflow - makes the dataset smaller + if (!IsOOBWorkflow(workflowTemplate.Id.ToString())) + { + // Perform workflow analysis + WorkflowActionAnalysis workFlowAnalysisResult = null; + var loadedWorkflow = LoadWorkflowDefinition(cc, workflowTemplate); + if (!string.IsNullOrEmpty(loadedWorkflow?.Item1)) + { + workFlowAnalysisResult = WorkflowManager.Instance.ParseWorkflowDefinition(loadedWorkflow.Item1, WorkflowTypes.SP2010); + } + + + var workFlowTriggerAnalysisResult = WorkflowManager.Instance.ParseWorkflowTriggers(workflowTemplate.AutoStartCreate, workflowTemplate.AutoStartChange, workflowTemplate.AllowManual); + + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = "", + ListUrl = "", + ListId = Guid.Empty, + ContentTypeId = "", + ContentTypeName = "", + Version = "2010", + Scope = "", + RestrictToType = "N/A", + DefinitionName = workflowTemplate.Name, + DefinitionDescription = workflowTemplate.Description, + SubscriptionName = "", + HasSubscriptions = false, + Enabled = false, + DefinitionId = workflowTemplate.Id, + IsOOBWorkflow = IsOOBWorkflow(workflowTemplate.Id.ToString()), + SubscriptionId = Guid.Empty, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + LastDefinitionEdit = loadedWorkflow != null ? loadedWorkflow.Item2 : DateTime.MinValue, + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2010", "", workflowTemplate.Name, workflowTemplate.Id.ToString(), IsOOBWorkflow(workflowTemplate.Id.ToString()),web); + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2010 type workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + } + } + #endregion + + #region All other Workflows + // Are there associated workflows for which we did not find a template (especially when the WF is created for a list) + foreach (var associatedWorkflow in this.sp2010WorkflowAssociations) + { + if (!processedWorkflowAssociations.Contains(associatedWorkflow.WorkflowAssociation.Id)) + { + // Skip previous versions of a workflow + // TODO: non-english sites will use another string + if (associatedWorkflow.WorkflowAssociation.Name.Contains("(Previous Version:")) + { + continue; + } + + // Perform workflow analysis + WorkflowActionAnalysis workFlowAnalysisResult = null; + var loadedWorkflow = LoadWorkflowDefinition(cc, associatedWorkflow.WorkflowAssociation); + if (!string.IsNullOrEmpty(loadedWorkflow?.Item1)) + { + workFlowAnalysisResult = WorkflowManager.Instance.ParseWorkflowDefinition(loadedWorkflow.Item1, WorkflowTypes.SP2010); + } + + var workFlowTriggerAnalysisResult = WorkflowManager.Instance.ParseWorkflowTriggers(associatedWorkflow.WorkflowAssociation.AutoStartCreate, associatedWorkflow.WorkflowAssociation.AutoStartChange, associatedWorkflow.WorkflowAssociation.AllowManual); + + WorkflowScanResult workflowScanResult = new WorkflowScanResult() + { + SiteColUrl = this.SiteCollectionUrl, + SiteURL = this.SiteUrl, + ListTitle = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.Title : "", + ListUrl = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.RootFolder.ServerRelativeUrl : "", + ListId = associatedWorkflow.AssociatedList != null ? associatedWorkflow.AssociatedList.Id : Guid.Empty, + ContentTypeId = associatedWorkflow.AssociatedContentType != null ? associatedWorkflow.AssociatedContentType.StringId : "", + ContentTypeName = associatedWorkflow.AssociatedContentType != null ? associatedWorkflow.AssociatedContentType.Name : "", + Version = "2010", + Scope = associatedWorkflow.Scope, + RestrictToType = "N/A", + DefinitionName = associatedWorkflow.WorkflowAssociation.Name, + DefinitionDescription = "", + SubscriptionName = associatedWorkflow.WorkflowAssociation.Name, + HasSubscriptions = true, + Enabled = associatedWorkflow.WorkflowAssociation.Enabled, + DefinitionId = Guid.Empty, + IsOOBWorkflow = false, + SubscriptionId = associatedWorkflow.WorkflowAssociation.Id, + UsedActions = workFlowAnalysisResult?.WorkflowActions, + ActionCount = workFlowAnalysisResult != null ? workFlowAnalysisResult.ActionCount : 0, + UsedTriggers = workFlowTriggerAnalysisResult?.WorkflowTriggers, + LastSubscriptionEdit = associatedWorkflow.WorkflowAssociation.Modified, + LastDefinitionEdit = loadedWorkflow != null ? loadedWorkflow.Item2 : associatedWorkflow.WorkflowAssociation.Modified, + }; + ops.AddRowToDataTable(workflowScanResult, dt, "2010", associatedWorkflow.Scope, associatedWorkflow.WorkflowAssociation.Name, Guid.Empty.ToString(), false,web); + //if (!this.ScanJob.WorkflowScanResults.TryAdd($"workflowScanResult.SiteURL.{Guid.NewGuid()}", workflowScanResult)) + //{ + // ScanError error = new ScanError() + // { + // Error = $"Could not add 2010 {associatedWorkflow.Scope} type workflow scan result for {workflowScanResult.SiteColUrl}", + // SiteColUrl = this.SiteCollectionUrl, + // SiteURL = this.SiteUrl, + // Field1 = "WorkflowAnalyzer", + // }; + // this.ScanJob.ScanErrors.Push(error); + //} + } + } + #endregion + + } + catch(Exception ex) + { + + } + } + + + + private bool GetWorkflowPropertyBool(IDictionary properties, string property) + { + if (string.IsNullOrEmpty(property) || properties == null) + { + return false; + } + + if (properties.ContainsKey(property)) + { + if (bool.TryParse(properties[property], out bool parsedValue)) + { + return parsedValue; + } + } + + return false; + } + + private DateTime GetWorkflowPropertyDateTime(IDictionary properties, string property) + { + if (string.IsNullOrEmpty(property) || properties == null) + { + return DateTime.MinValue; + } + + if (properties.ContainsKey(property)) + { + if (DateTime.TryParseExact(properties[property], "M/d/yyyy h:m:s tt", new CultureInfo("en-US"), DateTimeStyles.AssumeUniversal, out DateTime parsedValue)) + { + return parsedValue; + } + } + + return DateTime.MinValue; + } + + private string GetWorkflowProperty(WorkflowSubscription subscription, string propertyName) + { + if (subscription.PropertyDefinitions.ContainsKey(propertyName)) + { + return subscription.PropertyDefinitions[propertyName]; + } + + return ""; + } + + private Tuple LoadWorkflowDefinition(ClientContext cc, WorkflowAssociation workflowAssociation) + { + // Ensure the workflow library was loaded if not yet done + LoadWorkflowLibrary(cc); + try + { + return GetFileInformation(cc.Web, $"{this.workflowList.RootFolder.ServerRelativeUrl}/{workflowAssociation.Name}/{workflowAssociation.Name}.xoml"); + } + catch (Exception ex) + { + + } + + return null; + } + + private Tuple LoadWorkflowDefinition(ClientContext cc, WorkflowTemplate workflowTemplate) + { + if (!IsOOBWorkflow(workflowTemplate.Id.ToString())) + { + // Ensure the workflow library was loaded if not yet done + LoadWorkflowLibrary(cc); + try + { + return GetFileInformation(cc.Web, $"{this.workflowList.RootFolder.ServerRelativeUrl}/{workflowTemplate.Name}/{workflowTemplate.Name}.xoml"); + } + catch (Exception ex) + { + + } + } + + return null; + } + + private List LoadWorkflowLibrary(ClientContext cc) + { + if (this.workflowList != null) + { + return this.workflowList; + } + + var baseExpressions = new List>> { l => l.DefaultViewUrl, l => l.Id, l => l.BaseTemplate, l => l.OnQuickLaunch, l => l.DefaultViewUrl, l => l.Title, l => l.Hidden, l => l.RootFolder.ServerRelativeUrl }; + var query = cc.Web.Lists.IncludeWithDefaultProperties(baseExpressions.ToArray()); + var lists = cc.Web.Context.LoadQuery(query.Where(l => l.Title == "Workflows")); + cc.ExecuteQuery(); + this.workflowList = lists.FirstOrDefault(); + + return this.workflowList; + } + + private static Tuple GetFileInformation(Web web, string serverRelativeUrl) + { + //var file = web.GetFileByServerRelativePath(ResourcePath.FromDecodedUrl(serverRelativeUrl)); + var file = web.GetFileByServerRelativeUrl(serverRelativeUrl); + + web.Context.Load(file); + //web.Context.Load(file, p => p.ListItemAllFields); + web.Context.ExecuteQuery(); + + // TODO: fails when using sites.read.all role on xoml file download (access denied, requires ACP permission level) + ClientResult stream = file.OpenBinaryStream(); + web.Context.ExecuteQuery(); + + string returnString = string.Empty; + DateTime date = DateTime.MinValue; + + //UPDATED the LOC from date = file.ListItemAllFields.LastModifiedDateTime(); TO date = file.TimeLastModified; + date = file.TimeLastModified; + + using (Stream memStream = new MemoryStream()) + { + CopyStream(stream.Value, memStream); + memStream.Position = 0; + StreamReader reader = new StreamReader(memStream); + returnString = reader.ReadToEnd(); + } + + return new Tuple(returnString, date); + } + + private static void CopyStream(Stream source, Stream destination) + { + byte[] buffer = new byte[32768]; + int bytesRead; + + do + { + bytesRead = source.Read(buffer, 0, buffer.Length); + destination.Write(buffer, 0, bytesRead); + } while (bytesRead != 0); + } + private bool IsOOBWorkflow(string workflowTemplateId) + { + if (!string.IsNullOrEmpty(workflowTemplateId)) + { + foreach (var oobId in WorkflowDiscovery.OOBWorkflowIDStarts) + { + if (workflowTemplateId.StartsWith(oobId)) + { + return true; + } + } + } + + return false; + } + } +} diff --git a/Discovery/WorkflowManager.cs b/Discovery/WorkflowManager.cs new file mode 100644 index 0000000..754046a --- /dev/null +++ b/Discovery/WorkflowManager.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml; +using System.Xml.Serialization; +using Common; + +namespace Discovery +{ + public sealed class WorkflowManager + { + private static readonly Lazy _lazyInstance = new Lazy(() => new WorkflowManager()); + private WorkflowActions defaultWorkflowActions; + + private static readonly string[] SP2013SupportedFlowActions = new string[] + { + "Microsoft.SharePoint.WorkflowServices.Activities.Comment", + "Microsoft.SharePoint.WorkflowServices.Activities.CallHTTPWebService", + "Microsoft.Activities.BuildDynamicValue", + "Microsoft.Activities.GetDynamicValueProperty", + "Microsoft.Activities.CountDynamicValueItems", + "Microsoft.SharePoint.WorkflowServices.Activities.SetField", + "System.Activities.Statements.Assign", + "Microsoft.SharePoint.WorkflowServices.Activities.CreateListItem", + "Microsoft.SharePoint.WorkflowServices.Activities.UpdateListItem", + "Microsoft.SharePoint.WorkflowServices.Activities.DeleteListItem", + "Microsoft.SharePoint.WorkflowServices.Activities.WaitForFieldChange", + "Microsoft.SharePoint.WorkflowServices.Activities.WaitForItemEvent", + "Microsoft.SharePoint.WorkflowServices.Activities.CheckOutItem", + "Microsoft.SharePoint.WorkflowServices.Activities.UndoCheckOutItem", + "Microsoft.SharePoint.WorkflowServices.Activities.CheckInItem", + "Microsoft.SharePoint.WorkflowServices.Activities.CopyItem", + "Microsoft.SharePoint.WorkflowServices.Activities.Email", + "Microsoft.Activities.Expressions.AddToDate", + "Microsoft.SharePoint.WorkflowServices.Activities.SetTimeField", + "Microsoft.SharePoint.WorkflowServices.Activities.DateInterval", + "Microsoft.SharePoint.WorkflowServices.Activities.ExtractSubstringFromEnd", + "Microsoft.SharePoint.WorkflowServices.Activities.ExtractSubstringFromStart", + "Microsoft.SharePoint.WorkflowServices.Activities.ExtractSubstringFromIndex", + "Microsoft.SharePoint.WorkflowServices.Activities.ExtractSubstringFromIndexLength", + "Microsoft.Activities.Expressions.Trim", + "Microsoft.Activities.Expressions.IndexOfString", + "Microsoft.Activities.Expressions.ReplaceString", + "Microsoft.SharePoint.WorkflowServices.Activities.DelayFor", + "Microsoft.SharePoint.WorkflowServices.Activities.DelayUntil", + "Microsoft.SharePoint.WorkflowServices.Activities.Calc", + "Microsoft.SharePoint.WorkflowServices.Activities.WriteToHistory", + "Microsoft.SharePoint.WorkflowServices.Activities.TranslateDocument", + "Microsoft.SharePoint.WorkflowServices.Activities.SetModerationStatus" + }; + + private static readonly string[] SP2010SupportedFlowActions = new string[] + { + "Microsoft.SharePoint.WorkflowActions.EmailActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.CollectDataTask", + "Microsoft.SharePoint.WorkflowActions.TodoItemTask", + "Microsoft.SharePoint.WorkflowActions.GroupAssignedTask", + "Microsoft.SharePoint.WorkflowActions.WithKey.SetFieldActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.UpdateItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.CreateItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.CopyItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.CheckOutItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.CheckInItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.UndoCheckOutItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.DeleteItemActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.WaitForActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.WaitForDocumentStatusActivity", + "Microsoft.SharePoint.WorkflowActions.SetVariableActivity", + "Microsoft.SharePoint.WorkflowActions.BuildStringActivity", + "Microsoft.SharePoint.WorkflowActions.MathActivity", + "Microsoft.SharePoint.WorkflowActions.DelayForActivity", + "Microsoft.SharePoint.WorkflowActions.DelayUntilActivity", + "System.Workflow.ComponentModel.TerminateActivity", + "Microsoft.SharePoint.WorkflowActions.LogToHistoryListActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.SetModerationStatusActivity", + "Microsoft.SharePoint.WorkflowActions.AddTimeToDateActivity", + "Microsoft.SharePoint.WorkflowActions.SetTimeFieldActivity", + "Microsoft.SharePoint.WorkflowActions.DateIntervalActivity", + "Microsoft.SharePoint.WorkflowActions.ExtractSubstringFromEndActivity", + "Microsoft.SharePoint.WorkflowActions.ExtractSubstringFromStartActivity", + "Microsoft.SharePoint.WorkflowActions.ExtractSubstringFromIndexActivity", + "Microsoft.SharePoint.WorkflowActions.ExtractSubstringFromIndexLengthActivity", + "Microsoft.SharePoint.WorkflowActions.CommentActivity", + "Microsoft.SharePoint.WorkflowActions.PersistOnCloseActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.AddListItemPermissionsActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.RemoveListItemPermissionsActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.ReplaceListItemPermissionsActivity", + "Microsoft.SharePoint.WorkflowActions.WithKey.InheritListItemParentPermissionsActivity" + }; + + /// + /// Get's the single workflow manager instance, singleton pattern + /// + public static WorkflowManager Instance + { + get + { + return _lazyInstance.Value; + } + } + + #region Construction + private WorkflowManager() + { + // place for instance initialization code + defaultWorkflowActions = null; + } + #endregion + + /// + /// Translate workflow trigger to a string + /// + /// On create was set + /// on change wat set + /// manual execution is allowed + /// string representation of the used workflow triggers + public WorkflowTriggerAnalysis ParseWorkflowTriggers(bool onItemCreate, bool onItemChange, bool allowManual) + { + List triggers = new List(); + + if (onItemCreate) + { + triggers.Add("OnCreate"); + } + + if (onItemChange) + { + triggers.Add("OnChange"); + } + + if (allowManual) + { + triggers.Add("Manual"); + } + + return new WorkflowTriggerAnalysis() { WorkflowTriggers = triggers }; + } + + /// + /// Analysis a workflow definition and returns the used OOB actions + /// + /// Workflow definition to analyze + /// 2010 or 2013 workflow + /// List of OOB actions used in the workflow + public WorkflowActionAnalysis ParseWorkflowDefinition(string workflowDefinition, WorkflowTypes wfType) + { + try + { + if (string.IsNullOrEmpty(workflowDefinition)) + { + return null; + } + + var xmlDoc = new XmlDocument(); + xmlDoc.Load(WebpartMappingLoader.GenerateStreamFromString(workflowDefinition)); + + //determine whether document contains namespace + string namespaceName = ""; + if (wfType == WorkflowTypes.SP2010) + { + namespaceName = "ns0"; + } + else if (wfType == WorkflowTypes.SP2013) + { + namespaceName = "local"; + } + + var namespacePrefix = string.Empty; + XmlNamespaceManager nameSpaceManager = null; + if (xmlDoc.FirstChild.Attributes != null) + { + var xmlns = xmlDoc.FirstChild.Attributes[$"xmlns:{namespaceName}"]; + if (xmlns != null) + { + nameSpaceManager = new XmlNamespaceManager(xmlDoc.NameTable); + nameSpaceManager.AddNamespace(namespaceName, xmlns.Value); + namespacePrefix = namespaceName + ":"; + } + } + + // Grab all nodes with the workflow action namespace (ns0/local) + var nodes = xmlDoc.SelectNodes($"//{namespacePrefix}*", nameSpaceManager); + + // Iterate over the nodes and "identify the OOB activities" + List usedOOBWorkflowActivities = new List(); + List unsupportedOOBWorkflowActivities = new List(); + int actionCounter = 0; + int knownActionCounter = 0; + int unsupportedActionCounter = 0; + + foreach (XmlNode node in nodes) + { + actionCounter++; + + WorkflowAction defaultOOBWorkflowAction = null; + + if (wfType == WorkflowTypes.SP2010) + { + defaultOOBWorkflowAction = this.defaultWorkflowActions.SP2010DefaultActions.Where(p => p.ActionNameShort == node.LocalName).FirstOrDefault(); + } + else if (wfType == WorkflowTypes.SP2013) + { + defaultOOBWorkflowAction = this.defaultWorkflowActions.SP2013DefaultActions.Where(p => p.ActionNameShort == node.LocalName).FirstOrDefault(); + } + + if (defaultOOBWorkflowAction != null) + { + knownActionCounter++; + if (!usedOOBWorkflowActivities.Contains(defaultOOBWorkflowAction.ActionNameShort)) + { + usedOOBWorkflowActivities.Add(defaultOOBWorkflowAction.ActionNameShort); + } + + + if (wfType == WorkflowTypes.SP2010) + { + if (!WorkflowManager.SP2010SupportedFlowActions.Contains(defaultOOBWorkflowAction.ActionName)) + { + unsupportedActionCounter++; + unsupportedOOBWorkflowActivities.Add(defaultOOBWorkflowAction.ActionNameShort); + } + } + else if (wfType == WorkflowTypes.SP2013) + { + if (!WorkflowManager.SP2013SupportedFlowActions.Contains(defaultOOBWorkflowAction.ActionName)) + { + unsupportedActionCounter++; + unsupportedOOBWorkflowActivities.Add(defaultOOBWorkflowAction.ActionNameShort); + } + } + } + } + + return new WorkflowActionAnalysis() + { + WorkflowActions = usedOOBWorkflowActivities, + ActionCount = knownActionCounter, + UnsupportedActions = unsupportedOOBWorkflowActivities, + UnsupportedAccountCount = unsupportedActionCounter + }; + } + catch (Exception ex) + { + // TODO + // Eat exception for now + } + + return null; + } + + /// + /// Trigger the population of the default workflow actions for 2010/2013 workflows + /// + public void LoadWorkflowDefaultActions() + { + WorkflowActions wfActions = new WorkflowActions(); + + var sp2010Actions = LoadDefaultActions(WorkflowTypes.SP2010); + var sp2013Actions = LoadDefaultActions(WorkflowTypes.SP2013); + + foreach (var action in sp2010Actions) + { + wfActions.SP2010DefaultActions.Add(new WorkflowAction() { ActionName = action, ActionNameShort = GetShortName(action) }); + } + + foreach (var action in sp2013Actions) + { + wfActions.SP2013DefaultActions.Add(new WorkflowAction() { ActionName = action, ActionNameShort = GetShortName(action) }); + } + + this.defaultWorkflowActions = wfActions; + } + + #region Helper methods + private string GetShortName(string action) + { + if (action.Contains(".")) + { + return action.Substring(action.LastIndexOf(".") + 1); + } + + return action; + } + + private List LoadDefaultActions(WorkflowTypes wfType) + { + List wfActionsList = new List(); + + string fileName = null; + + if (wfType == WorkflowTypes.SP2010) + { + //fileName = "SharePointPnP.Modernization.Scanner.Core.Workflow.sp2010wfmodel.xml"; + fileName = "Common.sp2010wfmodel.xml"; + } + else if (wfType == WorkflowTypes.SP2013) + { + //fileName = "SharePointPnP.Modernization.Scanner.Core.Workflow.sp2013wfmodel.xml"; + fileName = "Common.sp2013wfmodel.xml"; + } + + var wfModelString = ""; + + //using (Stream stream = typeof(WorkflowManager).Assembly.GetManifestResourceStream(fileName)) + using (Stream stream = typeof(WorkflowAction).Assembly.GetManifestResourceStream(fileName)) + { + using (StreamReader reader = new StreamReader(stream)) + { + wfModelString = reader.ReadToEnd(); + } + } + + if (!string.IsNullOrEmpty(wfModelString)) + { + if (wfType == WorkflowTypes.SP2010) + { + Common.SP2010.WorkflowInfo wfInformation; + using (var stream = WebpartMappingLoader.GenerateStreamFromString(wfModelString)) + { + XmlSerializer xmlWorkflowInformation = new XmlSerializer(typeof(Common.SP2010.WorkflowInfo)); + wfInformation = (Common.SP2010.WorkflowInfo)xmlWorkflowInformation.Deserialize(stream); + } + + foreach (var wfAction in wfInformation.Actions.Action) + { + if (!wfActionsList.Contains(wfAction.ClassName)) + { + wfActionsList.Add(wfAction.ClassName); + } + } + } + else if (wfType == WorkflowTypes.SP2013) + { + Common.SP2013.WorkflowInfo wfInformation; + using (var stream = WebpartMappingLoader.GenerateStreamFromString(wfModelString)) + { + XmlSerializer xmlWorkflowInformation = new XmlSerializer(typeof(Common.SP2013.WorkflowInfo)); + wfInformation = (Common.SP2013.WorkflowInfo)xmlWorkflowInformation.Deserialize(stream); + + } + + foreach (var wfAction in wfInformation.Actions.Action) + { + if (!wfActionsList.Contains(wfAction.ClassName)) + { + wfActionsList.Add(wfAction.ClassName); + } + } + } + } + + return wfActionsList; + } + #endregion + } +} + diff --git a/Discovery/app.config b/Discovery/app.config new file mode 100644 index 0000000..ca263be --- /dev/null +++ b/Discovery/app.config @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Discovery/packages.config b/Discovery/packages.config new file mode 100644 index 0000000..4331ab7 --- /dev/null +++ b/Discovery/packages.config @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Discovery/sp2010wfmodel.xml b/Discovery/sp2010wfmodel.xml new file mode 100644 index 0000000..d2c4a70 --- /dev/null +++ b/Discovery/sp2010wfmodel.xml @@ -0,0 +1,1589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Discovery/sp2013wfmodel.xml b/Discovery/sp2013wfmodel.xml new file mode 100644 index 0000000..7936fa5 --- /dev/null +++ b/Discovery/sp2013wfmodel.xml @@ -0,0 +1,1919 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Microsoft.Services.WorkflowAssessment.sln b/Microsoft.Services.WorkflowAssessment.sln new file mode 100644 index 0000000..286ac34 --- /dev/null +++ b/Microsoft.Services.WorkflowAssessment.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1062 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{04A36617-4353-4779-92F9-36BAFFE6A5F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Root", "Root\Root.csproj", "{C36A3FF3-1A6B-4ACD-94FC-0BC798082603}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Analysis", "Analysis\Analysis.csproj", "{11F9C187-6E26-43CC-AA57-B82049101ECC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discovery", "Discovery\Discovery.csproj", "{66180571-9292-4411-8B01-B31DCE2CC0E8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {04A36617-4353-4779-92F9-36BAFFE6A5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04A36617-4353-4779-92F9-36BAFFE6A5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04A36617-4353-4779-92F9-36BAFFE6A5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04A36617-4353-4779-92F9-36BAFFE6A5F6}.Release|Any CPU.Build.0 = Release|Any CPU + {C36A3FF3-1A6B-4ACD-94FC-0BC798082603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C36A3FF3-1A6B-4ACD-94FC-0BC798082603}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C36A3FF3-1A6B-4ACD-94FC-0BC798082603}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C36A3FF3-1A6B-4ACD-94FC-0BC798082603}.Release|Any CPU.Build.0 = Release|Any CPU + {11F9C187-6E26-43CC-AA57-B82049101ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11F9C187-6E26-43CC-AA57-B82049101ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11F9C187-6E26-43CC-AA57-B82049101ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11F9C187-6E26-43CC-AA57-B82049101ECC}.Release|Any CPU.Build.0 = Release|Any CPU + {66180571-9292-4411-8B01-B31DCE2CC0E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66180571-9292-4411-8B01-B31DCE2CC0E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66180571-9292-4411-8B01-B31DCE2CC0E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66180571-9292-4411-8B01-B31DCE2CC0E8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E934118A-2D8B-4D11-A008-953F53637EBD} + EndGlobalSection +EndGlobal diff --git a/Root/CmdCompareDownloadWorkflows.cs b/Root/CmdCompareDownloadWorkflows.cs new file mode 100644 index 0000000..34bd51b --- /dev/null +++ b/Root/CmdCompareDownloadWorkflows.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; +using Common; +namespace Root +{ + public class CmdCompareDownloadWorkflows : PSCmdlet + { + private string logFolderPath; + public DirectoryInfo logFolder; + + [Parameter(Mandatory = true, HelpMessage = @"The path where workflows are downloaded to for analyzing (e.g. c:\temp\workflows")] + public string OutputDirectory { get; set; } + + protected override void BeginProcessing() + { + if (!Directory.Exists(string.Concat(OutputDirectory, @"\Logs"))) + { + logFolder = System.IO.Directory.CreateDirectory(string.Concat(OutputDirectory, @"\Logs")); + logFolderPath = logFolder.FullName; + Logging.LOG_DIRECTORY = logFolderPath; + Logging.GetInstance().WriteToLogFile(Logging.Info, "Log folder created"); + + } + else + { + logFolderPath = string.Concat(OutputDirectory, @"\Logs"); + Logging.LOG_DIRECTORY = logFolderPath; + } + + base.BeginProcessing(); + } + + protected override void EndProcessing() + { + base.EndProcessing(); + } + + protected override void ProcessRecord() + { + Console.WriteLine(System.Environment.NewLine); + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Beginning to analyze and compare SharePoint Workflows to Power Automate features.. "); + Console.WriteLine(System.Environment.NewLine); + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Please standby. This may take some time.. "); + Console.WriteLine(System.Environment.NewLine); + Logging.GetInstance().WriteToLogFile(Logging.Info, "Beginning to analyze and compare SharePoint Workflows to Power Automate features.. "); + //CompareInfoPathForms cif = new CompareInfoPathForms(); + //cif.CompareInfoPathToPowerApps(OutputDirectory); + CompareWorkflows cwf = new CompareWorkflows(); + cwf.CompareWorkflowsToPowerAutomate(OutputDirectory); + } + } +} diff --git a/Root/CmdGetWorkflowAssociationsForOnprem.cs b/Root/CmdGetWorkflowAssociationsForOnprem.cs new file mode 100644 index 0000000..e7f270b --- /dev/null +++ b/Root/CmdGetWorkflowAssociationsForOnprem.cs @@ -0,0 +1,309 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Data; +using System.Management.Automation; +using Microsoft.SharePoint.Client; +using System.Security; +using OfficeDevPnP.Core; +using Common; +using Discovery; + + +namespace Root +{ + public class PwdDynamicParam + { + private SecureString pwd; + + [Parameter(Mandatory = true, HelpMessage = "Specify the password as a secure string")] + public SecureString Password + { + get { return pwd; } + set { pwd = value; } + } + } + /// + /// Commandlet to discover the InfoPath forms in + /// Onpremise environments that are published to + /// list and document libraries + /// + /// /// + /// + + [Cmdlet(VerbsCommon.Get, "WorkflowAssociationsForOnprem")] + //public class CmdGetWorkflowAssociationsForOnprem : PSCmdlet,IDynamicParameters + public class CmdGetWorkflowAssociationsForOnprem : PSCmdlet + { + private string assessmentScope; + private static List sitecollectionUrls = new List(); + + [Parameter(Mandatory = true, HelpMessage = "Specify the Domain name of the user account")] + public string DomainName; + + [Parameter(Mandatory = false, HelpMessage = "Specify the password (NOTE : This paramater takes password as plain text. If you like to provide the password as a secure string, ignore this parameter. Youw will be prompted to type in the password as a secure string")] + public string PasswordPlainText; + + [Parameter(Mandatory = true, HelpMessage = "Specify the user account for authentication")] + public string UserAccount; + + + [Parameter(Mandatory = false, HelpMessage = "Specify the file path of a text file containing target site collection URLs")] + public string SiteCollectionURLFilePath; + + [Parameter(Mandatory = false, HelpMessage = "Specify the URL of the Web Application")] + public string WebApplicationUrl; + + [Parameter(Mandatory = false, HelpMessage = "Specify the URL of the Site Collection")] + public string SiteCollectionUrl; + public bool DownloadWorkflowDefinitions + { + get { return downloadWFDefinitions; } + set { downloadWFDefinitions = value; } + } + private bool downloadWFDefinitions; + + [Parameter(Mandatory = true, HelpMessage = @"The path where the Assessment Summary, logs, Workflow definitions are downloaded (if DownloadForms parameter is set to true) for analyzing (e.g. F:\temp\WorkflowDefinitions")] + public string AssessmentOutputFolder; + private string logFolderPath; + public DirectoryInfo logFolder; + private PwdDynamicParam pwdDyn = null; + private bool pwdIsPlain = true; + public DataTable dtWorkflowLocations = new DataTable(); + + + public object GetDynamicParameters() + { + if (Object.Equals(PasswordPlainText, null)) + { + pwdDyn = new PwdDynamicParam(); + pwdIsPlain = false; + return pwdDyn; + } + else + return null; + + } + protected override void BeginProcessing() + { + + if (!Directory.Exists(string.Concat(AssessmentOutputFolder, @"\Logs"))) + { + logFolder = System.IO.Directory.CreateDirectory(string.Concat(AssessmentOutputFolder, @"\Logs")); + logFolderPath = logFolder.FullName; + Logging.LOG_DIRECTORY = logFolderPath; + Logging.GetInstance().WriteToLogFile(Logging.Info, "Log folder created"); + + } + else + { + logFolderPath = string.Concat(AssessmentOutputFolder, @"\Logs"); + Logging.LOG_DIRECTORY = logFolderPath; + } + + base.BeginProcessing(); + } + + protected override void EndProcessing() + { + base.EndProcessing(); + } + + protected override void ProcessRecord() + { + try + { + + if (String.IsNullOrEmpty(WebApplicationUrl)) + { + if (String.IsNullOrEmpty(SiteCollectionUrl)) + { + assessmentScope = "Farm"; + BeginToAssess(); + } + else + { + assessmentScope = "SiteCollection"; + BeginToAssess(); + } + } + else + { + if (!String.IsNullOrEmpty(SiteCollectionUrl)) + { + WriteWarning("Provide either the Web App URL or the Site Collection URL, but not both !"); + + } + else + { + assessmentScope = "WebApplication"; + BeginToAssess(); + } + } + + } + catch (Exception ex) + { + Host.UI.WriteLine(ConsoleColor.DarkRed, Host.UI.RawUI.BackgroundColor, ex.Message); + } + } + + + protected void BeginToAssess() + { + Operations ops = new Operations(); + try + { + //New Code Starts + string userInput = string.Empty; + Console.WriteLine(System.Environment.NewLine); + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "The assessment is scoped to run at " + assessmentScope + + " level. Would you like to proceed? [Y] to continue, [N] to abort."); + var op = this.InvokeCommand.InvokeScript("Read-Host"); + userInput = op[0].ToString().ToLower(); + + while (!userInput.Equals("y") && !userInput.Equals("n")) + { + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Invalid input. Press [Y] to continue, [N] to abort."); + op = this.InvokeCommand.InvokeScript("Read-Host"); + userInput = op[0].ToString().ToLower(); + + } + if (userInput.Equals("y")) + { + GetWorkflowsforOnPrem objonPrem = new GetWorkflowsforOnPrem(); + ops.CreateDirectoryStructure(AssessmentOutputFolder); + + //Logging.GetInstance().WriteToLogFile(Logging.Info, "Beginning assessment.."); + Console.WriteLine(System.Environment.NewLine); + Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "Beginning assessment.."); + + if (assessmentScope.Equals("Farm")) + { + objonPrem.Scope = "Farm"; + objonPrem.Url = null; + } + else if (assessmentScope.Equals("WebApplication")) + { + objonPrem.Scope = "WebApplication"; + objonPrem.Url = WebApplicationUrl; + } + else if (assessmentScope.Equals("SiteCollection")) + { + objonPrem.Scope = "SiteCollection"; + objonPrem.Url = SiteCollectionUrl; + } + objonPrem.DownloadPath = AssessmentOutputFolder; + //Set UserName & Password + objonPrem.userName = UserAccount; + if (pwdIsPlain) + objonPrem.password = PasswordPlainText; + else + objonPrem.password = pwdDyn.Password.ToString(); + //dtWorkflowLocations = objonPrem.Execute(Credential); + dtWorkflowLocations = objonPrem.Execute(); + //Save the CSV file + string csvFilePath = string.Concat(AssessmentOutputFolder, ops.summaryFolder, ops.summaryFile); + ops.WriteToCsvFile(dtWorkflowLocations, csvFilePath); + } + else if (userInput.Equals("n")) + { + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Operation aborted as per your input !"); + } + //New Code Ends + + + //Create Assessment folders + /* old code commented out + ops.CreateDirectoryStructure(AssessmentOutputFolder); + + ops.CreateDataTableColumns(dt); + string csvFilePath = string.Concat(AssessmentOutputFolder, ops.summaryFolder, ops.summaryFile); + string downloadXomlFolderPath = string.Concat(AssessmentOutputFolder, ops.downloadedFormsFolder); + sitecollectionUrls.Clear(); + int scCount = LoopSiteCollectionUrls(sitecollectionUrls, SiteCollectionURLFilePath); + if (scCount == 0) + { + WriteWarning(string.Format("The text file located at {0} does not contain Site Collection URLs and appears to be empty !", SiteCollectionURLFilePath)); + } + else + { + AuthenticationManager authManager = new AuthenticationManager(); + ClientContext cc = null; + + foreach (var scUrl in sitecollectionUrls) + { + if (pwdIsPlain) + cc = authManager.GetNetworkCredentialAuthenticatedContext(scUrl, UserAccount, PasswordPlainText, DomainName); + else + cc = authManager.GetNetworkCredentialAuthenticatedContext(scUrl, UserAccount, pwdDyn.Password, DomainName); + + Web web = cc.Web; + cc.Load(web, website => website.Title); + cc.ExecuteQuery(); + + Host.UI.WriteLine(ConsoleColor.DarkMagenta, Host.UI.RawUI.BackgroundColor, web.Title); + WorkflowManager.Instance.LoadWorkflowDefaultActions(); + + WorkflowDiscovery wfDisc = new WorkflowDiscovery(); + wfDisc.DiscoverWorkflows(cc, dt); + } + //Save the CSV file + ops.WriteToCsvFile(dt, csvFilePath); + } + */ + + } + catch (Exception ex) + { + Host.UI.WriteLine(ConsoleColor.DarkRed, Host.UI.RawUI.BackgroundColor, ex.Message); + } + } + private static SecureString GetPassword() + { + ConsoleKeyInfo info; + //Get the user's password as a SecureString + SecureString securePassword = new SecureString(); + do + { + info = Console.ReadKey(true); + if (info.Key != ConsoleKey.Enter) + { + securePassword.AppendChar(info.KeyChar); + } + } + while (info.Key != ConsoleKey.Enter); + return securePassword; + } + + public int LoopSiteCollectionUrls(List sitecollectionUrls, string filePath) + { + int counter = 0; + try + { + string line; + System.IO.StreamReader file = + new System.IO.StreamReader(filePath); + while ((line = file.ReadLine()) != null) + { + //removes all extra spaces etc. + sitecollectionUrls.Add(line.TrimEnd()); + //System.Console.WriteLine(line); + counter++; + } + file.Close(); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return counter; + } + + + } +} diff --git a/Root/CmdGetWorkflowAssociationsForSPO.cs b/Root/CmdGetWorkflowAssociationsForSPO.cs new file mode 100644 index 0000000..112bbfa --- /dev/null +++ b/Root/CmdGetWorkflowAssociationsForSPO.cs @@ -0,0 +1,184 @@ +using Common; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Data; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; + +namespace Root +{ + [Cmdlet(VerbsCommon.Get, "WorkflowAssociationsForSPO")] + public class CmdGetWorkflowAssociationsForSPO : PSCmdlet + { + private static List sitecollectionUrls = new List(); + //[Parameter(Mandatory = true, HelpMessage = "Credentials to login to SPO for InfoPath Online Assessment")] + ////[System.Management.Automation.PSCredential] + //[System.Management.Automation.CredentialAttribute()] + //PSCredential Credential; + private string assessmentScope; + [Parameter(Mandatory = true, ParameterSetName = "Credential")] + public PSCredential Credential; + + [Parameter(Mandatory = false, HelpMessage = "Specify the tenant name of your SPO site collections")] + public string TenantName; + + [Parameter(Mandatory = false, HelpMessage = "Specify the file path of a text file containing all SPO site collection URLs")] + public string SiteCollectionURLFilePath; + + [Parameter(Mandatory = true, HelpMessage = "Set this switch to $true if you would like to download the Workflows for detailed assessment")] + public bool DownloadWorkflows + { + get { return downloadWorkflows; } + set { downloadWorkflows = value; } + } + private bool downloadWorkflows; + + [Parameter(Mandatory = true, HelpMessage = @"The path where the Assessment Summary, logs, Workflows forms are downloaded (if DownloadWorkflow parameter is set to true) for analyzing (e.g. F:\temp\Workflows")] + public string AssessmentOutputFolder; + private string logFolderPath; + public DirectoryInfo logFolder; + + protected override void BeginProcessing() + { + //Create required folders + if (!Directory.Exists(string.Concat(AssessmentOutputFolder, @"\Logs"))) + { + logFolder = System.IO.Directory.CreateDirectory(string.Concat(AssessmentOutputFolder, @"\Logs")); + logFolderPath = logFolder.FullName; + Logging.LOG_DIRECTORY = logFolderPath; + Logging.GetInstance().WriteToLogFile(Logging.Info, "Log folder created"); + + } + else + { + logFolderPath = string.Concat(AssessmentOutputFolder, @"\Logs"); + Logging.LOG_DIRECTORY = logFolderPath; + } + base.BeginProcessing(); + } + protected override void EndProcessing() + { + base.EndProcessing(); + } + + protected override void ProcessRecord() + { + try + { + try + { + + if (String.IsNullOrEmpty(TenantName) && String.IsNullOrEmpty(SiteCollectionURLFilePath)) + { + WriteWarning("Provide either the Tenant Name or the Site Collection File containing SPO URLs !"); + } + else if (!String.IsNullOrEmpty(TenantName)) + { + assessmentScope = "Tenant"; + BeginToAssess(); + } + else + { + assessmentScope = "SiteCollection"; + BeginToAssess(); + } + + } + catch (Exception ex) + { + Host.UI.WriteLine(ConsoleColor.DarkRed, Host.UI.RawUI.BackgroundColor, ex.Message); + } + + } + catch (Exception ex) + { } + } + + protected void BeginToAssess() + { + GetWorkflowForSPOnline objSPOnline = new GetWorkflowForSPOnline(); + Operations ops = new Operations(); + try + { + string downloadXomlFolderPath = string.Concat(AssessmentOutputFolder, ops.downloadedFormsFolder); + //Scope level code getting addded + string userInput = string.Empty; + Console.WriteLine(System.Environment.NewLine); + Collection op = new Collection(); + List allSPOTenantSites = new List(); + + if (assessmentScope == "Tenant") + { + allSPOTenantSites = ops.GetAllTenantSites(TenantName, Credential); + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "The assessment is scoped to run at " + assessmentScope + +" level. There are altogether " + allSPOTenantSites.Count + " sites in your tenant. Would you like to proceed? [Y] to continue, [N] to abort."); + op = this.InvokeCommand.InvokeScript("Read-Host"); + userInput = op[0].ToString().ToLower(); + } + else + { + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "The assessment is scoped to run at " + assessmentScope + +" level. Would you like to proceed? [Y] to continue, [N] to abort."); + op = this.InvokeCommand.InvokeScript("Read-Host"); + userInput = op[0].ToString().ToLower(); + } + while (!userInput.Equals("y") && !userInput.Equals("n")) + { + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Invalid input. Press [Y] to continue, [N] to abort."); + op = this.InvokeCommand.InvokeScript("Read-Host"); + userInput = op[0].ToString().ToLower(); + } + if (userInput.Equals("y")) + { + DataTable dtWorkflowLocations = new DataTable(); + //Clear the collection before running + sitecollectionUrls.Clear(); + //Create Assessment output folders + ops.CreateDirectoryStructure(AssessmentOutputFolder); + if (assessmentScope == "Tenant") + { + sitecollectionUrls = allSPOTenantSites; + } + else + { + objSPOnline.ReadInfoPathOnlineSiteCollection(sitecollectionUrls, SiteCollectionURLFilePath); + } + if (sitecollectionUrls.Count == 0) + { + Host.UI.WriteLine(ConsoleColor.Red, Host.UI.RawUI.BackgroundColor, + string.Format("Site Collection URLs at {0} text file were empty, please update the text file with SPO Workflows site URL.", SiteCollectionURLFilePath)); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Site Collection URLs at {0} text file were empty, please update the text file with SPO Workflows site URL.", SiteCollectionURLFilePath)); + } + else + { + string csvFilePath = string.Concat(AssessmentOutputFolder, ops.summaryFolder, ops.summaryFile); + if (DownloadWorkflows) + { } + else + { + + objSPOnline.DownloadPath = AssessmentOutputFolder; + objSPOnline.DownloadForms = DownloadWorkflows; + dtWorkflowLocations = objSPOnline.Execute(Credential, sitecollectionUrls); + //Save the CSV file + ops.WriteToCsvFile(dtWorkflowLocations, csvFilePath); + } + } + } + else if (userInput.Equals("n")) + { + Host.UI.WriteLine(ConsoleColor.Cyan, Host.UI.RawUI.BackgroundColor, "Operation aborted as per your input !"); + } + + } + catch (Exception ex) + { + Host.UI.WriteLine(ConsoleColor.DarkRed, Host.UI.RawUI.BackgroundColor, ex.Message); + } + } + } +} diff --git a/Root/GetWorkflowForSPOnline.cs b/Root/GetWorkflowForSPOnline.cs new file mode 100644 index 0000000..d838ea6 --- /dev/null +++ b/Root/GetWorkflowForSPOnline.cs @@ -0,0 +1,649 @@ +using Common; +using Discovery; +using Microsoft.Online.SharePoint.TenantAdministration; +using Microsoft.SharePoint.Client; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Security; +using System.Text; +using System.Threading.Tasks; +using File = Microsoft.SharePoint.Client.File; + +namespace Root +{ + public class GetWorkflowForSPOnline + { + + /// + /// Open the site collection file and store in a collection variable + /// Read the file and display it line by line. + /// + /// + public void ReadInfoPathOnlineSiteCollection(List sitecollectionUrls, string filePath) + { + try + { + int counter = 0; + string line; + System.IO.StreamReader file = + new System.IO.StreamReader(filePath); + while ((line = file.ReadLine()) != null) + { + //removes all extra spaces etc. + sitecollectionUrls.Add(line.TrimEnd()); + //System.Console.WriteLine(line); + counter++; + } + file.Close(); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + private static readonly string FormBaseContentType = "0x010101"; + public DataTable dt = new DataTable(); + + /// + /// Discover all sites present in the tenant and save them into a collection + /// + /// + /// + /// + public List GetAllSPOTenantSites(string TenantName, PSCredential Credential) + { + List sites = new List(); + try + { + string tenantAdminUrl = "https://" + TenantName + "-admin.sharepoint.com/"; + ClientContext ctx = null; + ctx = CreateClientContext(tenantAdminUrl, Credential.UserName, Credential.Password); + var site = ctx.Site; + ctx.Load(site); + ctx.ExecuteQueryRetry(); + var web = site.RootWeb; + var list = web.Lists.GetByTitle("DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS"); + ctx.Load(list); + ctx.ExecuteQuery(); + //Console.WriteLine("List name :{0}", list.Title); + var camlQuery = new CamlQuery(); + var items = list.GetItems(camlQuery); + ctx.Load(items); + ctx.ExecuteQuery(); + foreach (var item in items) + { + //Console.WriteLine("Site Url {0}", item["SiteUrl"]); + if (item["SiteUrl"] != null) + sites.Add(item["SiteUrl"].ToString()); + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + //Console.WriteLine(ex.Message); + } + return sites; + + } + + public List GetAllTenantSites(string TenantName, PSCredential Credential) + { + List sites = new List(); + try + { + string tenantAdminUrl = "https://" + TenantName + "-admin.sharepoint.com/"; + ClientContext ctx = null; + ctx = CreateClientContext(tenantAdminUrl, Credential.UserName, Credential.Password); + Tenant tenant = new Tenant(ctx); + SPOSitePropertiesEnumerable siteProps = tenant.GetSitePropertiesFromSharePoint("0", true); + ctx.Load(siteProps); + ctx.ExecuteQuery(); + int count = 0; + foreach (var site in siteProps) + { + sites.Add(site.Url); + count++; + } + Console.WriteLine("Total Site {0}", count); + return sites; + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + return sites; + } + /// + /// SPO + /// + public string DownloadPath { get; set; } + public bool DownloadForms { get; set; } + public DirectoryInfo analysisFolder; + public DirectoryInfo downloadedFormsFolder; + public DirectoryInfo summaryFolder; + + public void FindWorkflows(List sitecollectionUrls, PSCredential Credential) + { + try + { + foreach (string url in sitecollectionUrls) + { + ClientContext siteClientContext = null; + siteClientContext = CreateClientContext(url, Credential.UserName, Credential.Password); + using (siteClientContext) + { + bool hasPermissions = false; + + try + + { + Console.WriteLine(string.Format("Processing: " + url)); + siteClientContext.ExecuteQueryRetry(); + hasPermissions = true; + } + catch (System.Net.WebException webException) + { + Console.WriteLine(string.Format(webException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.StackTrace); + } + catch (Microsoft.SharePoint.Client.ClientRequestException clientException) + { + Console.WriteLine(string.Format(clientException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.StackTrace); + } + catch (Microsoft.SharePoint.Client.ServerUnauthorizedAccessException unauthorizedException) + { + Console.WriteLine(string.Format(unauthorizedException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.StackTrace); + } + + if (!hasPermissions) + continue; + Console.WriteLine(string.Format("Attempting to fetch all the sites and sub sites of " + url)); + //WriteVerbose("Trying to get all the sites and subsites of : " + url); + IEnumerable expandedSites = siteClientContext.Site.GetAllSubSites(); + + foreach (string site in expandedSites) + { + //Console.WriteLine(string.Format("Going into " + site)); + //WriteVerbose("Going into " + site); + using (ClientContext ccWeb = siteClientContext.Clone(site)) + { + try + { + FindWorkflowPerSite(ccWeb); + //FindInfoPathFormsPerSite(ccWeb); + } + catch (Microsoft.SharePoint.Client.ServerUnauthorizedAccessException unauthorizedException) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.StackTrace); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message.ToString() + " on " + url); + Console.WriteLine(string.Format(unauthorizedException.Message.ToString() + " on " + url)); + //WriteWarning(unauthorizedException.Message.ToString() + " on " + url); + } + } + } + } + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + + + public void FindWorkflowPerSite(ClientContext cc) + { + try + { + var site = cc.Site; + cc.Load(site); + cc.ExecuteQueryRetry(); + + var web = cc.Web; + cc.Load(web); + cc.ExecuteQueryRetry(); + + //Host.UI.WriteLine(ConsoleColor.DarkMagenta, Host.UI.RawUI.BackgroundColor, web.Title); + WorkflowManager.Instance.LoadWorkflowDefaultActions(); + + WorkflowDiscovery wfDisc = new WorkflowDiscovery(); + wfDisc.DiscoverWorkflows(cc, dt); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + /// + /// + /// + /// + /// + /// + /// + internal ClientContext CreateClientContext(string url, string username, SecureString password) + { + try + { + var credentials = new SharePointOnlineCredentials( + username, + password); + + return new ClientContext(url) + { + Credentials = credentials + }; + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + return new ClientContext(url) + { + }; + } + + + } + + internal DataTable FindInfoPathFormsPerSite(ClientContext cc) + { + int counter = 0; + //DataTable dt = new DataTable(); + try + { + var site = cc.Site; + cc.Load(site); + cc.ExecuteQueryRetry(); + + var web = cc.Web; + cc.Load(web); + cc.ExecuteQueryRetry(); + + + var lists = cc.Web.GetListsToScan(showHidden: true); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Started Scanning site {0}", site.Url)); + + foreach (var list in lists) + { + try + { + cc.Load(list); + cc.ExecuteQueryRetry(); + if (list.BaseTemplate == (int)ListTemplateType.XMLForm || + (!string.IsNullOrEmpty(list.DocumentTemplateUrl) && list.DocumentTemplateUrl.EndsWith(".xsn", StringComparison.InvariantCultureIgnoreCase)) + ) + { + try + { + DataRow row = dt.NewRow(); + + File file = GetFileId(cc, list.DocumentTemplateUrl); + if (file != null) + { + row["IpID"] = file.UniqueId; + } + // Form libraries depend on InfoPath + + row["SiteColID"] = site.Id; + row["SiteURL"] = site.Url; + row["WebID"] = web.Id; + row["WebURL"] = web.Url; + row["ListorLibID"] = list.Id; + row["RelativePath"] = list.RootFolder.ServerRelativeUrl + "/Forms"; + row["IpTemplateName"] = Path.GetFileName(list.DocumentTemplateUrl); + row["InfoPathUsage"] = "FormLibrary"; + //row["FileName"] = list.Properties.FieldValues["_ipfs_solutionName"].ToString(); + row["ItemCount"] = list.ItemCount; + dt.Rows.Add(row); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Found InfoPath Forms Library {0}", list.DefaultViewUrl)); + counter++; + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message.ToString() + " on " + web.Url); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + #region contentType Code + /* + else if (list.BaseTemplate == (int)ListTemplateType.DocumentLibrary || list.BaseTemplate == (int)ListTemplateType.WebPageLibrary) + { + try + { + // verify if a form content type was attached to this list + cc.Load(list, p => p.ContentTypes.Include(c => c.Id, c => c.DocumentTemplateUrl)); + //cc.Load(list); + cc.ExecuteQueryRetry(); + + var formContentTypeFound = list.ContentTypes.Where(c => c.Id.StringValue.StartsWith(FormBaseContentType, StringComparison.InvariantCultureIgnoreCase)).OrderBy(c => c.Id.StringValue.Length).FirstOrDefault(); + if (formContentTypeFound != null) + { + // Form libraries depend on InfoPath + DataRow row = dt.NewRow(); + if (formContentTypeFound.DocumentTemplateUrl.EndsWith(".xsn")) + { + File file = GetFileId(cc, list, formContentTypeFound.DocumentTemplateUrl); + if (file != null) + { + row["IpID"] = file.UniqueId; + } + } + row["SiteColID"] = site.Id; + row["SiteURL"] = site.Url; + row["WebID"] = web.Id; + row["WebURL"] = web.Url; + row["ListorLibID"] = list.Id; + row["RelativePath"] = list.RootFolder.ServerRelativeUrl; + row["InfoPathUsage"] = "ContentType"; + row["IpTemplateName"] = Path.GetFileName(formContentTypeFound.DocumentTemplateUrl); + //row["FileName"] = list.Properties.FieldValues["_ipfs_solutionName"].ToString(); + row["ItemCount"] = list.ItemCount; + dt.Rows.Add(row); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Found Content Type {0}", formContentTypeFound.DocumentTemplateUrl)); + counter++; + } + + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + */ + #endregion + else if (list.BaseTemplate == (int)ListTemplateType.GenericList) + { + try + { + Folder folder = cc.Web.GetFolderByServerRelativeUrl($"{list.RootFolder.ServerRelativeUrl}/Item"); + cc.Load(folder, p => p.Properties); + cc.ExecuteQueryRetry(); + + if (folder.Properties.FieldValues.ContainsKey("_ipfs_infopathenabled") && folder.Properties.FieldValues.ContainsKey("_ipfs_solutionName")) + { + bool infoPathEnabled = true; + if (bool.TryParse(folder.Properties.FieldValues["_ipfs_infopathenabled"].ToString(), out bool infoPathEnabledParsed)) + { + infoPathEnabled = infoPathEnabledParsed; + } + // Form libraries depend on InfoPath + if (infoPathEnabled) + { + DataRow row = dt.NewRow(); + string templateUrl = list.RootFolder.ServerRelativeUrl + "/Item/" + folder.Properties["_ipfs_solutionName"]; + File file = GetFileId(cc, templateUrl); + if (file != null) + { + row["IpID"] = file.UniqueId; + } + row["SiteColID"] = site.Id; + row["SiteURL"] = site.Url; + row["WebID"] = web.Id; + row["WebURL"] = web.Url; + row["ListorLibID"] = list.Id; + row["InfoPathUsage"] = "GenericList"; + row["RelativePath"] = list.RootFolder.ServerRelativeUrl + "/Item"; + row["IpTemplateName"] = folder.Properties["_ipfs_solutionName"]; + row["ItemCount"] = list.ItemCount; + dt.Rows.Add(row); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Found Generic List InfoPath form {0}", list.DefaultViewUrl)); + counter++; + + } + } + } + catch (ServerException ex) + { + if (((ServerException)ex).ServerErrorTypeName == "System.IO.FileNotFoundException") + { + // Ignore + } + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message.ToString() + " on " + web.Url); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message.ToString() + " on " + web.Url); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Found a total of {0} InfoPath forms in site {1}", counter, web.Url)); + Logging.GetInstance().WriteToLogFile(Logging.Info, string.Format("Completed Scanning site {0}", site.Url)); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + //counter = 0; + return dt; + } + + private static File GetFileId(ClientContext cc, string documentTemplateUrl) + { + //Guid fileId = new Guid(); + File file = null; + try + { + var spfileLocation = String.Concat(documentTemplateUrl); + + file = cc.Web.GetFileByServerRelativeUrl(spfileLocation); + // Then getting the file using the server-relative Url of the web object + cc.Load(file); + cc.ExecuteQuery(); + + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message.ToString() + " on " + documentTemplateUrl); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return file; + } + + public void CreateDataTableColumns(DataTable dt) + { + try + { + dt.Columns.Add("SiteColID"); + dt.Columns.Add("SiteURL"); + dt.Columns.Add("CreatedBy"); + dt.Columns.Add("ModifiedBy"); + dt.Columns.Add("ListTitle"); + dt.Columns.Add("ListUrl"); + dt.Columns.Add("ContentTypeId"); + dt.Columns.Add("ContentTypeName"); + dt.Columns.Add("ItemCount"); + dt.Columns.Add("Scope"); + dt.Columns.Add("Version"); + dt.Columns.Add("WFTemplateName"); + dt.Columns.Add("IsOOBWorkflow"); + dt.Columns.Add("RelativePath"); + dt.Columns.Add("WFID"); + dt.Columns.Add("WebID"); + dt.Columns.Add("WebURL"); + //dt.Columns.Add("ListorLibID"); + //dt.Columns.Add("RelativePath"); + //dt.Columns.Add("IpTemplateName"); + //dt.Columns.Add("InfoPathUsage"); + //dt.Columns.Add("IpID"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + + public DataTable Execute(PSCredential Credential, List sitecollectionUrls) + { + try + { + Logging.GetInstance().WriteToLogFile(Logging.Info, "Starting to analyze SharePoint Online environment"); + + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("Starting to analyze SharePoint Online environment"); + CreateDataTableColumns(dt); + //FindInfoPathForms(sitecollectionUrls, Credential); + FindWorkflows(sitecollectionUrls, Credential); + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + Logging.GetInstance().WriteToLogFile(Logging.Info, "TOTAL WORKFLOWS DISCOVERED : " + dt.Rows.Count.ToString()); + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("***********************************************************************"); + Console.WriteLine("TOTAL WORKFLOWS DISCOVERED : " + dt.Rows.Count.ToString()); + Console.WriteLine("***********************************************************************"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return dt; + } + + public void DownloadInfoPathForms(DataTable infopathFormLocations, PSCredential Credential) + { + try + { + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("***********************************************************************"); + Console.WriteLine("Beginning to download the InfoPath template forms locally.. "); + Console.WriteLine("***********************************************************************"); + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("Downloading forms...please wait.. "); + Console.WriteLine(System.Environment.NewLine); + + + + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + Logging.GetInstance().WriteToLogFile(Logging.Info, "Beginning to download the InfoPath template forms locally.. "); + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + + int formsDownloadCounter = 0; + string spfileLocation = string.Empty; + Operations ops = new Operations(); + foreach (DataRow infoPathFormLocation in infopathFormLocations.Rows) + { + try + { + spfileLocation = String.Concat(infoPathFormLocation["RelativePath"].ToString(), "/", infoPathFormLocation["IpTemplateName"].ToString()); + + ClientContext context = null; + context = CreateClientContext(infoPathFormLocation["WebURL"].ToString(), Credential.UserName, Credential.Password); + using (context) + { + List list = context.Web.GetListById(Guid.Parse(infoPathFormLocation["ListorLibID"].ToString())); + context.Load(list); + context.ExecuteQueryRetry(); + + var file = GetFileId(context, spfileLocation); + //var file = context.Web.GetFileByServerRelativeUrl(infoPathFormLocation["RelativePath"].ToString()); + //context.Load(file); + //context.ExecuteQuery(); + + string folderName = infoPathFormLocation["SiteColID"].ToString(); + //var dirInfo = System.IO.Directory.CreateDirectory(string.Concat(DownloadPath, @"\DownloadedForms", @"\", infoPathFormLocation["SiteColID"].ToString())); + var dirInfo = System.IO.Directory.CreateDirectory(string.Concat(DownloadPath, ops.downloadedFormsFolder, @"\", infoPathFormLocation["SiteColID"].ToString())); + string filename = file.Name; + + string filePath = string.Concat(DownloadPath, @"\DownloadedForms", @"\", infoPathFormLocation["SiteColID"].ToString(), @"\", infoPathFormLocation["IpID"].ToString(), "_", filename); + + //var dirInfo = System.IO.Directory.CreateDirectory(string.Concat(DownloadPath, @"\", infoPathFormLocation["SiteID"], @"\", infoPathFormLocation["WebID"].ToString())); + //string localfile = string.Concat(DownloadPath, @"\", infoPathFormLocation["SiteID"].ToString(), @"\", infoPathFormLocation["WebID"].ToString(), @"\", infoPathFormLocation["ListorLibID"].ToString(), "_", filename); + Logging.GetInstance().WriteToLogFile(Logging.Info, "Starting to download InfoPath located at " + list.DefaultViewUrl); + //Logging.GetInstance().WriteToLogFile(Logging.Info, "Downloading the form locallay to the location " + filePath); + try + { + //Downloading the file to the specified location + using (var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, spfileLocation)) + { + using (FileStream writeStream = System.IO.File.Open(filePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite)) + { + fileInfo.Stream.CopyTo(writeStream); + formsDownloadCounter++; + } + } + Logging.GetInstance().WriteToLogFile(Logging.Info, "Finished to download InfoPath located at " + list.DefaultViewUrl); + //Logging.GetInstance().WriteToLogFile(Logging.Info, "Finished to download InfoPath located at " + web.Url + "/" + list.DefaultViewUrl); + //Logging.GetInstance().WriteToLogFile(Logging.Info, "Download complete for the form located in " + spfileLocation); + + } + catch (Exception exception) + { + if (infoPathFormLocation["WebURL"] != null) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, exception.Message + " on " + infoPathFormLocation["WebURL"].ToString()); + } + Logging.GetInstance().WriteToLogFile(Logging.Error, exception.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, exception.StackTrace); + } + } + } + catch (Exception ex) + { + if (infoPathFormLocation["WebURL"] != null) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message + " on " + infoPathFormLocation["WebURL"].ToString()); + } + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + Console.WriteLine("Downloading forms complete !"); + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("***********************************************************************"); + Console.WriteLine("INFOPATH FORMS DOWNLOADED : " + formsDownloadCounter); + Console.WriteLine("***********************************************************************"); + Console.WriteLine(System.Environment.NewLine); + + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + Logging.GetInstance().WriteToLogFile(Logging.Info, "INFOPATH FORMS DOWNLOADED : " + formsDownloadCounter); + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + //Logging.GetInstance().WriteToLogFile(Logging.Info, "STARTING TO DOWNLOAD INFOPATH FORMS. TOTAL COUNT: " + infopathFormLocations.Rows.Count); + + //Load the Summary CSV to InfoPathFormLocations Collection + + //foreach (var location in infopathFormLocations) + + } + } +} diff --git a/Root/GetWorkflowsforOnPrem.cs b/Root/GetWorkflowsforOnPrem.cs new file mode 100644 index 0000000..62c66a9 --- /dev/null +++ b/Root/GetWorkflowsforOnPrem.cs @@ -0,0 +1,370 @@ +using Common; +using Discovery; +using Microsoft.SharePoint; +using Microsoft.SharePoint.Administration; +using Microsoft.SharePoint.Client; +using OfficeDevPnP.Core; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Management.Automation; +using System.Security; + +namespace Root +{ + public class GetWorkflowsforOnPrem + { + public string Url { get; set; } + public string Scope { get; set; } + //public string useExistingSummaryFile { get; set; } + public string userName { get; set; } + public string password { get; set; } + public bool OnPrem { get; set; } + public string DownloadPath { get; set; } + public bool DownloadForms { get; set; } + public string DomainName { get; set; } + public DirectoryInfo analysisFolder; + public DirectoryInfo downloadedFormsFolder; + public DirectoryInfo summaryFolder; + public DataTable dt = new DataTable(); + + //public DataTable Execute(PSCredential Credential) + public DataTable Execute() + { + List siteCollectionsUrl = new List(); + try + { + Logging.GetInstance().WriteToLogFile(Logging.Info, "Starting to analyze on-premise environment"); + CreateDataTableColumns(dt); + Console.WriteLine(System.Environment.NewLine); + Console.WriteLine("Starting to analyze on-premise environment"); + + //GetWorkflows(); + if (Scope == "Farm") + { + siteCollectionsUrl = QueryFarm(); + } + else if (Scope == "WebApplication") + { + siteCollectionsUrl = GetAllWebAppSites(); + } + else if (Scope == "SiteCollection") + { + siteCollectionsUrl.Add(Url); + } + //FindWorkflows(siteCollectionsUrl, Credential); + FindWorkflows(siteCollectionsUrl); + + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + Logging.GetInstance().WriteToLogFile(Logging.Info, "TOTAL WORKFLOWS DISCOVERED : " + dt.Rows.Count.ToString()); + Logging.GetInstance().WriteToLogFile(Logging.Info, "***********************************************************************"); + + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + return dt; + } + + public List GetAllWebAppSites() + { + List webAppSiteCollectionUrls = new List(); + try + { + SPWebApplication objWebApp = null; + objWebApp = SPWebApplication.Lookup(new Uri(Url)); + if (objWebApp == null) + { + Console.ForegroundColor = ConsoleColor.DarkMagenta; + Console.WriteLine("Unable to obtain the object for the Web Application URL provided. Check to make sure the URL provided is correct."); + Console.ForegroundColor = ConsoleColor.White; + Logging.GetInstance().WriteToLogFile(Logging.Error, "Unable to obtain the object for the Web Application URL provided. SPWebApplication.Lookup(new Uri(Url)) returned NULL"); + } + else + { + foreach (SPSite site in objWebApp.Sites) + { + webAppSiteCollectionUrls.Add(site.Url); + } + } + + + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return webAppSiteCollectionUrls; + } + + public List QueryFarm() + { + List farmSiteCollectionUrls = new List(); + try + { + Logging.GetInstance().WriteToLogFile(Logging.Info, "Starting to query the farm.."); + SPServiceCollection services = SPFarm.Local.Services; + foreach (SPService curService in services) + { + try + { + if (curService is SPWebService) + { + var webService = (SPWebService)curService; + if (curService.TypeName.Equals("Microsoft SharePoint Foundation Web Application")) + { + webService = (SPWebService)curService; + SPWebApplicationCollection webApplications = webService.WebApplications; + foreach (SPWebApplication webApplication in webApplications) + { + // WriteVerbose("Processing WebApplication " + webApplication.DisplayName); + if (webApplication != null) + { + if (false) + { + + } + else + { + foreach (SPSite site in webApplication.Sites) + { + try + { + farmSiteCollectionUrls.Add(site.Url); + //Console.Write("Gathering InfoPath form locations for Content DB " + contentDatabase.Name + "....."); + //QueryDatabases(contentDatabase.Name, contentDatabase.DatabaseConnectionString); + // Console.WriteLine("Done !"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + Console.WriteLine("Errored ! See log for details"); + } + } + } + } + } + } + } + + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + return farmSiteCollectionUrls; + } + //public void FindWorkflows(List sitecollectionUrls, PSCredential Credential) + public void FindWorkflows(List sitecollectionUrls) + { + try + { + foreach (string url in sitecollectionUrls) + { + ClientContext siteClientContext = null; + //siteClientContext = CreateClientContext(url,Credential,DomainName); + siteClientContext = CreateClientContext(url, userName,password, DomainName); + using (siteClientContext) + { + bool hasPermissions = false; + + try + + { + Console.WriteLine(string.Format("Processing: " + url)); + siteClientContext.ExecuteQueryRetry(); + hasPermissions = true; + } + catch (System.Net.WebException webException) + { + Console.WriteLine(string.Format(webException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, webException.StackTrace); + } + catch (Microsoft.SharePoint.Client.ClientRequestException clientException) + { + Console.WriteLine(string.Format(clientException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, clientException.StackTrace); + } + catch (Microsoft.SharePoint.Client.ServerUnauthorizedAccessException unauthorizedException) + { + Console.WriteLine(string.Format(unauthorizedException.Message.ToString() + " on " + url)); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message.ToString() + " on " + url); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.StackTrace); + } + + if (!hasPermissions) + continue; + Console.WriteLine(string.Format("Attempting to fetch all the sites and sub sites of " + url)); + //WriteVerbose("Trying to get all the sites and subsites of : " + url); + IEnumerable expandedSites = siteClientContext.Site.GetAllSubSites(); + + foreach (string site in expandedSites) + { + //Console.WriteLine(string.Format("Going into " + site)); + //WriteVerbose("Going into " + site); + using (ClientContext ccWeb = siteClientContext.Clone(site)) + { + try + { + FindWorkflowPerSite(ccWeb); + //FindInfoPathFormsPerSite(ccWeb); + } + catch (Microsoft.SharePoint.Client.ServerUnauthorizedAccessException unauthorizedException) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.StackTrace); + Logging.GetInstance().WriteToLogFile(Logging.Error, unauthorizedException.Message.ToString() + " on " + url); + Console.WriteLine(string.Format(unauthorizedException.Message.ToString() + " on " + url)); + //WriteWarning(unauthorizedException.Message.ToString() + " on " + url); + } + } + } + } + } + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + + public void FindWorkflowPerSite(ClientContext cc) + { + try + { + var site = cc.Site; + cc.Load(site); + cc.ExecuteQueryRetry(); + + var web = cc.Web; + cc.Load(web); + cc.ExecuteQueryRetry(); + + //Host.UI.WriteLine(ConsoleColor.DarkMagenta, Host.UI.RawUI.BackgroundColor, web.Title); + WorkflowManager.Instance.LoadWorkflowDefaultActions(); + + WorkflowDiscovery wfDisc = new WorkflowDiscovery(); + wfDisc.DiscoverWorkflows(cc, dt); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + } + } + + //internal ClientContext CreateClientContext(string url, string username, SecureString password, string domainName) + internal ClientContext CreateClientContext(string url, PSCredential Credential, string domainName) + { + ClientContext cc = null; + try + { + AuthenticationManager authManager = new AuthenticationManager(); + cc = authManager.GetNetworkCredentialAuthenticatedContext(url, Credential.UserName, Credential.Password, domainName); + Web web = cc.Web; + cc.Load(web, website => website.Title); + cc.ExecuteQuery(); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + return new ClientContext(url) + { + }; + } + return cc; + } + + internal ClientContext CreateClientContext(string url, string userName, string password, string domainName) + { + ClientContext cc = null; + try + { + AuthenticationManager authManager = new AuthenticationManager(); + cc = authManager.GetNetworkCredentialAuthenticatedContext(url, userName, password, domainName); + Web web = cc.Web; + cc.Load(web, website => website.Title); + cc.ExecuteQuery(); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + return new ClientContext(url) + { + }; + } + return cc; + } + + public void CreateDataTableColumns(DataTable dt) + { + try + { + dt.Columns.Add("SiteColID"); + dt.Columns.Add("SiteURL"); + dt.Columns.Add("CreatedBy"); + dt.Columns.Add("ModifiedBy"); + dt.Columns.Add("ListTitle"); + dt.Columns.Add("ListUrl"); + dt.Columns.Add("ContentTypeId"); + dt.Columns.Add("ContentTypeName"); + dt.Columns.Add("ItemCount"); + dt.Columns.Add("Scope"); + dt.Columns.Add("Version"); + dt.Columns.Add("WFTemplateName"); + dt.Columns.Add("IsOOBWorkflow"); + dt.Columns.Add("RelativePath"); + dt.Columns.Add("WFID"); + dt.Columns.Add("WebID"); + dt.Columns.Add("WebURL"); + //dt.Columns.Add("ListorLibID"); + //dt.Columns.Add("RelativePath"); + //dt.Columns.Add("IpTemplateName"); + //dt.Columns.Add("InfoPathUsage"); + //dt.Columns.Add("IpID"); + } + catch (Exception ex) + { + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.Message); + Logging.GetInstance().WriteToLogFile(Logging.Error, ex.StackTrace); + + } + } + + internal static void PopulateAdminAndOwnerColumns(ConcurrentDictionary siteScanResults, ConcurrentDictionary workflowScanResults) + { + foreach (var workflowScanResult in workflowScanResults) + { + if (siteScanResults.ContainsKey(workflowScanResult.Value.SiteColUrl)) + { + var siteScanResult = siteScanResults[workflowScanResult.Value.SiteColUrl]; + workflowScanResult.Value.Admins = siteScanResult.Admins; + workflowScanResult.Value.Owners = siteScanResult.Owners; + } + } + } + } +} diff --git a/Root/Properties/AssemblyInfo.cs b/Root/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5658bb6 --- /dev/null +++ b/Root/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Root")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Root")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c36a3ff3-1a6b-4acd-94fc-0bc798082603")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Root/Root.csproj b/Root/Root.csproj new file mode 100644 index 0000000..51187bb --- /dev/null +++ b/Root/Root.csproj @@ -0,0 +1,241 @@ + + + + + Debug + AnyCPU + {C36A3FF3-1A6B-4ACD-94FC-0BC798082603} + Library + Properties + Root + Microsoft.Services.WorkflowAssessment.Root + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + ..\packages\AngleSharp.0.9.9\lib\net45\AngleSharp.dll + + + ..\packages\Microsoft.Azure.ActiveDirectory.GraphClient.2.1.0\lib\portable-net4+sl5+win+wpa+wp8\Microsoft.Azure.ActiveDirectory.GraphClient.dll + + + ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll + + + ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll + + + ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll + + + ..\packages\Microsoft.Graph.1.9.0\lib\net45\Microsoft.Graph.dll + + + ..\packages\Microsoft.Graph.Core.1.9.0\lib\net45\Microsoft.Graph.Core.dll + + + ..\packages\Microsoft.IdentityModel.7.0.0\lib\net35\microsoft.identitymodel.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.5.2.4\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.5.2.4\lib\net451\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.5.2.4\lib\net451\Microsoft.IdentityModel.Tokens.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.Policy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.Client.TranslationServices.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Office.SharePoint.Tools.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.Online.SharePoint.Client.Tenant.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.ProjectServer.Client.dll + + + ..\packages\Microsoft.SharePoint.dll.15.0.4867.1000\lib\Microsoft.SharePoint\Microsoft.SharePoint.dll + True + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.DocumentManagement.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Publishing.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Runtime.Windows.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Search.Applications.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.Taxonomy.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.UserProfiles.dll + + + ..\packages\Microsoft.SharePointOnline.CSOM.16.1.20317.12000\lib\net45\Microsoft.SharePoint.Client.WorkflowServices.dll + + + ..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\SharePointPnPCoreOnline.3.24.2008.1\lib\net461\OfficeDevPnP.Core.dll + + + ..\packages\SharePointPnP.IdentityModel.Extensions.1.2.4\lib\net45\SharePointPnP.IdentityModel.Extensions.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.5.2.4\lib\net451\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Net.Http.4.3.1\lib\net46\System.Net.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + + ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + + + + + + + + + + + + + + + + + + + + {04a36617-4353-4779-92f9-36baffe6a5f6} + Common + + + {66180571-9292-4411-8b01-b31dce2cc0e8} + Discovery + + + + + Always + + + + \ No newline at end of file diff --git a/Root/app.config b/Root/app.config new file mode 100644 index 0000000..929bdbc --- /dev/null +++ b/Root/app.config @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Root/packages.config b/Root/packages.config new file mode 100644 index 0000000..a7dd370 --- /dev/null +++ b/Root/packages.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file