bin/SnsAdGroupMembers.xml

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>SnsAdGroupMembers</name>
    </assembly>
    <members>
        <member name="T:SnsAdGroupMembers.GetSnsAdGroupMembersPsModuleSettings">
            <summary>
            <para type="synopsis">Enumerates "SnsPsAdGroupMembers" PSModule Configuration.</para>
            <para type="description">Enumerates "SnsPsAdGroupMembers" PSModule Configuration.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Get-SnsAdGroupMembersPsModuleSettings Is Intended To Be Used Interactively By A User To Retrieve The PSModule
                Configuration From The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Get-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule. Then Sends Out The PSModule Configuration Object.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsPsModuleSetting Object With The Following Properties:
            </para>
            <para type="description">
                - "AutomationManagedAttribute" Property Of Type String. Represents The AD Attribute Name As It Is Seen In
                Attributes Tab Of "Active Directory Users and Computers" Management Console, Used To Indicate Whether Or Not An AD
                Group Is Automatically Managed. Whenever The Property Have No Value The Feature Is Disabled.
            </para>
            <para type="description">
                - "AutomationManagedValue" Property Of Type String. Represents The Value Which The PSModule Put In
                "AutomationManagedAttribute" To Indicate Whether Or Not An AD Group Is Automatically Managed. Whenever The
                Property Have No Value The Feature Is Disabled.
            </para>
            <para type="description">
                - "BlockRemovalPercent" Property Of Type Int32. Contains The Threshold In Percent About Block Automated Group
                Members Removal. In Case Of Organization Changes Or Other Reason, After The AD Accounts Synchronization From An HR
                System, It Might Happen That All The Members Of An Automated Group Match The Removal Logic. To Prevent The Removal
                Of All The Members From A Group "SnsPsAdGroupMembers" PSModule Evaluate The Number Of The Current Members, The
                Members Evaluated For Removal And Calculates Removal Percentage. In case The Removal Percentage Is Bigger Than The
                Value Specified In This Parameter, No Members Are Removed And The Issue Is Reported.
            </para>
            <para type="description">
                - "VerifyLeaversAccountDisabled" Property Of Type Boolean. Indicates Whether The AD Managed Group Configuration Is
                Verified About Bindings To Disabled AD Accounts. Disabling This Verification Will Stop The Events Generation When
                Either Group Notification Contact Or Exclusion Or Inclusion User Leave The Company And His / Hers AD Account Get
                Disabled On All AD Managed Groups. In That Case An IT Administrator Should Regularly Check The AD Managed Groups
                Configuration. To Prevent False Positive Report Events, This Verification Have To Be Disabled Whenever Either
                Notification Contacts Or Inclusions Or Exclusions Or AddLogic Or RemoveLogic Contains Shared Mailboxes.
            </para>
            <para type="description">
                - "VerifyLeaversOu" Property Of Type String Array. Contains An Array With DistinguishedName Parts Of The
                Organizational Units Where The Leavers Accounts Are Kept. According To The Best Practices, When A User Leave The
                Company, The AD Account Is Kept Disabled For Certain Period Of Time. Whenever The Process Include Moving The
                Leavers Accounts To A Dedicated OU This Features Comes In Handy. The PSModule Verifies The Groups Configuration
                About Bindings To AD Accounts Located In Those OU's, And Report That. This Is Very Useful Whenever
                "VerifyLeaversAccountDisabled" Feature Is Disabled. To Disable This Feature Assign Empty Array.
            </para>
            <para type="description">
                - "ReportPositionIssuesWithPrerequisiteGroups" Property Of Type Boolean. Indicates Whether The AD Managed Group
                Configuration Is Verified About AD Managed Groups Used As Input In Other AD Managed Groups Logic, And Whether The
                Prerequisite Group Is Managed After The Dependent One. When The Prerequisite Group Is Managed Beforehand, On The
                Dependent Group Management Will Have Up To Date Input. Otherwise The Dependent Group Will Be Updated Accordingly
                Earliest On The Next Management Schedule.
            </para>
            <para type="description">
                - "WarnAboutMissingLogic" Property Of Type Boolean. Indicates Whether The PSModule Will Throw Warnings Whenever An
                AD Managed Group Have Either AddLogic Or RemoveLogic Missing. Whenever You Have Groups Without Automatic Adding Or
                Removing, Disable This Verification To Avoid Unnecessary Report Events. For Example Whenever You Have Sensitive
                Groups You May Want To Automate Only The Removal From The Group And Using Formal Approval Process With Manual
                Adding. This Will Allow No Room For Forgotten Group Members When They Change Their Position Or Leave The Company.
            </para>
            <para type="description">
                - "MonthsToKeepProcessingEvents" Property Of Type Int32. Contains The Time Interval In Months To Keep The
                Processing Events Into The Statistics DataBase. As Processing Events Are Considered Events Related With The
                Processing Of The Groups Which Lead To Neither Group Members Modification Nor Groups Configuration Modification.
            </para>
            <para type="description">
                - "MonthsToKeepProvisioningEvents" Property Of Type Int32. Contains The Time Interval In Months To Keep The
                Provisioning Events Into The Statistics DataBase. As Provisioning Events Are Considered Events Related With Group
                Members Modification Or Group Configuration Modification.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Get-SnsAdGroupMembersPsModuleSettings -Verbose;
              </code>
              <para></para>
              <para>Enumerates The PSModule Configuration.</para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.GetSnsAdGroupMembersPsModuleSettings.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.GetSnsAdGroupMembersPsModuleSettings.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.AddSnsAdManagedGroupExclusion">
            <summary>
            <para type="synopsis">Add Specified AD Object As Managed Active Directory Group Explicit Exclusion.</para>
            <para type="description">Add Specified AD Object As Managed Active Directory Group Explicit Exclusion.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Add-SnsAdManagedGroupExclusion Is Intended To Be Used Interactively By A User To Add New Explicit Exclusion Into A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Explicit Exclusions Remain
                Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Add-SnsAdManagedGroupExclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Exclusions In Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Add-SnsAdManagedGroupExclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Add-SnsAdManagedGroupExclusion" CmdLet Loops Each Specified Group Entry And Add Each
                Specified Explicit Exclusion To Each Group. Whenever A Specified Explicit Exclusion Is Already Present In The AD
                Managed Group Configuration, A Warning Is Thrown. After The Adding Of All Explicit Exclusions To The Group
                Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupExclusion -Identity "Finance Department" `
                -Exclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Add It As Explicit Exclusion To AD Managed Group "Finance
                Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupExclusion -Identity "*Finance*" `
                -Exclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Add "John Smith" As A Explicit
                Exclusion. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will Be Thrown
                And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Add-SnsAdManagedGroupExclusion -Exclusion "John Smith";
              </code>
              <para></para>
              <para>
                Adds "John Smith" As Explicit Exclusion For All The AD Managed Groups Sent Via The Pipeline. Use This If You
                Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are
                Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario
                Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other
                Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupExclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupExclusion.Exclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Added In The List Of The Specified Managed Group Explicit Exclusions.</para>
            <para type="description">
                Explicit Exclusions Are Used When We Need To Not Add As Group Member An AD Object Which Does Match The
                AddLogic.
            </para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Exclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Exclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupExclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupExclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.ClearSnsAdManagedGroupExclusion">
            <summary>
            <para type="synopsis">Remove All Explicit Exclusions Associated With A Managed Active Directory Group.</para>
            <para type="description">Remove All Explicit Exclusions Associated With A Managed Active Directory Group.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Clear-SnsAdManagedGroupExclusion Is Intended To Be Used Interactively By A User To Remove All Explicit Exclusions
                Of A Managed AD Group Entry In The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Clear-SnsAdManagedGroupExclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Clear-SnsAdManagedGroupExclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Clear-SnsAdManagedGroupExclusion" CmdLet Loops Each Specified Group Entry And Remove
                All Explicit Exclusions Of Each Group. Whenever A Specified AD Managed Group Have No Explicit Exclusions, A
                Warning Is Thrown. After The Removing Of All Explicit Exclusions From The Group Configuration, The Group Object Is
                Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupExclusion -Identity "Finance Department";
              </code>
              <para></para>
              <para>
                Removes All Explicit Exclusions Of AD Managed Group "Finance Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupExclusion -Identity "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove All Explicit Exclusions
                Associated With It. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will Be
                Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Clear-SnsAdManagedGroupExclusion;
              </code>
              <para></para>
              <para>
                Removes All Explicit Exclusions Of All Sent Via The Pipeline AD Managed Groups. Use This If You Really Desperately
                Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are Sent Via The
                Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario Because
                Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other Words There
                Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupExclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupExclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupExclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.RemoveSnsAdManagedGroupExclusion">
            <summary>
            <para type="synopsis">Remove AD Object From A Managed Active Directory Group Explicit Exclusions.</para>
            <para type="description">Remove AD Object From A Managed Active Directory Group Explicit Exclusions.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Remove-SnsAdManagedGroupExclusion Is Intended To Be Used Interactively By A User To Remove An Explicit Exclusion
                Object From A Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Not Specified
                Explicit Exclusions Remain Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Remove-SnsAdManagedGroupExclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Exclusions In Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Remove-SnsAdManagedGroupExclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Remove-SnsAdManagedGroupExclusion" CmdLet Loops Each Specified Group Entry And Removes
                Each Specified Explicit Exclusion From Each Group. Whenever A Specified Explicit Exclusion Is Not Present In The
                AD Managed Group Configuration, A Warning Is Thrown. After The Removal Of All Explicit Exclusions From The Group
                Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupExclusion -Identity "Finance Department" `
                -Exclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Remove It From Explicit Exclusions Of AD Managed Group "Finance
                Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupExclusion -Identity "*Finance*" `
                -Exclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove "John Smith" From Its
                Explicit Exclusions List. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error
                Will Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Remove-SnsAdManagedGroupExclusion -Exclusion "John Smith";
              </code>
              <para></para>
              <para>
                Removes "John Smith" From The Explicit Exclusion List For All The AD Managed Groups Sent Via The Pipeline. Use
                This If You Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The
                Groups That Are Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In
                This Scenario Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects.
                With Other Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupExclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupExclusion.Exclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Removed From The List Of The Specified Managed Group Explicit Exclusions.</para>
            <para type="description">
                Explicit Exclusions Are Used When We Need To Not Add As Group Member An AD Object Which Does Match The
                AddLogic.
            </para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Exclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Exclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupExclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupExclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.SetSnsAdManagedGroupExclusion">
            <summary>
            <para type="synopsis">
                Set Specified AD Objects As Managed Active Directory Group Explicit Exclusions While Removing Any Existing Not
                Specified Explicit Exclusions.
            </para>
            <para type="description">
                Set Specified AD Objects As Managed Active Directory Group Explicit Exclusions While Removing Any Existing Not
                Specified Explicit Exclusions.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Set-SnsAdManagedGroupExclusion Is Intended To Be Used Interactively By A User To Set The Explicit Exclusions Of A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Not Specified Explicit
                Exclusions Are Removed.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Set-SnsAdManagedGroupExclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Exclusion "objectGUID" In
                Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Set-SnsAdManagedGroupExclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Set-SnsAdManagedGroupExclusion" CmdLet Loops Each Specified Group Entry And Sets The
                Specified Explicit Exclusions To Each Specified Group. Whenever A Specified Explicit Exclusion Is Already Present
                In The AD Managed Group Configuration, A Warning Is Thrown. Whenever An Existing Explicit Exclusion Is Not Present
                Among The Specified Explicit Exclusions, It Is Removed. Additionally To The Standard PowerShell "ShouldProcess"
                Method For Asking Confirmation, Is Implemented "ShouldContinue" Method For Asking The User For Confirmation.
                "ShouldContinue" Method Was Implemented To Ignore The "Force" Parameter Value With A Reason. Once Because The
                Users Often Ignore The Fact That The Existing Explicit Exclusions Will Be Removed, And Second Because The CmdLet
                Is Intended To Be Used Interactively Only. With Other Words You Will Never Need To Execute The CmdLet Within
                Automated Script Which Will Fail Because The Force Parameter Is Ignored By "Should Continue" Method. However In
                "ShouldContinue" Method Were Implemented "YesToAll" And "NoToAll" Responses Which Are Missing By Default. After
                The Processing Of The Explicit Exclusions Of The Group, The Group Object Is Normalized And Verified, Then Sent To
                The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupExclusion -Identity "Finance Department" `
                -Exclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Sets It As Explicit Exclusion For AD Managed Group "Finance
                Department" Removing Any Other Existing Explicit Exclusions.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupExclusion -Identity "*Finance*" `
                -Exclusion "John Smith";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Sets "John Smith" As An Explicit
                Exclusion Removing Any Other Existing Explicit Exclusions. In Case The Wildcard Value Matches More Than One AD
                Managed Group A Terminating Error Will Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Set-SnsAdManagedGroupExclusion -Exclusion "John Smith";
              </code>
              <para></para>
              <para>
                Sets "John Smith" As Explicit Exclusion For All The AD Managed Groups Sent Via The Pipeline Removing Any Other
                Existing Explicit Exclusions. Use This If You Really Desperately Need To Workaround The Errors From The Previous
                Example. To List And Verify The Groups That Are Sent Via The Pipeline Before Executing The CmdLet Is More Than A
                Good Idea. There Are No Errors In This Scenario Because Multiple Values Are Sent, Instead Of Specifying Single
                Value That Matches Multiple Objects. With Other Words There Is One To One Relation Between The Provided And
                Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupExclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupExclusion.Exclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Set In The List Of The Specified Managed Group Explicit Exclusions.</para>
            <para type="description">
                Explicit Exclusions Are Used When We Need To Not Add As Group Member An AD Object Which Does Match The
                AddLogic.
            </para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Exclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Exclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupExclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupExclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            <para type="description">The Parameter Does Not Affect The Call To "ShouldContinue" PowerShell Method.</para>
            <para type="description">After All This CmdLet Should Be Used Interactively.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.GetSnsAdManagedGroup">
            <summary>
            <para type="synopsis">Enumerates Managed Active Directory Group Configuration.</para>
            <para type="description">Enumerates Managed Active Directory Group Configuration.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Get-SnsAdManagedGroup Is Intended To Be Used Interactively By A User To Retrieve A Managed AD Group Configuration
                From The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Get-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Get-SnsAdManagedGroup" CmdLet Enumerates The Configuration Entries For Each Group
                Coming From The Pipeline Or Specified With "Identity" Parameter. If No Groups Are Specified Or Sent Through The
                Pipeline The CmdLet Enumerates All Enabled Managed AD Groups Configuration. The Add And Remove Logic Properties
                Are Normalized And The Matched AD Objects Are Verified Whether They Are Leavers If Any. The "Inclusions",
                "Exclusions" And "Notify" Properties Are Verified Whether They Contains Any Leavers. Then Each Individual Group
                Configuration Object Is Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup -Verbose;
              </code>
              <para></para>
              <para>Enumerates All Managed AD Group Configuration Objects From The PSModule Configuration.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup -Identity "Finance Department DL";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Group "Finance Department DL".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "Finance Department", "Sales Department";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Groups "Finance Department" And "Sales Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = "Finance Department DL", "Sales Department DL" | `
                Get-SnsAdManagedGroup -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Groups "Finance Department DL" And "Sales Department DL".
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.GetSnsAdManagedGroup.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description">If Omitted The CmdLet Will Get All Managed Groups.</para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.GetSnsAdManagedGroup.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.GetSnsAdManagedGroup.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.AddSnsAdManagedGroupInclusion">
            <summary>
            <para type="synopsis">Add Specified AD Object As Managed Active Directory Group Explicit Inclusion.</para>
            <para type="description">Add Specified AD Object As Managed Active Directory Group Explicit Inclusion.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Add-SnsAdManagedGroupInclusion Is Intended To Be Used Interactively By A User To Add New Explicit Inclusion Into A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Explicit Inclusions Remain
                Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Add-SnsAdManagedGroupInclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Inclusions In Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Add-SnsAdManagedGroupInclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Add-SnsAdManagedGroupInclusion" CmdLet Loops Each Specified Group Entry And Add Each
                Specified Explicit Inclusion To Each Group. Whenever A Specified Explicit Inclusion Is Already Present In The AD
                Managed Group Configuration, A Warning Is Thrown. After The Adding Of All Explicit Inclusions To The Group
                Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupInclusion -Identity "Finance Department" `
                -Inclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Add It As Explicit Inclusion To AD Managed Group "Finance
                Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupInclusion -Identity "*Finance*" `
                -Inclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Add "John Smith" As A Explicit
                Inclusion. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will Be Thrown
                And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Add-SnsAdManagedGroupInclusion -Inclusion "John Smith";
              </code>
              <para></para>
              <para>
                Adds "John Smith" As Explicit Inclusion For All The AD Managed Groups Sent Via The Pipeline. Use This If You
                Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are
                Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario
                Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other
                Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupInclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupInclusion.Inclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Added In The List Of The Specified Managed Group Explicit Inclusions.</para>
            <para type="description">Explicit Inclusions Are Used When We Need To Add An AD Object Which Do Not Match The AddLogic As Group Member.</para>
            <para type="description">Explicit Inclusion Objects External For The AD Domain Are Not Allowed.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Inclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Inclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupInclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupInclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.ClearSnsAdManagedGroupInclusion">
            <summary>
            <para type="synopsis">Remove All Explicit Inclusions Associated With A Managed Active Directory Group.</para>
            <para type="description">Remove All Explicit Inclusions Associated With A Managed Active Directory Group.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Clear-SnsAdManagedGroupInclusion Is Intended To Be Used Interactively By A User To Remove All Explicit Inclusions
                Of A Managed AD Group Entry In The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Clear-SnsAdManagedGroupInclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Clear-SnsAdManagedGroupInclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Clear-SnsAdManagedGroupInclusion" CmdLet Loops Each Specified Group Entry And Remove
                All Explicit Inclusions Of Each Group. Whenever A Specified AD Managed Group Have No Explicit Inclusions, A
                Warning Is Thrown. After The Removing Of All Explicit Inclusions From The Group Configuration, The Group Object Is
                Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupInclusion -Identity "Finance Department";
              </code>
              <para></para>
              <para>
                Removes All Explicit Inclusions Of AD Managed Group "Finance Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupInclusion -Identity "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove All Explicit Inclusions
                Associated With It. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will Be
                Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Clear-SnsAdManagedGroupInclusion;
              </code>
              <para></para>
              <para>
                Removes All Explicit Inclusions Of All Sent Via The Pipeline AD Managed Groups. Use This If You Really Desperately
                Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are Sent Via The
                Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario Because
                Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other Words There
                Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupInclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupInclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupInclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.RemoveSnsAdManagedGroupInclusion">
            <summary>
            <para type="synopsis">Remove AD Object From A Managed Active Directory Group Explicit Inclusions.</para>
            <para type="description">Remove AD Object From A Managed Active Directory Group Explicit Inclusions.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Remove-SnsAdManagedGroupInclusion Is Intended To Be Used Interactively By A User To Remove An Explicit Inclusion
                Object From A Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Not Specified
                Explicit Inclusions Remain Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Remove-SnsAdManagedGroupInclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Inclusions In Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Remove-SnsAdManagedGroupInclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Remove-SnsAdManagedGroupInclusion" CmdLet Loops Each Specified Group Entry And Removes
                Each Specified Explicit Inclusion From Each Group. Whenever A Specified Explicit Inclusion Is Not Present In The
                AD Managed Group Configuration, A Warning Is Thrown. After The Removal Of All Explicit Inclusions From The Group
                Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupInclusion -Identity "Finance Department" `
                -Inclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Remove It From Explicit Inclusions Of AD Managed Group "Finance
                Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupInclusion -Identity "*Finance*" `
                -Inclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove "John Smith" From Its
                Explicit Inclusions List. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error
                Will Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Remove-SnsAdManagedGroupInclusion -Inclusion "John Smith";
              </code>
              <para></para>
              <para>
                Removes "John Smith" From The Explicit Inclusion List For All The AD Managed Groups Sent Via The Pipeline. Use
                This If You Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The
                Groups That Are Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In
                This Scenario Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects.
                With Other Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupInclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupInclusion.Inclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Removed From The List Of The Specified Managed Group Explicit Inclusions.</para>
            <para type="description">Explicit Inclusions Are Used When We Need To Add An AD Object Which Do Not Match The AddLogic As Group Member.</para>
            <para type="description">Explicit Inclusion Objects External For The AD Domain Are Not Allowed.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Inclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Inclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupInclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupInclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.SetSnsAdManagedGroupInclusion">
            <summary>
            <para type="synopsis">
                Set Specified AD Objects As Managed Active Directory Group Explicit Inclusions While Removing Any Existing Not
                Specified Explicit Inclusions.
            </para>
            <para type="description">
                Set Specified AD Objects As Managed Active Directory Group Explicit Inclusions While Removing Any Existing Not
                Specified Explicit Inclusions.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Set-SnsAdManagedGroupInclusion Is Intended To Be Used Interactively By A User To Set The Explicit Inclusions Of A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Not Specified Explicit
                Inclusions Are Removed.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Set-SnsAdManagedGroupInclusion" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Explicit Inclusion "objectGUID" In
                Active Directory.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Set-SnsAdManagedGroupInclusion" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Set-SnsAdManagedGroupInclusion" CmdLet Loops Each Specified Group Entry And Sets The
                Specified Explicit Inclusions To Each Specified Group. Whenever A Specified Explicit Inclusion Is Already Present
                In The AD Managed Group Configuration, A Warning Is Thrown. Whenever An Existing Explicit Inclusion Is Not Present
                Among The Specified Explicit Inclusions, It Is Removed. Additionally To The Standard PowerShell "ShouldProcess"
                Method For Asking Confirmation, Is Implemented "ShouldContinue" Method For Asking The User For Confirmation.
                "ShouldContinue" Method Was Implemented To Ignore The "Force" Parameter Value With A Reason. Once Because The
                Users Often Ignore The Fact That The Existing Explicit Inclusions Will Be Removed, And Second Because The CmdLet
                Is Intended To Be Used Interactively Only. With Other Words You Will Never Need To Execute The CmdLet Within
                Automated Script Which Will Fail Because The Force Parameter Is Ignored By "Should Continue" Method. However In
                "ShouldContinue" Method Were Implemented "YesToAll" And "NoToAll" Responses Which Are Missing By Default. After
                The Processing Of The Explicit Inclusions Of The Group, The Group Object Is Normalized And Verified, Then Sent To
                The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupInclusion -Identity "Finance Department" `
                -Inclusion "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's objectGUID From AD And Sets It As Explicit Inclusion For AD Managed Group "Finance
                Department" Removing Any Other Existing Explicit Inclusions.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupInclusion -Identity "*Finance*" `
                -Inclusion "John Smith";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Sets "John Smith" As An Explicit
                Inclusion Removing Any Other Existing Explicit Inclusions. In Case The Wildcard Value Matches More Than One AD
                Managed Group A Terminating Error Will Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Set-SnsAdManagedGroupInclusion -Inclusion "John Smith";
              </code>
              <para></para>
              <para>
                Sets "John Smith" As Explicit Inclusion For All The AD Managed Groups Sent Via The Pipeline Removing Any Other
                Existing Explicit Inclusions. Use This If You Really Desperately Need To Workaround The Errors From The Previous
                Example. To List And Verify The Groups That Are Sent Via The Pipeline Before Executing The CmdLet Is More Than A
                Good Idea. There Are No Errors In This Scenario Because Multiple Values Are Sent, Instead Of Specifying Single
                Value That Matches Multiple Objects. With Other Words There Is One To One Relation Between The Provided And
                Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupInclusion.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupInclusion.Inclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Set In The List Of The Specified Managed Group Explicit Inclusions.</para>
            <para type="description">Explicit Inclusions Are Used When We Need To Add An AD Object Which Do Not Match The AddLogic As Group Member.</para>
            <para type="description">Explicit Inclusion Objects External For The AD Domain Are Not Allowed.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Inclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Inclusions
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupInclusion.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupInclusion.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            <para type="description">The Parameter Does Not Affect The Call To "ShouldContinue" PowerShell Method.</para>
            <para type="description">After All This CmdLet Should Be Used Interactively.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.AddSnsAdManagedGroupContact">
            <summary>
            <para type="synopsis">Add Specified Email As Managed Active Directory Group Notification Contact.</para>
            <para type="description">Add Specified Email As Managed Active Directory Group Notification Contact.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Add-SnsAdManagedGroupContact Is Intended To Be Used Interactively By A User To Add New Notification Contact Into A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Notification Contacts Remain
                Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Add-SnsAdManagedGroupContact" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Notification Contact Emails In Active
                Directory. Whenever An Email Exists It Is Amended With The PrimarySmtpAddress Of The AD Object, In Case The Email
                Does Not Exists In The AD No Errors Are Thrown Allowing Recipients From Other Domains And External For The
                Organization Recipients. In Case The User Specifies A Value Different Than SMTP Address And The CmdLet Cannot
                Enumerate The PrimarySmtpAddress Of The AD Object An Error Is Thrown.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Add-SnsAdManagedGroupContact" CmdLet Initializes The PSModule Configuration. Verifies
                The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell
                Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Add-SnsAdManagedGroupContact" CmdLet Loops Each Specified Group Entry And Add Each
                Specified Notification Contact To Each Group. Whenever A Specified Notification Contact Is Already Present In The
                AD Managed Group Configuration, A Warning Is Thrown. After The Adding Of All Notification Contacts To The Group
                Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupContact -Identity "Finance Department DL" `
                -Contact "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD And Add The Address As Notification Contact For AD Managed
                Group "Finance Department DL".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupContact -Identity "Finance Department DL" `
                -Contact "John Smith", "john.smith@outlook.com" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD, "john.smith@outlook.com" Address Remains Unverified, And Add
                Both Addresses As Notification Contacts For AD Managed Group "Finance Department DL". Thus way John Smith Will
                Receive Notifications Both In His Corporate And Private Mailbox. Not Saying It Is A Good And Secure Practice, It
                Is Just Demonstration That It Is Doable, And How Can Be Done.
              </para>
              <para>
                When Users From Other AD Domains In Multi Domain Forest Have To Be Added As Notification Contacts, Must Be Used
                Their Email Address. The CmdLet Will Not Be Able To Enumerate Their Accounts Outside Of The Current Domain.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Add-SnsAdManagedGroupContact -Identity "*Finance*" `
                -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Add "John Smith" As A
                Notification Contact. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will
                Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Add-SnsAdManagedGroupContact -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Adds "John Smith" As Notification Contact For All The AD Managed Groups Sent Via The Pipeline. Use This If You
                Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are
                Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario
                Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other
                Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupContact.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupContact.Contact">
            <summary>
            <para type="description">Specifies A Recipient For The Group Related Audit Reports.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SMTP Email Address. Can Be Used For External Recipients. Does Not Support Wildcard Characters.</para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Contacts Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Contacts
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupContact.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.AddSnsAdManagedGroupContact.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.ClearSnsAdManagedGroupContact">
            <summary>
            <para type="synopsis">Removes All Notification Contacts Associated With A Managed Active Directory Group.</para>
            <para type="description">Removes All Notification Contacts Associated With A Managed Active Directory Group.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Clear-SnsAdManagedGroupContact Is Intended To Be Used Interactively By A User To Remove All Notification Contacts
                Of A Managed AD Group Entry In The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Clear-SnsAdManagedGroupContact" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Clear-SnsAdManagedGroupContact" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Clear-SnsAdManagedGroupContact" CmdLet Loops Each Specified Group Entry And Remove All
                Notification Contacts Of Each Group. Whenever A Specified AD Managed Group Have No Notification Contacts, A
                Warning Is Thrown. After The Removing Of All Notification Contacts From The Group Configuration, The Group Object
                Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupContact -Identity "Finance Department";
              </code>
              <para></para>
              <para>
                Removes All Notification Contacts Of AD Managed Group "Finance Department".
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Clear-SnsAdManagedGroupContact -Identity "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove All Notification Contacts
                Associated With It. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will Be
                Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Clear-SnsAdManagedGroupContact;
              </code>
              <para></para>
              <para>
                Removes All Notification Contacts Of All Sent Via The Pipeline AD Managed Groups. Use This If You Really
                Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are Sent
                Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario
                Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other
                Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupContact.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupContact.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.ClearSnsAdManagedGroupContact.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.RemoveSnsAdManagedGroupContact">
            <summary>
            <para type="synopsis">Removes Specified Notification Contacts From Specified Managed Active Directory Group Configuration.</para>
            <para type="description">Removes Specified Notification Contacts From Specified Managed Active Directory Group Configuration.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Remove-SnsAdManagedGroupContact Is Intended To Be Used Interactively By A User To Remove A Notification Contact
                From A Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Not Specified
                Notification Contacts Remain Intact.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Remove-SnsAdManagedGroupContact" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Notification Contact Emails In Active
                Directory. Whenever An Email Exists It Is Amended With The PrimarySmtpAddress Of The AD Object, In Case The Email
                Does Not Exists In The AD No Errors Are Thrown Allowing Recipients From Other Domains And External For The
                Organization Recipients. In Case The User Specifies A Value Different Than SMTP Address And The CmdLet Cannot
                Enumerate The PrimarySmtpAddress Of The AD Object An Error Is Thrown.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Remove-SnsAdManagedGroupContact" CmdLet Initializes The PSModule Configuration.
                Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other
                PowerShell Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Remove-SnsAdManagedGroupContact" CmdLet Loops Each Specified Group Entry And Remove
                Each Specified Notification Contact From Each Group. Whenever A Specified Notification Contact Is Not Present In
                The AD Managed Group Configuration, A Warning Is Thrown. After The Removing Of All Specified Notification Contacts
                From The Group Configuration, The Group Object Is Normalized And Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupContact -Identity "Finance Department" `
                -Contact "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD And Remove The Address From AD Managed Group "Finance
                Department" Notification Contacts.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupContact -Identity "Finance Department" `
                -Contact "John Smith", "john.smith@outlook.com" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD, "john.smith@outlook.com" Address Remains Unverified, And
                Remove Both Addresses From AD Managed Group "Finance Department" Notification Contacts.
              </para>
              <para>
                When Users From Other AD Domains In Multi Domain Forest Have To Be Removeed As Notification Contacts, Must Be Used
                Their Email Address. The CmdLet Will Not Be Able To Enumerate Their Accounts Outside Of The Current Domain.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroupContact -Identity "*Finance*" `
                -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Remove "John Smith" From Group's
                Notification Contacts. In Case The Wildcard Value Matches More Than One AD Managed Group A Terminating Error Will
                Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Remove-SnsAdManagedGroupContact -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Removes "John Smith" From All The Sent Via The Pipeline AD Managed Groups Notification Contacts. Use This If You
                Really Desperately Need To Workaround The Errors From The Previous Example. To List And Verify The Groups That Are
                Sent Via The Pipeline Before Executing The CmdLet Is More Than A Good Idea. There Are No Errors In This Scenario
                Because Multiple Values Are Sent, Instead Of Specifying Single Value That Matches Multiple Objects. With Other
                Words There Is One To One Relation Between The Provided And Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupContact.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupContact.Contact">
            <summary>
            <para type="description">Specifies A Recipient To Remove From The Group Related Audit Reports.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SMTP Email Address.</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroupContact</para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Notification Contact It Will Throw Error.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Contacts Will Be Removeed From The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Contacts
                Will Be Removeed From All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupContact.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroupContact.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.SetSnsAdManagedGroupContact">
            <summary>
            <para type="synopsis">
                Set Specified Emails As Managed Active Directory Group Notification Contact While Removing Any Existing
                Notification Contacts.
            </para>
            <para type="description">
                Set Specified Emails As Managed Active Directory Group Notification Contact While Removing Any Existing
                Notification Contacts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Set-SnsAdManagedGroupContact Is Intended To Be Used Interactively By A User To Set The Notification Contacts Of A
                Managed AD Group Entry In The Configuration DataBase. In The Process Any Existing Notification Contacts Are
                Removed.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Set-SnsAdManagedGroupContact" CmdLet Enumerates The AD Managed Group Objects
                Corresponding To The Specified Group Identities And Verifies The Specified Notification Contact Emails In Active
                Directory. Whenever An Email Exists It Is Amended With The PrimarySmtpAddress Of The AD Object, In Case The Email
                Does Not Exists In The AD No Errors Are Thrown Allowing Recipients From Other Domains And External For The
                Organization Recipients. In Case The User Specifies A Value Different Than SMTP Address And The CmdLet Cannot
                Enumerate The PrimarySmtpAddress Of The AD Object An Error Is Thrown.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Set-SnsAdManagedGroupContact" CmdLet Initializes The PSModule Configuration. Verifies
                The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell
                Processes Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Set-SnsAdManagedGroupContact" CmdLet Loops Each Specified Group Entry And Sets The
                Specified Notification Contacts To Each Specified Group. Whenever A Specified Notification Contact Is Already
                Present In The AD Managed Group Configuration, A Warning Is Thrown. Whenever An Existing Notification Contact Is
                Not Present Among The Specified Notification Contacts, It Is Removed. Additionally To The Standard PowerShell
                "ShouldProcess" Method For Asking Confirmation, Is Implemented "ShouldContinue" Method For Asking The User For
                Confirmation. "ShouldContinue" Method Was Implemented To Ignore The "Force" Parameter Value With A Reason. Once
                Because The Users Often Ignore The Fact That The Existing Notification Contacts Will Be Removed, And Second
                Because The CmdLet Is Intended To Be Used Interactively Only. With Other Words You Will Never Need To Execute The
                CmdLet Within Automated Script Which Will Fail Because The Force Parameter Is Ignored By "Should Continue" Method.
                However In "ShouldContinue" Method Were Implemented "YesToAll" And "NoToAll" Responses Which Are Missing By
                Default. After The Processing Of The Notification Contacts Of The Group, The Group Object Is Normalized And
                Verified, Then Sent To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupContact -Identity "Finance Department" `
                -Contact "John Smith" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD And Sets The Address As Notification Contact For AD Managed
                Group "Finance Department" Removing Any Other Existing Notification Contacts.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupContact -Identity "Finance Department" `
                -Contact "John Smith", "john.smith@outlook.com" -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates John Smith's PrimarySmtpAddress From AD, "john.smith@outlook.com" Address Remains Unverified, And Set
                Both Addresses As Notification Contacts For AD Managed Group "Finance Department" Removing Any Other Existing
                Notification Contacts.
              </para>
              <para>
                When Users From Other AD Domains In Multi Domain Forest Have To Be Added As Notification Contacts, Must Be Used
                Their Email Address. The CmdLet Will Not Be Able To Enumerate Their Accounts Outside Of The Current Domain.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroupContact -Identity "*Finance*" `
                -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Managed Group "Finance Department" And Sets "John Smith" As A
                Notification Contact Removing Any Other Existing Notification Contacts. In Case The Wildcard Value Matches More
                Than One AD Managed Group A Terminating Error Will Be Thrown And The Request Will Be Not Completed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Get-SnsAdManagedGroup "*Finance*";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Managed Groups That Match The Wildcard Pattern.
              </para>
              <para></para>
              <para></para>
              <code>
                $arrGrs;
              </code>
              <para></para>
              <para>Lists On The Host Window The Enumerated AD Managed Groups.</para>
              <para></para>
              <para></para>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = $arrGrs | Set-SnsAdManagedGroupContact -Contact "John Smith";
              </code>
              <para></para>
              <para>
                Sets "John Smith" As Notification Contact For All The AD Managed Groups Sent Via The Pipeline Removing Any Other
                Existing Notification Contacts. Use This If You Really Desperately Need To Workaround The Errors From The Previous
                Example. To List And Verify The Groups That Are Sent Via The Pipeline Before Executing The CmdLet Is More Than A
                Good Idea. There Are No Errors In This Scenario Because Multiple Values Are Sent, Instead Of Specifying Single
                Value That Matches Multiple Objects. With Other Words There Is One To One Relation Between The Provided And
                Processed Objects.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupContact.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupContact.Contact">
            <summary>
            <para type="description">Specifies Recipients For The Group Related Audit Reports.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SMTP Email Address. Can Be Used For External Recipients. Does Not Support Wildcard Characters.</para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not
                Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Contacts Will Be Added To The Specified Group.</para>
            <para type="description">
                In Case Multiple Values Are Specified And Multiple Managed AD Groups Are Specified, All Specified Contacts
                Will Be Added To All Specified Groups.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupContact.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroupContact.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            <para type="description">The Parameter Does Not Affect The Call To "ShouldContinue" PowerShell Method.</para>
            <para type="description">After All This CmdLet Should Be Used Interactively.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.InvokeSnsAdGroupMembersManage">
            <summary>
            <para type="synopsis">Invokes Automatic Active Directory Group Membership Management.</para>
            <para type="description">Invokes Automatic Active Directory Group Membership Management.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Invoke-SnsAdGroupMembersManage Is Intended To Be Used Both Interactively By A User, To Test A Specific AD Managed
                Group Configuration, And Within Automation Scripts Run On A Schedule As A Service For Actual AD Managed Groups
                Members Management.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description">
                NOTE: The Automation Scripts That Use This CmdLet Must Be Run With An Active Directory Service Account Which Must
                Have Sufficient Access Rights To Add Group Members, Remove Group Members And Modify Active Directory Attributes Of
                The AD Group Objects. The Same Applies To The Users Who Run The CmdLet Interactively.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validations "Invoke-SnsAdGroupMembersManage" CmdLet Enumerates The AD Managed Group Configuration
                Objects Corresponding To Any Specified Group Identities. When Value Is Provided To "Identity" Parameter The CmdLet
                Switches To "WhatIf" Mode Automatically. When Actual Group Members Management Needs To Be Performed, The CmdLet
                Shall Be Run Without "Identity" Parameter. Thus Way No Groups Will Be Skipped From Members Management, Except The
                Explicitly Disabled Ones.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Invoke-SnsAdGroupMembersManage" CmdLet Initializes The PSModule Configuration,
                Verifies The Availability And The Accessibility Of The Active Directory, Verifies The Existence, The Schema And
                The Integrity Of The Configuration And Statistics DataBases. Imports, Validates, And Normalizes The Managed
                Groups, Groups Explicit Inclusions, Groups Explicit Exclusions And Groups Notification Contacts Configuration.
                Those Are Stored In Different DataBase Tables Within The Configuration DataBase.
            </para>
            <para type="description"></para>
            <para type="description">
                The Verifications And Normalizations Made On "Groups" Configuration Are:
            </para>
            <para type="description">
                - Verifies About Invalid Values In Enabled Column And If There Are Any The Are Replaced With Disabled. Because
                SQLite Does Not Have Native Boolean Type, We Are Using Integers As Representation Of Booleans, Where 0 Is False 1
                Is True. Since We Are Using Column With Type Integer It Allows All Integers, Not Just 0 And 1. Therefore In Case
                Of Manual Intervention Of The DataBase Using GUI Or CLI Tools, The Data Can Be Manipulated To Cause Errors In The
                Module. Therefore The CmdLet Replaces All Values Which Are Not 0 Or 1 With 0. Using GUI Or CLI Tools To Directly
                Access The PSModule DataBases Is Not Recommended. Do It At Your Own Risk!!!
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "GroupGuid" And "GroupCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "AddLdapQuery" And "RemoveLdapQuery" Columns Simultaneously. Obviously If
                We Not Manage The Group Members The Group Is Not Managed And Have No Place In The Managed Groups Configuration.
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "GroupGuid" Using LDAP Search With The Value In The "GroupCn".
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "AddLdapQuery" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "RemoveLdapQuery" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "GroupGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Replaces ":Expand:", ":Band", ":Band", ":Bor" And ":Bor" Strings If Present With The Actual LDAP Operator In
                "AddLdapQuery" And "RemoveLdapQuery" Columns.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "GroupGuid" Column. All Managed GroupGuid's Should Be Already Enumerated
                On The Previous Steps.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "GroupGuid" Column Which Does Not Match The GUID Syntax. All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" So Far If Their
                Values Are Correct.
            </para>
            <para type="description">
                - Deletes Any Duplicate Entries If There Are Any. Normally The CmdLets Would Not Allow Duplicates, If We Have Such
                It Is Manual Intervention Directly In The DataBase Using Third Party GUI Or CLI Tools. As I Wrote Above Doing So
                Is Not Recommended And If You Do, Do It At Your Own Risk.
            </para>
            <para type="description">
                - Updates The "GroupCn" Columns With The Actual CN Of The Group. The "GroupCn" Is Used For Reporting, Obviously We
                Need The Reporting To Work As Expected With The Correct Values Since The Very Beginning. There Might Be Renamed
                Groups Since The Previous CmdLet Execution. Of Course The Cache Is Used As Well, And If The PSSession Is Kept
                Started Since Before The Rename The Caching Might Lead To Unexpected Results.
            </para>
            <para type="description">
                - Reorder The Managed Groups Positions, In A Way So They Start From 0 And Are Consequent. Because The
                Pre-Processing Above Might Delete Configuration Entries, Might Lead To Empty Position Numbers. The Group Position
                Determine The Order In Which The Groups Will Be Managed. Which Might Be Important In Case A Group Logic Uses The
                Membership Of Another Group.
            </para>
            <para type="description">
                It Sounds Not Logical To Manage Group Membership Based On The Membership In Another Group, However Certain
                Features In Azure Does Not Work With Nested Groups, Such As Granting Azure Roles And Scope Groups For Certain
                Azure Apps, Like Single Sign On And Provisioning Apps For Third Party Cloud Solutions. Therefore To Achieve The
                Nesting Effect Without Using Nesting, Management Of Groups Based On The Membership Of Other Groups Is Required.
                For Example, We Have A Company With Two Branches, Headquarters In New York And Second Site In London. We Have HRs
                In Both Sites. We Create Two Distribution Lists "New York HRs" And "London HRs" Both Automatically Managed With
                Very Complex Add And Remove Logics. We Need To Make Another Group "All HRs". Normally We Would Nest The Existing
                Groups Into The New One. However We Need This Group To Be AADConnect Synced To Azure And Allow Single Sign On To
                Workday For Example, Whose SSO App Cannot Work With Nested Groups. In That Case Instead To Repeat The Very Complex
                Logics For The HR Groups Created For Each Site, And Overload The Used Domain Controller, We Can Use More Simplified
                Add LDAP Query Like:
            </para>
            <para type="description">
                &#40;|&#40;memberOf=CN=New York HRs,OU=Groups,DC=contoso,DC=com&#41;&#40;memberOf=CN=London HRs,OU=Groups,DC=contoso,DC=com&#41;&#41;
            </para>
            <para type="description">
                Remove LDAP Query:
            </para>
            <para type="description">
                &#40;&#38;&#40;!&#40;memberOf=CN=New York HRs,OU=Groups,DC=contoso,DC=com&#41;&#41;&#40;!&#40;memberOf=CN=London HRs,OU=Groups,DC=contoso,DC=com&#41;&#41;&#41;
            </para>
            <para type="description">
                By Doing So, We Add To The "All HRs" Group The Direct Members Of "New York HRs" And "London HRs". Here The Groups
                Processing Order Comes To Place. If The "All HRs" Group Have Less Order Position Than The Other Two Site Related
                Groups, It Will Get As Input Outdated Info. For Example There Might Be A New HR Which Is Waiting To Be Added In
                "London HRs" Group. Normally He Will Be Added On The Same CmdLet Run. However He Have To Wait Till The Next CmdLet
                Run To Be Added To "All HRs" Group, Because It Is Already Processed. If "All HRs" Group Is Processed After The Two
                Site Related HRs Groups, It Will Have Up To Date Input. Because The User Is Already Added To "London HRs" Group.
                And The User Will Be Added In The "All HRs" Group In The Same CmdLet Execution.
            </para>
            <para type="description">
                Issues With The Order Positions Whenever A Prerequisite Group Have Higher Order Position Than The Evaluated Ones
                Are Reported With Warning In The Internal Report. While The Cases When A Prerequisite Group Is Not Automatically
                Managed Are Not Reported. The Reason Is That There Are Certain Cases Where Certain Groups Cannot Be Automated.
                Because Their Management Requires Procedures To Be Followed Related With Either Approvals Or Documenting Or
                Requirements For Tickets. In That Cases Such Groups Membership Cannot Be Managed Via This CmdLet. However Those
                Groups Membership Can Be Used As Input For Other Automated Groups. In That Case, We Do Not Need Warnings In The
                Reports, That We Can Do Nothing About. For Example We Might Have Requirement To Use Fine-Grained Password Policy,
                To Enforce Higher Password Length Requirements For The Administrators. The Fine-Grain Policy Can Be Assigned Only
                On Global Security Groups. Unlike Domain Admins Enterprise Admins And Schema Admins Are Universal Security Groups
                And Cannot Be Added Into Fine-Grained Policy Directly. Those Groups Membership Might Require Approval Process, And
                Generally, You Do Not Want To Automate Their Membership. However To Address The Password Length Requirement, Can
                Be Created Global Security Group "Admin Password Policy" Added To The Fine-Grained Policy And Managed Via This
                CmdLet, To Add The Members Of The "Enterprise Admins" And "Schema Admins". Yes, Those People Could Remove Them
                Selves Manually From "Admin Password Policy", But The Automation Jobs Will Add Them Again. Sooner Or Later They
                Will Stop Removing Themselves, They Cannot Be So Quick As An Automation Job Could Be.
            </para>
            <para type="description">
                The CmdLet Can Be Used For Either Adding Members Only Or Removing Members Only Or Both Adding And Removing
                Members. Managed Groups Configuration Entries Are Deleted When Both Adding And Removing Are Missing. At The End Of
                The Day, In The Scenario Above, We Might Want, All The Leavers To Be Automatically Removed From "Domain Admins” As
                Soon As Their Labor Contract Is Ended. In That Case We Can Manage "Domain Admins" Group With Only Removal Logic,
                Made To Remove All Disabled Accounts. Adding Members To Be Not Automated And Instead To Be Followed An Approval
                Process. If You Do So With Such An Important Group, Please Make Sure You Have An Account Which Is Not Synchronized
                From The HR System, Just In Case To Be Able To Recover The AD Domain, If That Sync Become Mad And Disables All The
                Accounts.
            </para>
            <para type="description">
                The Example With The HR Groups Above Shows Another Use Case Scenario When Might Be Needed Group Membership Input
                For Managing The Membership Of Another Group. As It Is Mentioned The Site Groups Are Distribution Lists Only,
                While The "All HR's" Is Intended For Granting Access Rights. Nesting OF Distribution Lists Into Security Group
                Will Not Grant The Access Rights To Their Members. To Use Nesting They Have To Be Converted To Mail-Enabled
                Security Groups, Something We Actually Might Want To Avoid.
            </para>
            <para type="description">
                NOTE: There Are Not Any Checks About Valid Values In "GroupGuid" Column. Normally They Have To Be Populated By The
                CmdLets For Managing Of The Groups Configuration. In Case AD Group Objects Get Deleted, Their objectGUID Will Be
                Not Verified In The Preprocessing Stage. Instead It Will Be Verified And Reported Properly When The Group Members
                Management Is Made. The Purpose Of The Preprocessing Above Is To Ensure Consistent Data For The ProcessRecord
                Method. Normally Those Pre-Processing Actions Should Do Nothing Because The Configuration Data Is Verified And
                Created Using The CmdLets. Therefore The Purpose Of Those Pre-Processing Tasks Is To Ensure That In Case Of Manual
                Intervention On The Configuration Data, The CmdLet Will Do Whatever It Can To Restore The Data Integrity And
                Reduce The Damage Caused By Messing With The Configuration.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The Verifications And Normalizations Made On "Inclusions" Configuration Are:
            </para>
            <para type="description">
                - Verifies About Invalid Values In Enabled Column And If There Are Any The Are Replaced With Disabled.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "GroupGuid" And "GroupCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "InclusionGuid" And "InclusionCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "GroupGuid" Using LDAP Search With The Value In The "GroupCn".
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "InclusionGuid" Using LDAP Search With The Value In The "InclusionCn".
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "GroupGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "InclusionGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "GroupGuid" Column. All Managed GroupGuids Had To Be Enumerated So Far.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "InclusionGuid" Column. All InclusionGuids Had To Be Enumerated So Far.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "GroupGuid" Column Which Does Not Match The GUID Syntax. By Now All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" If The Values Are
                Correct.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "InclusionGuid" Column Which Does Not Match The GUID Syntax. By Now All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" If The Values Are
                Correct.
            </para>
            <para type="description">
                - Updates The "GroupCn" Columns With The Actual CN Of The Group. The "GroupCn" Is Used For Reporting.
            </para>
            <para type="description">
                - Updates The "InclusionCn" Columns With The Actual CN Of The Group. The "InclusionCn" Is Used For Reporting.
            </para>
            <para type="description">
                - Checks And Deletes Any Orphaned Entries.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The Verifications And Normalizations Made On "Exclusions" Configuration Are:
            </para>
            <para type="description">
                - Verifies About Invalid Values In Enabled Column And If There Are Any The Are Replaced With Disabled.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "GroupGuid" And "GroupCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "ExclusionGuid" And "ExclusionCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "GroupGuid" Using LDAP Search With The Value In The "GroupCn".
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "ExclusionGuid" Using LDAP Search With The Value In The "ExclusionCn".
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "GroupGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "ExclusionGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "GroupGuid" Column. By Now All Managed GroupGuids Had To Be Enumerated.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "ExclusionGuid" Column. By Now All ExclusionGuids Had To Be Enumerated.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "GroupGuid" Column Which Does Not Match The GUID Syntax. By Now All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" If The Values Are
                Correct.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "ExclusionGuid" Column Which Does Not Match The GUID Syntax. By Now All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" If The Values Are
                Correct.
            </para>
            <para type="description">
                - Updates The "GroupCn" Columns With The Actual CN Of The Group. The "GroupCn" Is Used For Reporting.
            </para>
            <para type="description">
                - Updates The "ExclusionCn" Columns With The Actual CN Of The Group. The "ExclusionCn" Is Used For Reporting.
            </para>
            <para type="description">
                - Checks And Deletes Any Orphaned Entries.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The Verifications And Normalizations Made On "NotificationContacts" Configuration &#40;In The DataBase It Is
                "Contacts" Table&#41; Are:
            </para>
            <para type="description">
                - Verifies About Invalid Values In Enabled Column And If There Are Any The Are Replaced With Disabled.
            </para>
            <para type="description">
                - Deletes All Rows With Missing Data In "GroupGuid" And "GroupCn" Columns Simultaneously.
            </para>
            <para type="description">
                - Updates Any Rows With Missing Data In "GroupGuid" Using LDAP Search With The Value In The "GroupCn".
            </para>
            <para type="description">
                - Replaces Any DistinguishedName, And SID Values If Any In "GroupGuid" Column With The "objectGUID" Of Their
                Corresponding AD Object.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "GroupGuid" Column. By Now All Managed GroupGuids Had To Be Enumerated.
            </para>
            <para type="description">
                - Deletes Any Entries Without Values In "Email" Column.
            </para>
            <para type="description">
                - Deletes Any Entries With Values In "GroupGuid" Column Which Does Not Match The GUID Syntax. By Now All
                DistinguishedName Or SID Values Had To Be Replaced With Their Corresponding Objects "objectGUID" If The Values Are
                Correct.
            </para>
            <para type="description">
                - Updates The "GroupCn" Columns With The Actual CN Of The Group. The "GroupCn" Is Used For Reporting.
            </para>
            <para type="description">
                - Checks And Deletes Any Orphaned Entries.
            </para>
            <para type="description">
                NOTE: There Are Not Any Validations Of The Values In "Email" Column. Thus Way As Notification Contacts Can Be Used
                External For The AD Domain Recipients, For Example Recipients In Other Domains From The Same Forest Or External
                For The Organization Recipients. The Module Does Not Make Any Remote PSSessions To The On Premises Exchange /
                Hybrid Exchange Servers, And It Works For A Single Domain. Therefore The Module Cannot Validate Recipients Outside
                The Domain Where It Works.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                After The Configuration Preprocessing The Configuration DataBase Is Defragmented. Then The Statistics DataBase
                Path Is Enumerated, DataBase Existence Is Verified And The DataBase Schema Is Validated.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Invoke-SnsAdGroupMembersManage" CmdLet Enumerates The Configuration Entries For Each
                Group Coming From The Pipeline Or Specified With "Identity" Parameter. If No Groups Are Specified Or Sent Through
                The Pipeline The CmdLet Enumerates All Enabled Managed Groups Configuration. When Groups Are Either Specified Or
                Send Via Pipeline, The CmdLet Switch To "WhatIf" Mode. In That Case The "WhatIf" "Add" And "Remove" Events Are
                Included In The Notification Contacts Report. Normally They Are Not Included Because It Is Report Only Mode And No
                Membership Is Changed On The Groups. This Was Introduced To Avoid Forwarding Of The Internal Reports To The Group
                Contacts When Collaborating With Them On The Managed Group Configuration. The Internal Report Contains Events
                About All Managed Groups Which Is Not OK To Be Forwarded To Contacts Not Related With The Groups. Specifying
                "WhatIf" When Identity Is Supplied Will Not Revert The Default "WhatIf" Behavior, And "WhatIf" Events Will Remain
                Included In The Notification Contacts Reports For The Currently Processed Groups.
            </para>
            <para type="description">
                As Per The Best Practices The CmdLet Provides The User With Visual Feedback Of The Progress That Is Being Made In
                A Progress Bar. To Improve The CmdLet Performance That Feedback Is Provided Only Whenever The CmdLet Is Executed
                In Interactive PSSession. About Even More In Depth Feedback Related With The CmdLet Progress, Please Use "Verbose"
                Parameter.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Each Of The Managed Groups Are Processed In A Loop, And The Following Actions Are Performed On Each Of Them:
            </para>
            <para type="description"></para>
            <para type="description">
                - Creates Or Updates A Provisioning Start Entry In The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description">
                - Enumerates Managed Group DistinguishedName And Email. Normally At This Stage The Group Is Already Present In The
                Internal Cache.
            </para>
            <para type="description"></para>
            <para type="description">
                - Updates The Predefined AD Attribute Of The Managed Group With Predefined Constant String Intended For Easy
                Recognizing The Automatically Managed From The Manually Managed AD Groups. This Feature Is Disabled By Default. It
                Can Be Enabled By Defining An AD Attribute And Constant String Using "Set-SnsAdGroupMembersPsModuleSettings"
                CmdLet.
            </para>
            <para type="description"></para>
            <para type="description">
                - Verifies Managed Group Explicit Exclusions. Enumerates Each Exclusion Entry DistinguishedName, This Way
                Verifying The Exclusion Entry Existence. In Case Enumeration Fails The Exclusion Entry Is Not Processed. And This
                Is Reported To The Group Notification Contacts. In Case The Enumerated Exclusion DistinguishedName Contains Either
                ",OU=Leavers," Or ",OU=Disabled Users," Or The AD Account Is Disabled, Warnings Are Thrown Accordingly And The
                Issue Is Reported To The Notification Contacts As Well. In Those Cases The Exclusion Entry Is Processed Which
                Might Lead To NDR's Reverted To The Senders Who Send Emails To The Managed Group. The Verified Values Are Compared
                With The Values From The Previous CmdLet Execution And If They Are Changed An Event Is Included Into Notification
                Contacts Report. Thus Way The Notification Contacts Are Informed That The Exclusions Are Modified Since The
                Previous CmdLet Execution.
            </para>
            <para type="description"></para>
            <para type="description">
                - Verifies Managed Group Explicit Inclusions. The Verification Is Made Exactly In The Same Manner Like The
                Explicit Exclusions.
            </para>
            <para type="description"></para>
            <para type="description">
                - Verifies Managed Group Notification Contacts. Enumerates The DistinguishedName Of Each Contact Using The
                Following LDAP Query "&#40;|&#40;mail=[Mail]&#41;&#40;proxyAddresses=smtp:[Mail]&#41;&#41;" In Case The Distinguished Name Is Not
                Enumerated No Actions Are Taken. We Need To Preserve The Functionality For External Contacts As Well. In Case The
                Recipient Is Enumerated The Notification Contact Is Updated With The Value Taken From Recipients "mail" Attribute
                If It Is Different. Thus Way When A Notification Contact Change Hers / His Email, The Configuration Will Be
                Updated Automatically With The New Email Address &#40;Of Course If The Best Practices To Leave The Old Address As
                Secondary For Certain Period Of Time Are Followed&#41;. Afterward The Distinguished Name Is Evaluated Whether The
                Object Is Leaver. The CmdLet Behavior Is Slightly Different Here. Along With The Warning It Includes The Leavers
                Manager Taken From "manager" Attribute As A Notification Contact. When Changes Are Detected, In Recipients For The
                Notification Contacts Report Are Included Both The Old And The New Recipients.
            </para>
            <para type="description"></para>
            <para type="description">
                - Verifies Whether Managed Group "Add" And "Remove" Queries Rely On Other Managed Groups. If There Are Any
                Dependency Relations, Their Order Position Are Checked And Whenever Prerequisite Groups Are Processed After The
                Currently Evaluated One, Warnings Are Thrown. This Feature Can Be Disabled Using
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet.
            </para>
            <para type="description"></para>
            <para type="description">
                - Verifies Managed Group "Add" And "Remove" Queries About Direct Binding To An AD Object Using DistinguishedName
                And Throw Warning. Normally The Inclusions And Exclusions Can Be Achieved With Proper LDAP Query. At The Same Time
                This Overcomplicate The Query And Creates Additional Overhead On The Used Domain Controller.
            </para>
            <para type="description">
                Let's Explain That With An Example. Let's Assume You Need A Group That Will Include Specific Team That Is Managed
                By A Certain Manager, And You Need To Include A Person Who Reports To A Different Manager. Then Part Of The LDAP
                Query Would Look Like:
            </para>
            <para type="description">
                "&#40;|&#40;manager=CN=John Smith,CN=Users,DC=contoso,DC=com&#41;&#40;distinguishedName=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;&#41;"
            </para>
            <para type="description">
                Please Keep In Mind That The Build In "Users" Is Container, Not OU. The LDAP Query Could Be Furter Really
                Complicated With Other Requirements Like The Members To Be Active Employes, To Have Mailbox, To Be Not Contingent
                Workers And etc. This Will Lead All The Requirements To Be Evaluated Multiple Times Because The Query Contains
                "OR". Using Explicit Inclusion From The LDAP Query Would Be Removed:
            </para>
            <para type="description">
                "&#40;distinguishedName=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                And The "OR" Operator. This Example Is About One Inclusion, What If The Explicit Inclusions Were 10? The Same
                Applies About The Exclusions. This Evaluation Cannot Be Disabled.
            </para>
            <para type="description"></para>
            <para type="description">
                - Enumerates The Current Members Of The Managed Group. The Enumeration Of The Members Happens With LDAP Query.
            </para>
            <para type="description">
                Binding To The Managed Group Object And Enumeration Of Its "member" Attribute Value Does Not Work For Groups With
                Large Number Of Members, Because There Is An AD Limitation About The Number Of Reverted Objects. The Limitation
                Depends On The AD Functional Level When The First Domain Controller Was Promoted. The Consequent Increase Of The
                Domain Functional Level Does Not Increase That Limitation. If You Are Interested How To Increase It Research In
                Internet. The PSModule Overcomes That Limitation Using LDAP Search, Where It Can Managed The Number Of Reverted
                Objects. This Slows Down The PSModule But There Is No Need To Modify The AD Configuration Partition Using
                "ADSIEdit".
            </para>
            <para type="description">
                NOTE: The LDAP Query Used To Enumerate The Managed Group Members Does Not Consider The Members Of The Nested
                Groups. Thus Way If An Object Is Member Of A Nested Group And Not Member Of The Managed Group Directly Will Be
                Considered As Not Member And If Meets The Requirements To Be A Member Will Be Added Later. Using Such An
                Automation For Group Members Management With The Time Makes Group Nesting Into The Managed Groups Not Feasible,
                And Sooner Or Later You'll Stop Nesting In The Managed Groups. However Pay Extra Attention When You Create The
                Remove LDAP Query And Use Nesting, To Avoid The Nested Groups Removal.
            </para>
            <para type="description">
                Nesting Is Used To Simplify The Group Members Management And Reduce The Administrative Effort For That. However
                When You Are Using An Automation There Is Not Any Administrative Effort For The Group Members Management. Not
                Using Nesting In The Managed Groups Is Rather Related With The Convenience Of The IT's And Simplifying Any
                Possible Troubleshooting. The Nesting Does Not Affect The PSModule.
            </para>
            <para type="description"></para>
            <para type="description">
                - Normalizes The "Add" LDAP Query:
            </para>
            <para type="description">
                -- In Case There Is No "Add" Query Specified Throws Warning That No Automatic Members Adding Will Be Made. This
                Feature Can Be Disabled Using "Set-SnsAdGroupMembersPsModuleSettings" CmdLet.
            </para>
            <para type="description">
                -- Evaluates The "Add" Query About String Representation Of "objectGUID" Values And Replaces Them With The
                DistinguishedName Of The Actual AD Objects. In Case An Enumerated "objectGUID" Cannot Be Found In AD, Throws Error
                That This Object Does Not Exists. Every Error On That Phase Stops Any Further Processing Of The Specific Managed
                Group Only. In Case The Enumerated AD Object Is Identified As Leaver Or Is Located In "Disabled Users" OU Warnings
                Are Thrown. They Do Not Prevent The Further Processing Of The Managed Group. The Normalization Is Made In A Loop
                Until All String Representations Of "objectGUID" Values In The LDAP Query Are Evaluated And Replaced.
            </para>
            <para type="description">
                -- Verifies And Reports About Any Changes In The Managed Group "Add" Logic. This Verification Happens After The
                LDAP Query Normalization And All The "objectGUID" Values Are Already Replaced With Their Corresponding
                DistinguishedName. In Case An Object Is Renamed Or Moved Into Different OU There Will Be Event Notifying The
                Notification Contacts About Change In The Add Logic. I Personally Do Not Consider This As False Positive, Rather
                As Expected Behavior. Moreover Having DistinguishedName Instead Of GUID In The Event Text Makes More Sense For The
                Notification Contacts.
            </para>
            <para type="description"></para>
            <para type="description">
                - Enumerates The AD Objects Eligible To Be Added Via LDAP Search Using The Following LDAP Query:
            </para>
            <para type="description">
                "&#40;&#38;&#40;objectCategory=person&#41;&#40;objectClass=user&#41;[AddQuery]&#40;!&#40;memberOf=[GroupDN]&#41;&#41;&#41;"
            </para>
            <para type="description">
                Thus Way The AD Search Reverts Only User Accounts Who Meet The Adding Criteria And Are Not Direct Members Of The
                Managed Group. This Ignores Any Nested Group Members And They Are Present In The AD Search Output. The LDAP Query
                Is Limited To AD User Accounts Only.
            </para>
            <para type="description">
                Normally All HR Tools Are Not Aware Of The AD Groups, Therefore The Synchronization Tools Do Not Sync AD Groups
                From The HR Systems. The Same Applies To The AD Contact Objects, They Are External Recipients And It Is Not
                Expected To Be Present In The HR Systems. Therefore It Is Better To Add That Kind Of Objects Manually As Group
                Members, Than Relying On Manually Updated Attributes. Managing Via Automation Of Those Kind Of Group Members Is
                Pointless. Whenever You Need To Make A Distribution List With All Contact Objects From Specific Supplier Or
                Customer, Is Better To Use Either One Time Single Liner PowerShell Script To Add Them Initially And Afterward
                Manage The Group Manually Or Make A Dynamic Distribution Group. Anyway The Contacts Management Would Be Always
                Manual, Since There Is Not Any Possibility The Required Input To Be Supplied From An External Partner.
            </para>
            <para type="description"></para>
            <para type="description">
                - In Case The Managed Group Have Explicit Inclusions, And Those Objects Are Not Already Members Of The Managed
                Group, They Are Added To The List With Eligible Objects That Will Be Added As Members Later. No Additional
                Verifications Are Made On The Inclusions At This Stage Except Whether They Are Not Already Members Of The Group.
                If They Are Already Added On Some Previous Execution Of The CmdLet We Do Not Need To Add Them Again And Report
                False Positives To The Notification Contacts.
            </para>
            <para type="description"></para>
            <para type="description">
                - In Case The Managed Group Have Explicit Exclusions And Those Exclusions Are Present In The List Of Objects For
                Adding, They Are Removed From The List. In Case There Are Exclusions Which Are Not Present In The List For Adding,
                They Are Reported With A Warning. The Purpose Of The Exclusions Feature Is To Not Add As Group Member An Object
                Who Meets The Adding Criteria. Therefore An Exclusion Who Does Not Meet The Adding Criteria Is Not Needed And Only
                Increases The Configuration Size, And Creates Overhead For The CmdLet Verifications.
            </para>
            <para type="description">
                NOTE: Because The Exclusions Are Managed After The Inclusions. In Case An Administrator Add The Same Object As
                Inclusion And As Exclusion Simultaneously, The Exclusion Will Take Precedence. It Is Another Topic Why Someone
                Will Do So. However This Will Not Create Additional Overhead Neither To The CmdLet Nor To AD, Because On The
                Second Verification Of The Same Object Everything Needed Will Be Already Cached.
            </para>
            <para type="description"></para>
            <para type="description">
                - Add All The Remaining Objects In The List For Adding As Group Members. On This Action Is Invoked The PowerShell
                "ShouldProcess" Method To Ask The User For Confirmation. Because The CmdLet Is Intended To Be Run In Automation
                Scripts The CmdLet Impact Is "Medium", Therefore The CmdLet Does Not Ask For Confirmation By Default. However
                "ShouldProcess" Does Provides Additional Useful Features Available To The User Automatically, Such As "WhatIf" And
                Other Functionalities. At The Same Time "Confirm" Parameter Remains Available And The User Might Decide To Use It
                When Testing Configuration Changes. Sometimes The Adding's That The CmdLet Might Process, Could Be A Lot,
                Especially When New Managed Group Entry Is Created. From That Perspective Confirmation Is Asked Once For Adding
                All The Accounts Which Needs To Be Added And Second Time For Removing All The AD Objects Which Needs To Be
                Removed. I Personally Found It Not Feasible To Be Asked For Confirmation About Each Individual Adding Or Removing.
            </para>
            <para type="description">
                Whenever The CmdLet Is Run Against All Managed Groups In "WhatIf" Mode, "WhatIf" Events Are Created For Each
                Individual Object And Added To The Internal Report. However When The CmdLet Is Called With Identity Specified
                Those "WhatIf" Events Are Added To The Notification Contacts Report As Well. Which Makes Sense Because Running The
                CmdLet With Identity Specified Is To Test Specific Managed Group Configuration, And Not Wait All The Groups To Be
                Processed, Therefore The Notification Contacts Will Receive Those Events, Instead Of Forwarding The Internal
                Report To The Requestor, Which Might Contain Events Related With Other Groups. Then Remains Only To Ask The
                Requestor To Confirm Whether The Actions That The CmdLet Would Take Are Correct And Exactly What Was Requested.
            </para>
            <para type="description"></para>
            <para type="description">
                - Normalizes The Remove LDAP Query:
            </para>
            <para type="description">
                -- In Case There Is No Remove Query Specified Throws Warning That No Automatic Members Removal Will Be Made. This
                Feature Can Be Disabled Using "Set-SnsAdGroupMembersPsModuleSettings" CmdLet.
            </para>
            <para type="description">
                -- Evaluates The Remove Query About String Representation Of "objectGUID" Values And Replaces Them With The
                DistinguishedName Of The Actual AD Objects. In Case An Enumerated "objectGUID" Cannot Be Found In AD, Throws Error
                That This Object Does Not Exists. Every Error On That Phase Stops Any Further Processing Of The Specific Managed
                Group Only. In Case The Enumerated AD Object Is Identified As Leaver Warnings Are Thrown. They Do Not Prevent The
                Further Processing Of The Managed Group. The Normalization Is Made In A Loop Until All String Representations Of
                "objectGUID" Values In The LDAP Query Are Evaluated.
            </para>
            <para type="description">
                -- Verifies And Reports About Any Changes In The Managed Group "Remove" Logic. This Verification Happens After The
                LDAP Query Normalization And All The "objectGUID" Values Are Already Replaced With Their Corresponding
                DistinguishedName. In Case An Object Is Renamed Or Moved Into Different OU There Will Be Event Notifying The
                Notification Contacts About Change In The Remove Logic.
            </para>
            <para type="description"></para>
            <para type="description">
                - Enumerates The AD Objects Eligible To Be Removed Via LDAP Search Using The Following LDAP Query:
            </para>
            <para type="description">
                "&#40;&#38;[RemoveQuery]&#40;memberOf=[GroupDn]&#41;&#41;"
            </para>
            <para type="description">
                Thus Way The AD Search Reverts Only AD Objects Who Meet The Removal Criteria And Are Direct Members Of The Managed
                Group. This Ignores Any Nested Group Members And They Are Not Present In The AD Search Output. If A Not Managed
                Group Is Nested In Managed Group, This Does Not Make It Managed. The LDAP Query Is Not Limited To AD User
                Accounts. You Have To Be Careful With The Remove Query To Not Accidentally Remove The Nested Groups If You Need To
                Preserve Them.
            </para>
            <para type="description"></para>
            <para type="description">
                - In Case The Managed Group Have Explicit Inclusions And Those Inclusions Are Present In The List Of Objects For
                Removal, They Are Removed From The List. In Case There Are Inclusions Which Are Not Present In The List For
                Removal, They Are Reported With A Warning. The Purpose Of The Inclusions Feature Is To Keep As Group Member An
                Object Who Meets The Removal Criteria. Therefore An Inclusion Who Does Not Meet The Removal Criteria Is Not Needed
                And Only Increases The Configuration Size, And Creates Overhead For The CmdLet Verifications. As It Was Written
                Above, This CmdLet And PSModule Do Allow Different Logic For Add Than The Logic For Removal. The Removal Logic Can
                Be Specified In A Way To Allow Members To Remain After They No Longer Meet The Adding Criteria, Or Manually Added
                Objects To Remain As Members. Which Makes Maintaining Of Inclusion List In Those Cases Unnecessary. Let's Clarify
                This With An Example. We Take The Example With The Two Sites From Above And We Create A Group Named "New York
                Employees" And "London Employees". Let's Assume That A Person John Smith Moves From New York To London. If We Do
                The Removal Logic Strict We Can Do It To Remove All The Account Which Are Disabled Or Not Located In New York. But
                Also We Might Make That Group To Remove Only The Leavers. In That Case When John Smith Relocate To London He Will
                Be Not Removed From The Group And We Will Have No Need To Maintain Inclusion List For The Group, Just Because John
                Wants To Remain Member Of "New York Employees". I Would Advise Strict Removal Logic For Distribution Lists Used
                For Distributing Sensitive Information, And Security Groups Used For Granting Access Rights. About Groups Used For
                Chit Chat I Would Advise Not So Strict Removal Logic And Remove Only The Leavers.
            </para>
            <para type="description"></para>
            <para type="description">
                - In Case The Managed Group Have Explicit Exclusions And Those Exclusions Are Not Present In The List With The
                Objects For Removal, And Are Currently Direct Members Of the Managed Group, They Are Added To The List For Removal.
            </para>
            <para type="description"></para>
            <para type="description">
                - Remove All The Remaining Objects In The List For Removal From The Group. On This Action Is Invoked The
                PowerShell "ShouldProcess" Method To Ask The User For Confirmation With The Same Behavior As Adding The Members.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "EndProcessing" Method "Invoke-SnsAdGroupMembersManage" CmdLet:
            </para>
            <para type="description"></para>
            <para type="description">
                - Queries The Active Directory About Any Groups That Contain The Predefined Value In The Predefined AD Attribute
                Used For Quick Distinct Of The Automatically Managed AD Groups. In Case A Search Result Group Is Not Enabled
                Managed Group, The AD Attribute Is Cleared. Therefore When A Group Is No Longer Managed Or Get Disabled, The Group
                Attribute Will Be Cleared Accordingly, So The Company IT's To Have Up To Date Information. This Action Is Not
                Performed When The Imported From The Configuration DataBase Group Configuration Is Incomplete, Those Are The Cases
                When We Supplied Identities To The CmdLet. This Action Is Not Performed When The CmdLet Is Running In "WhatIf"
                Mode Without Supplying Any Identities To The CmdLet As Well.
            </para>
            <para type="description"></para>
            <para type="description">
                - Clears The Outdated Entries In The Statistics DataBase. Events With Event Type Processing Are Kept For 2 Months.
                Events With Type Provisioning Are Kept For 14 Months. The Group Provisioning Entries Are Deleted When There Are No
                Longer Events Associated With Them. Which Results In: When Nothing Is Made On A Specific Group On That
                Provisioning Instance, The Group Entry Is Deleted After 2 Months, Otherwise The Group Entry Is Deleted After 14
                Months. Normally The Statistics DataBase Will Only Grow With The Time. To Prevent Any Low Disk Space Issues Or
                Performance Issues With The DataBase File, Outdated Entries Have To Be Deleted. This Deletion Is On DataBase Level
                Only, No DataBase File Compacting And Defragmentation Is Made, Because With The Statistics DataBase Growth Over
                The Time, The Defragmentation And Compacting Time Will Grow. This Might Increase With Hours, The Time Required The
                CmdLet To Complete, Which Is Not Acceptable.
            </para>
            <para type="description">
                If You Use A Physical Or Virtual Machine With Slow Disk System, Or You Manage Huge Number Of Groups, Performance
                Issues Still Might Happen. In That Case I Would Suggest First To Use "Invoke-SnsStatisticsDataBaseDefragmentation"
                To Compact The DataBase. If Compacting Do Not Help You Can Modify The Thresholds Using
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet.
            </para>
            <para type="description">
                The Statistics DataBase Defragmentation Locks The DataBase For Prolong Amount Of Time. If Automated Job For
                Production Group Members Management Is Executed During That Time, It Will Fail. I Would Recommend The Production
                Group Management Automations To Be Scheduled In A Way, To Allow Daily Or Weekly Maintenance. For Example, The
                Automation Job About Production Group Members Management To Be Scheduled From Monday To Saturday On Every 2 Hours.
                And Once Per Week In Sunday Morning To Be Run A Scheduled Task To Compact The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description">
                - Initializes And Sends To The Pipeline A "SnsReportCollection" Object. It Is Up To The User To Decide Whether The
                Reports Will Be Sent Over Emails Or Using Other Ways Of Distribution. If Emails Are Chosen What Will Be The
                Wording Of Those Emails, Any Company Brand Related Stationaries And Stylings, Which Report Columns To Include And
                Which To Filter. From That Perspective And Because Of The Best Practices, The Output Is Reverted In An Object.
                Because The CmdLet Produces Multiple Reports, It Reverts Single Object Which Combines The Reports Within Object
                Properties. The Output Object Have Properties Which Contains Collections Of Report Objects And Properties That
                Contain Collections Of Other Objects, That Combine Report Collections With Other Information:
            </para>
            <para type="description">
                -- "InternalReport" Property. Contains A Collection Of "SnsReport" Objects Intended For The Use Of The Company
                IT's And The People That Are Responsible For The Automations. Each "SnsReport" Object Have "Name", "Message",
                "Severity" And "EventType" Properties. The "Name" And "Message" Properties Are Type Of String. The Other Two
                Properties Are Type Of Enum.
            </para>
            <para type="description">
                -- "MissingGroups" Property. Contains A Collection Of "SnsMissingGroup" Objects Intended For The Use Of The People
                That Are Responsible For The Automations Only. Each "SnsMissingGroup" Object Have "CN", "Mail", "Started" And
                "LastProcessed" Properties. The "CN" And "Mail" Properties Are Type Of String. The Other Two Properties Are Type
                Of DateTime, The DateTime Kind Is Accurate So The User To Be Able To Provide The Timing Either In Local Time Or In
                UTC Correctly. This Report Contains Information About Any Managed Group That Have Been Started And Disappeared
                During Process. Normally There Should Be Not Any, Because This CmdLet Does Not Leave Uncomplete Groups For The
                Next Execution. From That Perspective Such Might Appear When The CmdLet Is Interrupted, A Group Is Not Marked As
                Completed And On The Next Run That Group Is No Longer Present In The Configuration.
            </para>
            <para type="description">
                -- "GroupReports" Property. Contains A Collection Of "SnsGroupReport" Objects Intended To Be Sent To The
                Notification Contacts Of Individual Groups. "SnsGroupReport" Objects Are Initialized Only For The Groups That Have
                Notification Contacts, And Events Intended To Be Send To Those Contacts Occur During The CmdLet Run. For Example
                If No Warning And Errors Related With A Group Are Thrown, And No Members Are Modified, The Notification Contacts
                Report Is Not Needed, Then No Output Object Is Created For That Specific Group. If An Automation Is Run On A
                Schedule, In Most Of The Cases This Property Will Contain No Reports, Because Changes In Groups Membership Will
                Happen After Changes In The HR System, Which Does Not Happen Very Often. "SnsGroupReport" Object Have "GroupGuid"
                With Type Of String, "GroupCn" With Type Of String, "Contacts" With Type Of String Array And "GroupReport" With
                Type Of SnsReport Array. The "Contacts" Array Contains The SMTP Addresses Of The Recipients That The Specific
                Report Shall Be Send. The SnsReport Object Is Already Described In The "InternalReport" Section.
            </para>
            <para type="description">
                -- "ContactReports" Property. This Is A Dynamic Property Which Generates On Demand When Accessed
                "SnsContactReport" Collection With Reports Intended To Specific Recipients Using The "GroupReports". Sending Out
                Emails For Each Individual Group Could Generate Multiple Emails Intended To Single Notification Contact, In The
                Cases Where A Single Contact Is Set To Multiple Groups. This Property Combines The Events From The Groups Into
                Reports Intended To A Single Recipient, Thus Way Reducing The Number Of Notifications Send Out.
            </para>
            <para type="description">
                -- "ErrorMessage" Property. To Be Able To Complete And Prepare The Required Reports The CmdLet Does Not Throw
                Terminating Errors. Instead Whenever An Terminating Event Occur The CmdLet Prepare The Report Object, Store The
                Terminating Event In This Property And Then Exits. Therefore It Could Be Expected That In Case Of Terminating
                Event All The Events From The Already Processed Groups Will Be Present In The Corresponding Properties Of The
                Output Object.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsReportCollection]$objReportCollection = Invoke-SnsAdGroupMembersManage -Verbose;
              </code>
              <para></para>
              <para>Manage The Members Of All Managed AD Groups Taken From The PSModule Configuration.</para>
              <para>Additional Progress Information Is Reverted In The Verbose Stream.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsReportCollection]$objReportCollection = Invoke-SnsAdGroupMembersManage -Verbose -WhatIf;
              </code>
              <para></para>
              <para>
                Report The Actions And Events That The CmdLet Would Normally Do During The Managing The Members Of All Managed AD
                Groups Taken From The PSModule Configuration, Without Actual Members Management.
              </para>
              <para>Additional Progress Information Is Reverted In The Verbose Stream.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsReportCollection]$objReportCollection = Invoke-SnsAdGroupMembersManage -Verbose -Confirm;
              </code>
              <para></para>
              <para>
                Manage The Members Of All Managed AD Groups Taken From The PSModule Configuration With Asking The User For
                Confirmation Before To Add Members If There Are Any For Adding, And Second Time Before To Remove Members If There
                Are Any For Removal.
              </para>
              <para>Additional Progress Information Is Reverted In The Verbose Stream.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsReportCollection]$objReportCollection = Invoke-SnsAdGroupMembersManage `
                -Identity "Finance Department DL" -Verbose;
              </code>
              <para></para>
              <para>
                Report The Actions And Events That The CmdLet Would Normally Do During The Managing The Members Of The Specified
                Managed AD Group, Without Actual Members Management. Any "WhatIf" Adding And Removing Events Will Be Included In
                The Notification Contacts Report.
              </para>
              <para>Additional Progress Information Is Reverted In The Verbose Stream.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsReportCollection]$objReportCollection = "Finance Department DL", "Sales Department DL" | `
                Invoke-SnsAdGroupMembersManage -Verbose;
              </code>
              <para></para>
              <para>
                Report The Actions And Events That The CmdLet Would Normally Do During The Managing The Members Of The Sent Via
                The Pipeline Managed AD Groups, Without Actual Members Management. Any "WhatIf" Adding And Removing Events Will Be
                Included In The Notification Contacts Report.
              </para>
              <para>Additional Progress Information Is Reverted In The Verbose Stream.</para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.InvokeSnsAdGroupMembersManage.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description">When Identity Parameter Is Specified, WhatIf Parameter Will Be Automatically Set To TRUE.</para>
            <para type="description">Any Adding And Removing "WhatIf" Events Will Be Included In The Contacts Report As Well.</para>
            <para type="description">If Omitted The CmdLet Will Run Against All The Managed Groups.</para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            <para type="description">
                The Wildcard Functionality Is To Be Used Only For Less Typing. In Case The CmdLet Is Unable To Unambiguously
                Identify The Managed AD Group It Will Throw Error.
            </para>
            <para type="description">
                For Example If You Are Sure That An Identity "Finance*" Will Revert From The Groups Configuration A Single
                Group Named "Finance Department" You Can Save Time And Use It Instead For Typing "Finance Department". However
                If There Are Multiple Managed AD Groups Matching "Finance*" You Will Receive Error.
            </para>
            <para type="description">
                The Specified Identity Is Validated Against The Configuration DataBase. Therefore Only The Managed AD Groups
                Counts. Any AD Groups Not Automatically Managed That Match "Finance*" Are Not Considered And Will Not Throw
                Error.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.InvokeSnsAdGroupMembersManage.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.InvokeSnsAdGroupMembersManage.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            <para type="description">Works Only When The CmdLet Is Run Interactively.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.InvokeSnsStatisticsDataBaseDefragmentation">
            <summary>
            <para type="synopsis">Defragment And Compact The Statistics DataBase.</para>
            <para type="description">Defragment And Compact The Statistics DataBase.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Invoke-SnsStatisticsDataBaseDefragmentation Is Intended To Be Used Both Interactively By A User And Within A
                Scheduled Jobs As A Services To Defragment And Compact The Statistics DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Depending On The Environment Scale, The Number Of Automated Groups And The Environment Dynamic, The Statistics
                DataBase Would Grow In Size. This Makes It Impossible The DataBase To Be Maintained During The PSModule Load, Like
                It Is Done With The Configuration DataBase. The Feature That Deletes The DataBase Entries When They Expire Based
                On Specified With The Module Configuration Threshold, Creates White Space Within The DataBase And Do Not Shrink
                The DataBase. Regular Maintenance Of The Statistics DataBase Is Needed To Prevent Performance Issues For The
                Automatic Group Members Management. The DataBase Maintenance Could Possibly Require Large Downtime Window.
                Therefore It Is Feasible The Schedule For The Automatic Members Management To Allow Such Downtime. And During That
                Downtime Additional Job To Perform The Maintenance Of The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Invoke-SnsStatisticsDataBaseDefragmentation" CmdLet Initializes The PSModule
                Configuration. Verifies The Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About
                Other PowerShell Processes Using "SnsPsAdGroupMembers" PSModule, Verifies The Existence, The Schema And The
                Integrity Of The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Invoke-SnsStatisticsDataBaseDefragmentation" CmdLet Deletes Any Outdated Statistics
                Entries Depending On Thresholds Which Can Be Modified Using "Set-SnsAdGroupMembersPsModuleSettings" CmdLet. The
                Automatic Outdated Entries Deletion Can Be Disabled With Specifying Both The Threshold For Deletion Of Processing
                And Provisioning Events To 0. Afterward The Statistics DataBase File Is Defragmented And Compacted. The CmdLet Do
                Not Require Neither Input Nor Reverts Any Output.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                Invoke-SnsStatisticsDataBaseDefragmentation -Verbose;
              </code>
              <para></para>
              <para>
                Defragments And Compacts The Statistics DataBase.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="T:SnsAdGroupMembers.NewSnsAdManagedGroup">
            <summary>
            <para type="synopsis">Creates A Managed Active Directory Group Configuration Entry.</para>
            <para type="description">Creates A Managed Active Directory Group Configuration Entry.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                New-SnsAdManagedGroup Is Intended To Be Used Interactively By A User To Create A Managed AD Group Configuration
                Entry In The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validation The CmdLet Query The Active Directory And Enumerates The Provided By The User Objects. In
                Case The Specified Objects Does Not Exists The CmdLet Throws Error. The Parameters Which Accept Wildcard Usage
                Requires To Identify Unambiguously The Specified Object In AD. Therefore If A Specified Wildcard Pattern Revert
                More Than One Object, The CmdLet Will Throw Error. Use The Wildcards Only To Spare Typing When You Are Completely
                Sure It Will Revert Single Object.
            </para>
            <para type="description">
                The Validation Of "AddLogic" And "RemoveLogic" Parameters, Treat The Specified Values As LDAP Query And Executes
                Them Against AD. If The LDAP Query Revert No Results The Validation Fails. This Reduces The CmdLet Performance And
                Slows It Down, But It Is Not Intended To Be Used On Regular Basis Or Within Automation Scripts Anyway. So The
                Reduced Performance Is Acceptable In This Case. When The CmdLet Connects To A Domain Controller In The Same Subnet
                The Reduced Performance Is Not Noticeable By The User.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "New-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "New-SnsAdManagedGroup" CmdLet Performs Additional Verifications Which Cannot Be Made
                During The Parameters Validation. "AddLogic" And "RemoveLogic" Parameters Are Not Mandatory To Allow The User To
                Configure A Group Only For Adding Or Only For Removing Members, However Where Both Are Missing The Group Will Be
                Not Managed At All. Normally This Cannot Be Verified During The Parameters Validation As The CmdLet Accepts The
                Parameters In The Order Specified By The User. Therefore The User Might Specify The "RemoveLogic" Before The
                "AddLogic" Which Will Cause False Positives On Any Parameter Validation From This Kind. Afterward The CmdLet
                Enumerates The Values For The Parameters Which Are Required For The Normal Operation Of The PSModule But Are Not
                Specified By The User. One Of Those Is The Order Position Of The New AD Managed Group Entry. Whenever The
                "Position" Parameter Is Omitted The New AD Managed Group Entry Will Be Created With A Position Value Which Will
                Cause The Group To Be Processed By "Invoke-SnsAdGroupMembersManage" CmdLet After The Existing AD Managed Groups.
                (The New Group Will Be Placed At The End Of The Queue). Then The CmdLet Creates The Main AD Managed Group Entry,
                And Afterward Invokes In Background The CmdLets For Setting Exclusions, Inclusions And Notification Contacts. I've
                Included Those Parameters To This CmdLet Just To Allow Mass Creation Of AD Managed Groups Using Input From .CSV
                File Or Excel File Converted To .CSV File, Without The Need Of Writing A Complex Script. This Is The Reason The
                Corresponding Parameters To Accept Only String Values, Unlike The Dedicated For That Purpose CmdLets. At The End,
                The Newly Created AD Managed Group Is Retrieved From The Configuration, Its Properties Normalized And Send To The
                Pipeline Output.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = New-SnsAdManagedGroup -Identity "Finance Department DL" `
                -AddLogic "(department=Finance Department)(!(userAccountControl:Band:=2))(mail=*)" `
                -RemoveLogic "(|(!(department=Finance*))(userAccountControl:Band:=2)(!(mail=*)))" `
                -Inclusion "john.smith@contoso.com;jane.smith@contoso.com" -Exclusion "adam.smith@contoso.com" `
                -Contact "john.smith@contoso.com", "eve.smith@contoso.com" -Verbose;
              </code>
              <para></para>
              <para>
                Creates Managed AD Group Configuration Object For "Finance Department DL" Active Directory Group With The
                Specified "AddLogic" And "RemoveLogic" With The Next Available Position (After The Existing Group Configuration
                Entries).
              </para>
              <para>
                Calls In Background "Set-SnsAdManagedGroupInclusion" CmdLet To Set john.smith@contoso.com And
                jane.smith@contoso.com As Explicit Inclusions To The Newly Created AD Managed Group Entry. The Entries Are
                Provided As A Single String Value. The Parameter Split It To String Array On Semicolon (;) Character.
              </para>
              <para>
                Calls In Background "Set-SnsAdManagedGroupExclusion" CmdLet To Set adam.smith@contoso.com As Explicit Exclusion To
                The Newly Created AD Managed Group Entry.
              </para>
              <para></para>
              <para>
                Calls In Background "Set-SnsAdManagedGroupContact" CmdLet To Set john.smith@contoso.com And eve.smith@contoso.com
                As Notification Contacts To The Newly Created AD Managed Group Entry. The Values Are Provided As String Array.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Import-Csv -Path "C:\GroupsCfg.csv" -Delimiter "|" `
                -Encoding "ASCII" | New-SnsAdManagedGroup;
              </code>
              <para></para>
              <para>
                Imports .CSV File "C:\GroupsCfg.csv" During The Import Pipeline (|) Character Is Considered As Delimiter. The
                Output Objects Are Send Via The PowerShell Pipeline To "New-SnsAdManagedGroup" Which Creates The AD Managed Group
                Entries As They Are Specified In The .CSV File.
              </para>
              <para></para>
              <para>
                In Order "New-SnsAdManagedGroup" To Accept Properly The Objects Sent Via Pipeline, They Must Have Properties
                Corresponding To The CmdLet Parameters. Therefore The .CSV File Must Have Column Names In The .CSV Header That
                Correspond To "New-SnsAdManagedGroup" Parameter Names Or Parameter Aliases. Have Multiple CmdLet Parameter Aliases
                Allows More Flexibility In The .CSV File Column Names.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = New-SnsAdManagedGroup -Identity "Finance Department DL" `
                -AddLogic "(department=Finance Department)(!(userAccountControl:Band:=2))(mail=*)" -Inclusion "Smith, John";
              </code>
              <para></para>
              <para>
                Throws An Error And The AD Managed Group Entry Is Not Created. The Reason Is Related With The Unusual Behavior Of
                The Inclusion Parameter. The Display Name Of User John Smith Contains Comma (,). This Leads To Splitting Of The
                Specified String Value On Comma (,) Character. As A Result The Parameter Validation Can Not Unambiguously Identify
                The Users Account And Throws Error. In Cases Like That First Create The Configuration Entry Without The Inclusion,
                Exclusion And Notification Contact Entries And Then Use The Corresponding CmdLets To Add Them. Alternatively You
                Can Use An AD Attribute Value Which Does Not Contain Comma (,) Or Semicolon (;) Characters. This Exactly Is The
                Reason Those Parameters To Not Accept distinguishedName Values.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Identity">
            <summary>
            <para type="description">Specifies A Not Managed Active Directory Group.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For Multiple
                Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For Multiple Characters.
                LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - distinguishedName. Must Be Existing Group In The AD Domain. Does Not Support Wildcard Characters.
            </para>
            <para type="description">
                - displayName. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For Multiple
                Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For Multiple Characters.
                LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Group In The AD Domain. Supports Star (*) Wildcard Character For Multiple
                Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Group In The AD Domain. Does Not Support Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Group In The AD Domain. Does Not Support Wildcard Characters.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.AddLogic">
            <summary>
            <para type="description">Specifies The Logic For Adding Members Of The AD Managed Group.</para>
            <para type="description">
                The Logic Is Active Directory Attributes Based And Must Comply With The Lightweight Directory Access Protocol
                (LDAP) Query Language.
            </para>
            <para type="description">
                For Best Results I Would Recommend Usage Of Attributes Which Values Are Automatically Maintained, For Example
                With A Synchronization From An HR Tool.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">The Provided Value Will Be Used On The Group Members Adding As Follows:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)(!(memberOf=[ADManagedGroupDn]))[AddLogic])"</para>
            <para type="description">During The Parameter Validation The CmdLet Will Actually Execute The Following LDAP Query:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)[AddLogic])"</para>
            <para type="description">Therefore The Value Specified To The Parameter Must Have The Following Syntax "([Attribute1]=[Value1])"</para>
            <para type="description"></para>
            <para type="description">
                Whenever You Need To Specify Multiple Conditions And The Added Member Must Comply With All Of Them (AND Logic)
                You Need Not To Specify AND. The Logic Must Looks Like "([Attribute1]=[Value1])([Attribute2]=[Value2])".
            </para>
            <para type="description">
                For Example When You Need All Enabled Users With Mailboxes From "Finance Department" To Be Added In A Group The
                Logic Has To Looks Like:
            </para>
            <para type="description">"(department=Finance Department)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(mail=*)"</para>
            <para type="description"></para>
            <para type="description">
                Whenever You Need To Specify Multiple Conditions With OR Logic. You Need To Specify That. The Logic Must Looks
                Like "(|([Attribute1]=[Value1])([Attribute2]=[Value2]))".
            </para>
            <para type="description">
                For Example When You Need All Enabled Users With Mailboxes From "Finance Department" And "Sales Department" To
                Be Added In A Group The Logic Has To Looks Like:
            </para>
            <para type="description">"(|(department=Finance*)(department=Sales*))(!(userAccountControl:1.2.840.113556.1.4.803:=2))(mail=*)"</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                To Save You Time Researching In Internet About The Correct Syntax For Reference LDAP extensibleMatch Rules
                OID's When They Are Needed, You Can Use:
            </para>
            <para type="description">- :Band: When You Need LDAP_MATCHING_RULE_BIT_AND (:1.2.840.113556.1.4.803:)</para>
            <para type="description">- :Bor: When You Need LDAP_MATCHING_RULE_BIT_OR (:1.2.840.113556.1.4.804:)</para>
            <para type="description">- :Expand: When You Need LDAP_MATCHING_RULE_TRANSITIVE_EVAL (:1.2.840.113556.1.4.1941:)</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.RemoveLogic">
            <summary>
            <para type="description">Specifies The Logic For Removing Members From The AD Managed Group.</para>
            <para type="description">
                The Logic Is Active Directory Attributes Based And Must Comply With The Lightweight Directory Access Protocol
                (LDAP) Query Language.
            </para>
            <para type="description">
                For Best Results I Would Recommend Usage Of Attributes Which Values Are Automatically Maintained, For Example
                With A Synchronization From An HR Tool.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">The Provided Value Will Be Used On The Group Members Removing As Follows:</para>
            <para type="description">"(&amp;[RemoveLdapQuery](memberOf=[ADManagedGroupDn]))"</para>
            <para type="description">During The Parameter Validation The CmdLet Will Actually Execute The Following LDAP Query:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)[RemoveLdapQuery])"</para>
            <para type="description"></para>
            <para type="description">
                Unlike The AddLogic Here You Most Likely Will Need To Use OR Logic Only. Therefore You Need To Specify The
                Logic As Follows:
            </para>
            <para type="description">"(|(!(Attribute1=Value1))(!(Attribute2=Value2)))"</para>
            <para type="description"></para>
            <para type="description">For Example When You Need To Remove Users From A Group:</para>
            <para type="description">- When They Are No Longer In "Finance Department" Or "Sales Department".</para>
            <para type="description">- When Their Accounts Get Disabled.</para>
            <para type="description">- When Their Mailboxes Are Disabled.</para>
            <para type="description">"(|(!(|(department=Finance*)(department=Sales*)))(userAccountControl:1.2.840.113556.1.4.803:=2)(!(mail=*)))"</para>
            <para type="description">
                For RemoveLogic It Just Does Not Make Sense To Use AND Logic. At The End We Need To Remove The Members When
                One Of The Conditions Occur. It Is Not Likely All Of The Conditions To Occur Simultaneously To Remove A Member.
            </para>
            <para type="description">
                NOTE: Unlike The AddLogic The RemoveLogic Actually Does Not Add The Conditions The Removed Object To Be A User
                Account. Which Means That "SnsPsAdGroupMembers" PSModule Actually Does Remove Group And Contact Member
                Objects. When You Prepare Your RemoveLogic Please Pay Attention That The Different AD Objects Have Different
                Sets Of Attributes. For Example If You Have Condition (!(userPrincipalName=*)) This Would Automatically Remove
                All The Nested Groups And Contacts, Because They Have No UPN Attribute.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                To Save You Time Researching In Internet About The Correct Syntax For Reference LDAP extensibleMatch Rules
                OID's When They Are Needed, You Can Use:
            </para>
            <para type="description">- :Band: When You Need LDAP_MATCHING_RULE_BIT_AND (:1.2.840.113556.1.4.803:)</para>
            <para type="description">- :Bor: When You Need LDAP_MATCHING_RULE_BIT_OR (:1.2.840.113556.1.4.804:)</para>
            <para type="description">- :Expand: When You Need LDAP_MATCHING_RULE_TRANSITIVE_EVAL (:1.2.840.113556.1.4.1941:)</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Position">
            <summary>
            <para type="description">Specifies The Position For The New AD Managed Group.</para>
            <para type="description">
                If Omitted The CmdLet Will Assign The Next Value After The Highest Existing Position In The Configuration,
                Placing The Newly Created Entry In The End Of The Processing Queue.
            </para>
            <para type="description">
                "Invoke-SnsAdGroupMembersManage" CmdLet Process The AD Managed Groups In Ascending Order (In Sequence) Based
                On The AD Managed Group Position. Whenever There Are Dependencies Between The Groups, The Prerequisite Group
                Have To Be Processed Before The Dependent Group (Must Have Lesser Position). Otherwise The Dependent Group
                Will Use As Input Outdated Information.
            </para>
            <para type="description">
                This Is Not Critical Though On The Next Run The Dependent Groups Will Have The Proper Input Because The
                Prerequisite Group Will Be Updated (On The Current Run). Wrong Sequence Just Slows Down The Group Members
                Management.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Disabled">
            <summary>
            <para type="description">Specifies To Disable The New AD Managed Group Configuration Entry.</para>
            <para type="description">Disabled AD Managed Groups Are Not Processed By "Invoke-SnsAdGroupMembersManage".</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Inclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Set In The List Of The Specified Managed Group Explicit Inclusions.</para>
            <para type="description">Explicit Inclusions Are Used When We Need To Add An AD Object Which Do Not Match The AddLogic As Group Member.</para>
            <para type="description">Explicit Inclusion Objects External For The AD Domain Are Not Allowed.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Inclusions Will Be Added To The Specified Group.</para>
            <para type="description"></para>
            <para type="description">
                The Parameter Have Functionality Different Than The Recommendations And The Best Practices. The Parameter
                Accepts Only Values Of Types String Or String Array. Normally For Management Of The Explicit Inclusions Have
                To Be Used The CmdLets With Noun "SnsAdManagedGroupInclusion", Their Parameters Behave According The Best
                Practices And The MS Recommendations For CmdLet Parameters. I've Included This Parameter Here To Simplify The
                AD Managed Group Configuration Creation Using A .CSV File Or Excel File Converted To .CSV File. All The
                Objects Created With "Import-Csv" CmdLet Have Properties Of Type String. Type Of String Array By Default Is
                Not Available, Without Additional Processing Of The CmdLet Output Objects. From That Perspective This
                Parameter Can Accept Single String Value And Splits It To String Array On Semicolon (;) And Comma (,)
                Characters, Assuming That There Will Be No AD Objects Containing Those Characters In The Attributes Used As
                Identity. To Avoid Issues With The Input Objects Created By "Import-Csv" CmdLet Please Avoid Using Those
                Characters As .CSV Delimiter And Make Sure The Quotation Marks (") In The .CSV File Are In Their Proper Place.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Exclusion">
            <summary>
            <para type="description">Specifies An AD Object To Be Set In The List Of The Specified Managed Group Explicit Exclusions.</para>
            <para type="description">
                Explicit Exclusions Are Used When We Need To Not Add As Group Member An AD Object Which Does Match The
                AddLogic.
            </para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">
                - SMTP Email Address. Supports Star (*) Wildcard Character For Multiple Characters. LDAP Does Not Support
                Single Wildcard Character.
            </para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Exclusions Will Be Added To The Specified Group.</para>
            <para type="description">
                The Parameter Have Functionality Different Than The Recommendations And The Best Practices. The Parameter
                Accepts Only Values Of Types String Or String Array. Normally For Management Of The Explicit Exclusions Have
                To Be Used The CmdLets With Noun "SnsAdManagedGroupExclusion", Their Parameters Behave According The Best
                Practices And The MS Recommendations For CmdLet Parameters. I've Included This Parameter Here To Simplify The
                AD Managed Group Configuration Creation Using A .CSV File Or Excel File Converted To .CSV File. All The
                Objects Created With "Import-Csv" CmdLet Have Properties Of Type String. Type Of String Array By Default Is
                Not Available, Without Additional Processing Of The CmdLet Output Objects. From That Perspective This
                Parameter Can Accept Single String Value And Splits It To String Array On Semicolon (;) And Comma (,)
                Characters, Assuming That There Will Be No AD Objects Containing Those Characters In The Attributes Used As
                Identity. To Avoid Issues With The Input Objects Created By "Import-Csv" CmdLet Please Avoid Using Those
                Characters As .CSV Delimiter And Make Sure The Quotation Marks (") In The .CSV File Are In Their Proper Place.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Contact">
            <summary>
            <para type="description">Specifies Recipients For The Group Related Audit Reports.</para>
            <para type="description"></para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SMTP Email Address. Can Be Used For External Recipients. Does Not Support Wildcard Characters.</para>
            <para type="description">
                - Exchange Alias. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - cn. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - displayName. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*)
                Wildcard Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - employeeID. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - name. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - sAMAccountName. Must Be Existing Either Account Or Group Object In The AD Domain. Supports Star (*) Wildcard
                Character For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - telephoneNumber. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character For
                Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - userPrincipalName. Must Be Existing Account Object In The AD Domain. Supports Star (*) Wildcard Character
                For Multiple Characters. LDAP Does Not Support Single Wildcard Character.
            </para>
            <para type="description">
                - objectGUID. Must Be Existing Either Account, Group Or Contact Object In The AD Domain. Does Not Support
                Wildcard Characters.
            </para>
            <para type="description">
                - objectSid. Must Be Existing Either Account Or Group Object In The AD Domain. Does Not Support Wildcard
                Characters.
            </para>
            <para type="description"></para>
            <para type="description">In Case Multiple Values Are Specified All Specified Contacts Will Be Added To The Specified Group.</para>
            <para type="description">
                The Parameter Have Functionality Different Than The Recommendations And The Best Practices. The Parameter
                Accepts Only Values Of Types String Or String Array. Normally For Management Of The Notification Contacts Have
                To Be Used The CmdLets With Noun "SnsAdManagedGroupContact", Their Parameters Behave According The Best
                Practices And The MS Recommendations For CmdLet Parameters. I've Included This Parameter Here To Simplify The
                AD Managed Group Configuration Creation Using A .CSV File Or Excel File Converted To .CSV File. All The
                Objects Created With "Import-Csv" CmdLet Have Properties Of Type String. Type Of String Array By Default Is
                Not Available, Without Additional Processing Of The CmdLet Output Objects. From That Perspective This
                Parameter Can Accept Single String Value And Splits It To String Array On Semicolon (;) And Comma (,)
                Characters, Assuming That There Will Be No AD Objects Containing Those Characters In The Attributes Used As
                Identity. To Avoid Issues With The Input Objects Created By "Import-Csv" CmdLet Please Avoid Using Those
                Characters As .CSV Delimiter And Make Sure The Quotation Marks (") In The .CSV File Are In Their Proper Place.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.NewSnsAdManagedGroup.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.RemoveSnsAdManagedGroup">
            <summary>
            <para type="synopsis">Deletes Managed Active Directory Group Configuration.</para>
            <para type="description">Deletes Managed Active Directory Group Configuration.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Remove-SnsAdManagedGroup Is Intended To Be Used Interactively By A User To Delete A Managed AD Group Configuration
                From The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validation The CmdLet Query The Configuration DataBase And Enumerates The Provided By The User
                Objects. In Case The Specified Objects Does Not Exists The CmdLet Throws Error. The Parameters Which Accept
                Wildcard Usage Requires To Identify Unambiguously The Specified Object. Therefore If A Specified Wildcard Pattern
                Revert More Than One Object, The CmdLet Will Throw Error. Use The Wildcards Only To Spare Typing When You Are
                Completely Sure It Will Revert Single Object.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Remove-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Remove-SnsAdManagedGroup" CmdLet Enumerates The Configuration Entries For Each Group
                Coming From The Pipeline Or Specified With "Identity" Parameter And Deletes Them. In Case The Deletion Is
                Successful The CmdLet Does Not Revert Output. Whenever The Deletion Does Not Happen Either Because The User Did
                Not Confirmed The Deletion Or When The CmdLet Is Run With WhatIf Parameter Or Any Failure, AD Managed Group Object
                Is Send To The Pipeline.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroup -Identity "Finance Department DL";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Object For AD Group "Finance Department DL" And Deletes It.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Remove-SnsAdManagedGroup "Finance Department", "Sales Department";
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Groups "Finance Department" And "Sales Department" And Delete Them.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = "Finance Department DL", "Sales Department DL" | `
                Remove-SnsAdManagedGroup -Verbose;
              </code>
              <para></para>
              <para>
                Enumerates The Configuration Objects For AD Groups "Finance Department DL" And "Sales Department DL" And Delete
                Them.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroup.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroup.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.RemoveSnsAdManagedGroup.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.SetSnsAdManagedGroup">
            <summary>
            <para type="synopsis">Modifies A Managed Active Directory Group Configuration Entry.</para>
            <para type="description">Modifies A Managed Active Directory Group Configuration Entry.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Set-SnsAdManagedGroup Is Intended To Be Used Interactively By A User To Modify A Managed AD Group Configuration
                Entry In The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validation The CmdLet Query The Configuration DataBase And Enumerates The Provided By The User
                Objects. In Case The Specified Objects Does Not Exists The CmdLet Throws Error. The Parameters Which Accept
                Wildcard Usage Requires To Identify Unambiguously The Specified Object. Therefore If A Specified Wildcard Pattern
                Revert More Than One Object, The CmdLet Will Throw Error. Use The Wildcards Only To Spare Typing When You Are
                Completely Sure It Will Revert Single Object.
            </para>
            <para type="description">
                The Validation Of "AddLogic" And "RemoveLogic" Parameters, Treat The Specified Values As LDAP Query And Executes
                Them Against AD. If The LDAP Query Revert No Results The Validation Fails. This Reduces The CmdLet Performance And
                Slows It Down, But It Is Not Intended To Be Used On Regular Basis Or Within Automation Scripts Anyway. So The
                Reduced Performance Is Acceptable In This Case. When The CmdLet Connects To A Domain Controller In The Same Subnet
                The Reduced Performance Is Not Noticeable By The User.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Set-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "ProcessRecord" Method "Set-SnsAdManagedGroup" CmdLet Performs Additional Verifications Which Cannot Be Made
                During The Parameters Validation. "AddLogic" And "RemoveLogic" Parameters Are Not Mandatory To Allow The User To
                Configure A Group Only For Adding Or Only For Removing Members, However Where Both Are Missing The Group Will Be
                Not Managed At All. Normally This Cannot Be Verified During The Parameters Validation As The CmdLet Accepts The
                Parameters In The Order Specified By The User. Therefore The User Might Specify The "RemoveLogic" Before The
                "AddLogic" Which Will Cause False Positives On Any Parameter Validation From This Kind. Afterward The CmdLet
                Modifies The AD Managed Group Properties That Correspond To The Specified By The User CmdLet Parameters. Since The
                CmdLet Is Intended To Be Used On Existing Groups, The Parameters For Managing Explicit Inclusions, Explicit
                Exclusions And Notification Contacts Are Not Present Here. Instead You Can Use The Corresponding CmdLets. Then The
                CmdLet Sends To The PowerShell Pipeline The Modified AD Managed Group Objects.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsAdManagedGroup Objects With The Following Properties And Methods:
            </para>
            <para type="description">
                - "Position" Property Of Type Integer. Represents The Group Position In The Collection For Members Management.
            </para>
            <para type="description">
                - "Identity" Property Of Type Guid. Represents The Managed Group AD "objectGUID".
            </para>
            <para type="description">
                - "Name" Property Of Type String. Contains The Value Of The Managed Group "cn" Attribute.
            </para>
            <para type="description">
                - "AddLogic" Property Of Type String. Contains The Logic For Adding Members Into The Managed Group.
            </para>
            <para type="description">
                - "RemoveLogic" Property Of Type String. Contains The Logic For Removing Members From The Managed Group.
            </para>
            <para type="description">
                - "Inclusions" Property Of Type SnsAdManagedGroupInclusion Array. Contains An Array With The Group's Explicit
                Inclusions. Each SnsAdManagedGroupInclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Exclusions" Property Of Type SnsAdManagedGroupExclusion Array. Contains An Array With The Group's Explicit
                Exclusions. Each SnsAdManagedGroupExclusion Object Contains: "Identity" Property Of Type Guid. "Name" Property Of
                Type String. "Enabled" Property Of Type Boolean.
            </para>
            <para type="description">
                - "Notify" Property Of Type SnsAdManagedGroupContact Array. Contains An Array With The Group's Notification
                Contacts. Each SnsAdManagedGroupContact Object Contains: "Email" Property Of Type String. "Enabled" Property Of
                Type Boolean.
            </para>
            <para type="description">
                - "Enabled" Property Of Type Boolean. Represents Whether The Managed Group Entry Is Active Or Not.
            </para>
            <para type="description">
                - "GetSnsRawAddLogic" Method Intended To Revert The Not Normalized Add Logic As It Is Set In The Group
                Configuration.
            </para>
            <para type="description">
                - "GetSnsRawRemoveLogic" Method Intended To Revert The Not Normalized Remove Logic As It Is Set In The Group
                Configuration.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroup -Identity "Finance Department DL" `
                -AddLogic "(department=Finance Department)(!(userAccountControl:Band:=2))(mail=*)" `
                -RemoveLogic "(|(!(department=Finance*))(userAccountControl:Band:=2)(!(mail=*)))";
              </code>
              <para></para>
              <para>
                Modifies The "AddLogic" And "RemoveLogic" Of The Managed AD Group Configuration Object For "Finance Department DL"
                Active Directory Group.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroup -Identity "Finance Department DL" `
                -Enabled:$false -Verbose;
              </code>
              <para></para>
              <para>
                Disables The Managed AD Group Configuration Object For "Finance Department DL" Active Directory Group.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsAdManagedGroup[]]$arrGrs = Set-SnsAdManagedGroup -Identity "Finance Department DL" `
                -Position 0 -Confirm;
              </code>
              <para></para>
              <para>
                Modifies The Position Of The Managed AD Group Configuration Object For "Finance Department DL" Active Directory
                Group. On The Process The User Will Be Asked For Confirmation. With Position 0 The AD Managed Group Will Be The
                First Processed By "Invoke-SnsAdGroupMembersManage" CmdLet.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.Identity">
            <summary>
            <para type="description">Specifies A Managed Domain Group Present In The Configuration.</para>
            <para type="description">The Parameter Accepts The Following Values:</para>
            <para type="description">- SnsAdGroupMembers.SnsAdManagedGroup</para>
            <para type="description">- objectGUID</para>
            <para type="description">- cn (Allows Usage Of Wildcard Characters.)</para>
            <para type="description">Allowed Wildcard Characters Usage In Both PowerShell And SQL Syntax:</para>
            <para type="description">Star (*) And Percent (%) Are Used For Multiple Characters.</para>
            <para type="description">Question Mark (?) And Underscore (_) Are Used For Single Character.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.AddLogic">
            <summary>
            <para type="description">Specifies The Logic For Adding Members Of The AD Managed Group.</para>
            <para type="description">
                The Logic Is Active Directory Attributes Based And Must Comply With The Lightweight Directory Access Protocol
                (LDAP) Query Language.
            </para>
            <para type="description">
                For Best Results I Would Recommend Usage Of Attributes Which Values Are Automatically Maintained, For Example
                With A Synchronization From An HR Tool.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">The Provided Value Will Be Used On The Group Members Adding As Follows:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)(!(memberOf=[ADManagedGroupDn]))[AddLogic])"</para>
            <para type="description">During The Parameter Validation The CmdLet Will Actually Execute The Following LDAP Query:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)[AddLogic])"</para>
            <para type="description">Therefore The Value Specified To The Parameter Must Have The Following Syntax "([Attribute1]=[Value1])"</para>
            <para type="description"></para>
            <para type="description">
                Whenever You Need To Specify Multiple Conditions And The Added Member Must Comply With All Of Them (AND Logic)
                You Need Not To Specify AND. The Logic Must Looks Like "([Attribute1]=[Value1])([Attribute2]=[Value2])".
            </para>
            <para type="description">
                For Example When You Need All Enabled Users With Mailboxes From "Finance Department" To Be Added In A Group The
                Logic Has To Looks Like:
            </para>
            <para type="description">"(department=Finance Department)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(mail=*)"</para>
            <para type="description"></para>
            <para type="description">
                Whenever You Need To Specify Multiple Conditions With OR Logic. You Need To Specify That. The Logic Must Looks
                Like "(|([Attribute1]=[Value1])([Attribute2]=[Value2]))".
            </para>
            <para type="description">
                For Example When You Need All Enabled Users With Mailboxes From "Finance Department" And "Sales Department" To
                Be Added In A Group The Logic Has To Looks Like:
            </para>
            <para type="description">"(|(department=Finance*)(department=Sales*))(!(userAccountControl:1.2.840.113556.1.4.803:=2))(mail=*)"</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                To Save You Time Researching In Internet About The Correct Syntax For Reference LDAP extensibleMatch Rules
                OID's When They Are Needed, You Can Use:
            </para>
            <para type="description">- :Band: When You Need LDAP_MATCHING_RULE_BIT_AND (:1.2.840.113556.1.4.803:)</para>
            <para type="description">- :Bor: When You Need LDAP_MATCHING_RULE_BIT_OR (:1.2.840.113556.1.4.804:)</para>
            <para type="description">- :Expand: When You Need LDAP_MATCHING_RULE_TRANSITIVE_EVAL (:1.2.840.113556.1.4.1941:)</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.RemoveLogic">
            <summary>
            <para type="description">Specifies The Logic For Removing Members From The AD Managed Group.</para>
            <para type="description">
                The Logic Is Active Directory Attributes Based And Must Comply With The Lightweight Directory Access Protocol
                (LDAP) Query Language.
            </para>
            <para type="description">
                For Best Results I Would Recommend Usage Of Attributes Which Values Are Automatically Maintained, For Example
                With A Synchronization From An HR Tool.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">The Provided Value Will Be Used On The Group Members Removing As Follows:</para>
            <para type="description">"(&amp;[RemoveLdapQuery](memberOf=[ADManagedGroupDn]))"</para>
            <para type="description">During The Parameter Validation The CmdLet Will Actually Execute The Following LDAP Query:</para>
            <para type="description">"(&amp;(objectCategory=person)(objectClass=user)[RemoveLdapQuery])"</para>
            <para type="description"></para>
            <para type="description">
                Unlike The AddLogic Here You Most Likely Will Need To Use OR Logic Only. Therefore You Need To Specify The
                Logic As Follows:
            </para>
            <para type="description">"(|(!(Attribute1=Value1))(!(Attribute2=Value2)))"</para>
            <para type="description"></para>
            <para type="description">For Example When You Need To Remove Users From A Group:</para>
            <para type="description">- When They Are No Longer In "Finance Department" Or "Sales Department".</para>
            <para type="description">- When Their Accounts Get Disabled.</para>
            <para type="description">- When Their Mailboxes Are Disabled.</para>
            <para type="description">"(|(!(|(department=Finance*)(department=Sales*)))(userAccountControl:1.2.840.113556.1.4.803:=2)(!(mail=*)))"</para>
            <para type="description">
                For RemoveLogic It Just Does Not Make Sense To Use AND Logic. At The End We Need To Remove The Members When
                One Of The Conditions Occur. It Is Not Likely All Of The Conditions To Occur Simultaneously To Remove A Member.
            </para>
            <para type="description">
                NOTE: Unlike The AddLogic The RemoveLogic Actually Does Not Add The Conditions The Removed Object To Be A User
                Account. Which Means That "SnsPsAdGroupMembers" PSModule Actually Does Remove Group And Contact Member
                Objects. When You Prepare Your RemoveLogic Please Pay Attention That The Different AD Objects Have Different
                Sets Of Attributes. For Example If You Have Condition (!(userPrincipalName=*)) This Would Automatically Remove
                All The Nested Groups And Contacts, Because They Have No UPN Attribute.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                To Save You Time Researching In Internet About The Correct Syntax For Reference LDAP extensibleMatch Rules
                OID's When They Are Needed, You Can Use:
            </para>
            <para type="description">- :Band: When You Need LDAP_MATCHING_RULE_BIT_AND (:1.2.840.113556.1.4.803:)</para>
            <para type="description">- :Bor: When You Need LDAP_MATCHING_RULE_BIT_OR (:1.2.840.113556.1.4.804:)</para>
            <para type="description">- :Expand: When You Need LDAP_MATCHING_RULE_TRANSITIVE_EVAL (:1.2.840.113556.1.4.1941:)</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.Position">
            <summary>
            <para type="description">Specifies The Position For The New AD Managed Group.</para>
            <para type="description">
                "Invoke-SnsAdGroupMembersManage" CmdLet Process The AD Managed Groups In Ascending Order (In Sequence) Based
                On The AD Managed Group Position. Whenever There Are Dependencies Between The Groups, The Prerequisite Group
                Have To Be Processed Before The Dependent Group (Must Have Lesser Position). Otherwise The Dependent Group
                Will Use As Input Outdated Information.
            </para>
            <para type="description">
                This Is Not Critical Though On The Next Run The Dependent Groups Will Have The Proper Input Because The
                Prerequisite Group Will Be Updated (On The Current Run). Wrong Sequence Just Slows Down The Group Members
                Management.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.Enabled">
            <summary>
            <para type="description">Specifies To Disable The New AD Managed Group Configuration Entry.</para>
            <para type="description">Disabled AD Managed Groups Are Not Processed By "Invoke-SnsAdGroupMembersManage".</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdManagedGroup.Force">
            <summary>
            <para type="description">Specifies To Ignore The Errors Related With Multiple PSSessions.</para>
            </summary>
        </member>
        <member name="T:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings">
            <summary>
            <para type="synopsis">Modifies "SnsPsAdGroupMembers" PSModule Configuration.</para>
            <para type="description">Modifies "SnsPsAdGroupMembers" PSModule Configuration.</para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Operation Of "SnsPsAdGroupMembers" PSModule Install It With "AllUsers" Scope. The Idea Behind
                This Module Is To Be Used On A Scheduled Task "As Service" For The Actual Group Members Management, And
                Interactively By IT Administrators To Create And Modify The Managed Groups Configuration. This Requires The
                PSModule To Be Available To Multiple User Accounts.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                To Ensure The Smooth Creation Of "SnsPsAdGroupMembers" PSModule DataBases, The First Load Of The PSModule Must Be
                In Elevated Mode. In The Normal Operation The PSModule Does Not Require Elevated Mode. More Information About That
                Is Provided Further In This Document.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "Why Should I Use This PSModule Instead Of Dynamic Groups?":
            </para>
            <para type="description">
                - Well First And Foremost Reason Is Related With The Fact That This PowerShell Module Does Allow To Have Different
                Logic For Adding And Removing Members. This Is Not Achievable With Dynamic Groups.
            </para>
            <para type="description">
                - The Company IT Department Might Need To Use A Single Group For Granting Access Rights In On Premises AD, AzureAD
                And Use It As Distribution List At The Same Time. Although This Can Be Achieved With Dynamic Groups You Have To
                Maintain At Least Two Of Them, One For On Premises AD And One For AzureAD.
            </para>
            <para type="description">
                - There Are Cases Related With Certain AzureAD Functionalities And Synchronizations With Third Party Cloud
                Solutions Which Do Not Support Nested And Dynamic Groups. Managing Of Groups With Large Number Of Members In
                Corporate Environment Without Using Of Group Nestling Could Be Quite Tricky And Related With Lot Of Users
                Frustration And Administrative Effort.
            </para>
            <para type="description">
                - The "SnsPsAdGroupMembers" PSModule Prepare Reports About Modifying Group Members And Audit Of Changes In The
                Group Management Settings. Whenever A Group Is Used For Granting Sensitive Access Rights Or Managing The Members
                Of A Sensitive Distribution List, The Group Owners Might Want To Receive Those Reports, Often Immediately After
                The Above-Mentioned Actions Are Taken.
            </para>
            <para type="description">
                - The PSModule Can Be Used Only For Adding Or Only For Removing Members. Using Of Both Is Not Mandatory. This Does
                Allow Implementation Of Process For Adding Members In Sensitive Groups, Like "Domain Admins" For Example,
                Following Formal Approval Process, But Removing Members Immediately When The Person Who Owns The Account Leave The
                Company, Or Change The Position. In This Case There Will Be Zero Tolerance For Users "Forgotten" With More Than
                Needed Access Rights.
            </para>
            <para type="description">
                This PSModule Have The Same Disadvantages And Requirements As The Dynamic Groups. Since The Management Logic Is
                Based On AD Attribute Values, It Requires The Used Ones To Be Up To Date And Consistent. Some Sort Of
                Synchronization From The Company HR System Would Address This. Such A Synchronization Is Nice To Have But Not A
                Requirement. Using My Other PSModule's Will Be Relatively Easy Creation Of Own Synchronization Related With Any On
                Premises HR Application. Most Of The Cloud Based Ones, Already Have Out Of The Box Synchronization Tools. Creation
                Of New One Would Not Be Feasible, But It Depends On The API's The Tool Provides.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Manages The Membership Of Active Directory Groups In A Single Domain Forest Based On
                Predefined Logic About Adding And Removing Members. For That Purpose, The PowerShell Module Uses SQLite
                Configuration DataBase To Keep Information About:
            </para>
            <para type="description">
                - The Managed Groups.
            </para>
            <para type="description">
                - The Logic For Adding Members Into Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - The Logic For Removing Members From Each Individual Group, Based On Attribute Values.
            </para>
            <para type="description">
                - Explicit Group Inclusions. Those Are AD Objects Which Shall Be Added As Group Members, Although They Do Not Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Explicit Group Exclusions. Those Are AD Objects Which Shall Not Be Added As Group Members, Although They Do Meet
                The Adding Criteria.
            </para>
            <para type="description">
                - Notification Contacts Who Shall Receive Reports About The Actions And Audit Events Related With Their Own Groups.
            </para>
            <para type="description">
                - The PSModule Configuration.
            </para>
            <para type="description">
                - Managed Groups Configuration Changes Tracking.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Uses Another SQLite DataBase To Store All The Events Related With The CmdLets
                Operation And Events Related With Actions Taken On The Managed Groups.
            </para>
            <para type="description"></para>
            <para type="description">
                To Increase The Confidence In The Automation Among The Group Owners, "SnsPsAdGroupMembers" PSModule Produces
                Reports Intended To Be Provided To Those Owners, Whenever The PSModule Adds And / Or Removes Members, Whenever It
                Detects Changes In The Groups Configuration That Might Affect The Group Members, Such Like Changes In The Add
                Logic, Remove Logic, Explicit Inclusions, Explicit Exclusions And Notification Contacts.
            </para>
            <para type="description">
                In Case Of Changes In The Notification Contacts, Both The Old And New Contacts Are Included In The Report
                Recipients List. The Reports Are Prepared Only When Actual Changes Are Made Or Detected Whenever The Actual Group
                Management Occur. For That Purpose, The PSModule Uses An SQLite Statistics DataBase To Store Information About:
            </para>
            <para type="description">
                - Events Related With Automatic Adding Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Automatic Removing Members Into Managed AD Group, Regardless The Group Requires Or Not
                Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With Changes In Managed Groups Configuration That Might Affect The Group Membership, Regardless
                The Group Requires Or Not Notification Contacts Report.
            </para>
            <para type="description">
                - Events Related With The Module Operation And Groups Management Intended To Be Provided To The Company IT's. The
                Internal Events Not Related With Specific Managed Group Are Not Kept In The Statistics DataBase. Therefore The
                Statistics DataBase Is Not Suitable Source Of Information About Troubleshooting Of Performance, Module Related
                Issues, And Script Related Issues. However It Is Perfectly Reliable Source Of Troubleshooting Information Related
                With Troubleshooting Of Incorrect Logic And Any Managed Groups Misconfiguration.
            </para>
            <para type="description"></para>
            <para type="description">
                The PowerShell Module Only Prepares Reports And Reverts Them As "SnsReportCollection" Output Object. The Email
                Relay Options Differ From One Environment To Another, It Is Not Feasible To Maintain Multiple Settings Related
                With Email Sending In The Configuration DataBase, While Sending Of An Email From PowerShell Is Simple As Running
                Of A CmdLet. Depending On The Company, Might Be Used Different Languages, Different Wording, Company Branding,
                Company Stationaries, Company Colors And Company Visual Stylings In The Emails. From That Perspective The PSModule
                Reverts Reports In Custom Objects And Collections. The User Have To Convert Them To HTML Text And Send Them As
                Emails, Within The Automation Scripts Which Use "SnsPsAdGroupMembers" Module. The Simplest Way For Doing That Is
                Using "ConvertTo-Html" And "Send-MailMessage" Native PowerShell CmdLets. Whenever Managed Group Owners Are Not
                Interested To Receive Any Notifications The Reports For They Own Groups Can Be Disabled Via Leaving Empty The
                Notification Contacts Setting Of The Group &#40;Or Remove All Notification Contacts For A Managed Group If There Are
                Already Specified&#41;. This Does Not Disable The Logging Of Events Into The Statistics DataBase.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                For DataBase Engine Is Used SQLite. SQLite Is Free Open Source Serverless DataBase, Which Comes With Its Own
                Advantages And Disadvantages. As Serverless DataBase There Is No Server To Manage The DataBase Requests And Locks.
                From That Perspective Using A Single SQLite DataBase Either Over Network Or Mapped Drives Or Simultaneously By
                Multiple Applications / PSSessions Might Lead To Errors In Accessing The DataBase Or DataBase Corruption.
            </para>
            <para type="description">
                From That Perspective All The CmdLets Within This Module Have A Feature That Prevents Running Of Those CmdLets In
                Multiple PowerShell Sessions. All The CmdLets Have Parameter "Force" Which Allows The Usage Of The CmdLets In
                Multiple PSSessions, Use It At Your Own Risk. The Parameter Is Ignored And Does Not Work When The PSSession Is "As
                A Service" &#40;In Automation Script Executed With Scheduled Task For Example&#41;.
            </para>
            <para type="description">
                Both The Configuration And Statistics DataBases Are Located In "C:\ProgramData\SnsAdGroupMembers" By Default. In
                Order The Folder And DataBase Files To Be Created Properly, The First Run Of This CmdLet To Be Made In Elevated
                PowerShell Session. Creation Of The DataBase Folder And Setting The Required NTFS Permissions Requires Local
                Administrator Access Rights. The DataBase Files Can Be Moved / Migrated Into Different Folders, In That Case The
                Administrator Who Is Doing That Have To Make Sure That The Folder Exists, All The Users That Will Use This
                PSModule Will Have "Modify" NTFS Permissions Over The Folder And The DataBase Files, Move The DataBase Files Into
                The New Folder And Properly Provide The Module With The New Folder Absolute &#40;Full&#41; Path.
            </para>
            <para type="description">
                Although Using This PSModule On Domain Controllers Is Possible, It Is Against The Best Practices And It Is Not
                Recommended. All Automations Shall Be Run On Dedicated Virtual Or Physical Machine. From That Perspective It Is
                Required "Local Admin" Access Rights.
            </para>
            <para type="description">
                It Is Not Recommended The DataBase Files To Be Moved, And If That Happen They Shall Be Not Moved On Network Shares
                Or Mapped Drives. This Will Not Prevent The PSModule To Do Its Job. It Will Introduce Performance Degradation,
                Possible Interruption In Case Of Network Issues And Eventually Corruption Of The DataBases.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                Never Move DataBases Outside The Default Location When The PSModule Is Installed With Scope "CurrentUser".
            </para>
            <para type="description"></para>
            <para type="description">
                !!! WARNING !!!
            </para>
            <para type="description">
                "CfgDbFolder" Setting Specifies The Location Of Both Configuration And Statistics DataBases Simultaneously Unless
                The Statistics DataBase Have Explicitly Specified Location. With Other Words When Modify Configuration DataBase
                Location And "StatDbFolder" Setting Is Not Used, Both DataBases Have To Be Moved In The New Location.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" PSModule Contains CmdLets Intended To Be Run Interactively By The User And CmdLets Intended
                To Be Run Within Automation Scripts On A Schedule As A Service. The CmdLets Intended To Be Used Within Automation
                Scripts Comply With Additional Requirements Related With Logging, Reporting And Ability To Being Monitored &#40;Using
                "SnsPsScriptsMonitoring" PSModule For Example&#41;. "Invoke-SnsAdGroupMembersManage" Is A CmdLet Intended To Be Used
                In An Automation Scripts. By Its Nature, This CmdLet Is An Automation Encapsulated Within A CmdLet. The Logs And
                Events Happening During The CmdLet Run Are Logged In An SQLite DataBase "GroupMembersProvStat.db" Referred Furter
                As Statistics DataBase. It Could Be Used For Other Reporting Purposes Like Periodical Comprehensive Reports About
                The Actions Taken By Automation Scripts &#40;This Requires Additional Scripting To Read The DataBase And Prepare The
                Reports&#41;.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                When Working With Active Directory It Is Important What Identity Attribute Will Be Chosen For Binding To The AD
                Objects. Although Naturally AD Uses DistinguishedName For Binding And LDAP Queries, It Is Not The Best Possible
                Identity. The DistinguishedName Is Unique But It Is Not Constant, It Can Be Changed Over The AD Object Life Cycle.
                An AD Object Can Be Renamed And / Or Moved Into Different Organizational Unit, Or The Organizational Unit Where
                The Object Is Located Can Be Renamed And / Or Moved. That Will Modify Object's Distinguished Name. In This Case
                The Active Directory Will Automatically Reflect Those Changes In The Attributes Of The Object And On All
                Relational Attributes Of The Remaining Objects Which Point To Our Object. For Example "member" Attribute Of All
                The Groups Where Our AD Object Is Member Of, Or "manager" Attribute Of All Accounts That Our User Is Manager.
                However AD Will Not Modify Accordingly The PSModule Configuration Stored In An External For The AD DataBase. This
                Will Lead To Errors And Failures.
            </para>
            <para type="description">
                It Is Best Practice The AD Related Applications To Use For Binding Other Identity Attributes Which Do Not Change
                During The Objects Life Cycle. Those Are "objectGUID" And "objectSid". The Best Practices Gives Preference To The
                "objectSid" By Various Reasons. Since It Is Possible Groups To Have Member Objects Without "objectSid" &#40;Contact
                Objects For Example&#41; The "SnsPsAdGroupMembers" PSModule Uses As Identity The "ObjectGUID" Attribute. Thus Way When
                An Object Is Renamed Or Moved The PSModule Is Not Affected And Continue To Work As Intended.
            </para>
            <para type="description"> The
                The Well-Known AD Behavior, That When An Object Is Deleted And Then Recreated, All The Access Rights And Group
                Membership Are Lost, Is Related With The Fact That The Recreated Object Have Different "objectSid". Using The
                "objectGUID" As Identity Introduces Similar Behavior Of "SnsPsAdGroupMembers". Deletion And Recreation Of An AD
                Group Object Does Not Automatically Enable It For Automatic Members Management With The Logic Of The Deleted Group.
            </para>
            <para type="description"> The
                Using "objectGUID" As Identity In The PSModule Configuration Ensures That The PSModule Is Not Affected By
                Objects Rename Or Objects Move. When A Managed Group, Explicit Inclusion, Explicit Exclusion Is Renamed Or Moved
                Into Different OU, Their "objectGUID" Remains Intact. And The PSModule Continue To Bind To Those Objects Without
                Errors. However This Does Introduce Additional Overhead For The CmdLets Intended To Manage The Groups
                Configuration. When An Object Is Provided To Them They Need To Search For That Object In Active Directory,
                Enumerate The "objectGUID" Of The Object And Specify The Enumerated Value Into The Configuration DataBase. Since
                The CmdLets Query AD, That Query Can Be Made Against Multiple Attributes, Which Does Provide Freedom For The User
                To Use Multitude Of Values When An AD Object Is Provided To A Parameter. Please Refer To Each To The Parameters
                Sections Of Each CmdLet Help Document.
            </para>
            <para type="description">
                When LDAP Queries Are Needed The Things Get More Complicated. The LDAP Queries Work Only With DistinguishedName.
                When You Need To Query About Reports Of A Person, Or Members Of A Group The AD Expects LDAP Query With
                DistinguishedName Values. An Example Of Often Use LDAP Query Clause Is:
            </para>
            <para type="description">
                "&#40;manager=CN=Jane Smith,CN=Users,DC=contoso,DC=com&#41;"
            </para>
            <para type="description">
                If "SnsPsAdGroupMembers" PSModule Keep It As Is Into The Configuration, In Case Of DistinguishedName Change, The
                Logic Will Revert No Results, Which Might Lead To Removal Of All The Members From The Group. Instead The LDAP
                Clause Is Stored Like:
            </para>
            <para type="description">
                "&#40;manager=00000000-0000-0000-0000-000000000000&#41;"
            </para>
            <para type="description">
                This Complicates The PSModule Further, As On The AD Managed Group Configuration Creation / Modification It Have To
                Evaluate The Specified Parameters, Match Them Using RegEx Pattern About Any Distinguished Names, Bind To The AD
                Object Using The Matched DistinguishedName, Enumerates The AD Object "objectGUID" And Amend The Matched
                DistinguishedName With The Enumerated "objectGUID". And Before The Actual AD Managed Group Members Management, It
                Have To Evaluate The Configuration About "objectGUID" Values Using RegEx Matching, Bind To The AD Object Using The
                Matched "objectGUID", Enumerate The AD Object DistinguishedName And Amend The "objectGUID" With The Enumerated
                DistinguishedName. Thus Way Introducing Overhead For The PSModule And For The Domain Controller Which Serves The
                LDAP Requests.
            </para>
            <para type="description">
                To Reduce The Number Of The AD Requests And The Overhead, The PSModule Caches The Attributes Of The Previously
                Bind To Or Queried About AD Objects, And Consequently Uses The Cache Instead Of Making New AD Requests. The
                Effectiveness Of The AD Cache Depends On The Similarities In The Configuration Of The Groups.
            </para>
            <para type="description">
                The Attributes Modified By The "SnsPsAdGroupMembers" PSModule Like "memberOf" AD Attribute, Are Never Cached.
                Caching Those Might Lead To False Positive Or Real Errors.
            </para>
            <para type="description">
                The Values Of The AD Attributes Without Requirements For Uniqueness Cannot Be Used For Indexing And Searches In
                The Cache. For Example There Is No Uniqueness Requirement For "cn" Attribute, You Can Have Multiple Objects With
                The Same "cn" As Long As They Are Located In Different OU's. When A CmdLet Parameter From The PSModule Is Provided
                With "cn" Value, It Must Make LDAP Search To Enumerate The AD Object, Either To Confirm That The Value Corresponds
                To An AD Object Or To Throw Error About Multiple Objects. In Case We Have The Specified Value In The Cache It Is
                Not Certain That There Are No Other Objects With The Same Value In The AD Domain. Whenever We Use AD Attributes
                With Uniqueness Requirements Like Distinguished Name, For Example Presence Of The Provided Value In The Cache Can
                Be Safely Assumed As Correct And Unique, In That Case Query Against The AD Domain Is Not Needed. Usage Of Values
                In Attributes Without Uniqueness Requirements Reduces The Effectiveness Of The AD Cache Feature Further.
            </para>
            <para type="description">
                Introducing A Cache In The PSModule Introduces All Generic Disadvantages Related With Caching, Like Cached
                Outdated Values. The "SnsPsAdGroupMembers" PSModule Keeps The AD Cache In The System Memory. This Does Ensure
                Maximum Speed For Accessing The Cache, With Negative Impact On The Machine Performance Because Of The Increased
                Memory Usage. Together With The Feature Which Does Not Allow Usage Of The PSModule In Multiple PSSession &#40;Which
                Actually Force The Users To Close Their PSSessions Once They Finish Their Job&#41;, Ensures Relatively Short Life Span
                Of The Cached Entries, Thus Way Reducing The Cache Effectiveness But Increasing The Reliability Via Minimizing The
                Possibility For Issues Related With Outdated Entries.
            </para>
            <para type="description">
                Although The Shorter Lifespan Of The Cached Entries Reduces The Possibility For Mistakes, It Does Not Eliminate
                Them Completely. Mistakes Might Happen Without Corrupted Or Outdated Cached Entry. Let Us Assume We Have A
                Department Related Group Where Members Are Added Based On Specific Value In The Department AD Attribute And
                Removed When The Value Is Different. At The Same Time, The Department AD Attribute Is Automatically Synchronized
                From The Company HR System. In Case Of Department Rebranding The Sync From The HR System Will Modify The Attribute
                Value Of All Department Members. In That Case All The Department Members Will Be Removed From The Group. This Is
                Addressed With Introducing Of New Feature Which Prevents Any Members Removal Whenever The Members Enumerated For
                Removing Are More Than Certain Threshold. The Threshold Is Configurable. The Default Value Is 50%.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                "SnsPsAdGroupMembers" Provides A Feature Intended For Quick Identifying Whether A Group Is Automatically Managed
                Or Not, Which Is Disabled By Default. It Could Be Very Annoying And Frustrating To Manually Add Or Remove A Member
                Into A Group And The Automation To Revert The Changes Back Because The Member Does Not Match The Adding Or Match
                The Removing Criteria For The Automatic Group Members Management. Normally The IT Administrators Would Need To
                Check In The PS Module Configuration To Verify Whether An AD Group Is Automatically Managed Using The PSModule
                Before Membership Modification. This Might Lead To Failed Scheduled Tasks Due To Multiple PSSessions With The
                PSModule Loaded. From That Perspective "SnsPsAdGroupMembers" Stores A Predefined Constant Value In A Predefined AD
                Attribute Of The AD Managed Groups And Clears The Predefined Constant Value From The Predefined AD Attribute Of
                The Not Managed Groups. Therefore The Company IT Administrators Just Need To Look At That Attribute Before
                Manually Add Or Remove Groups Members In An AD Group.
            </para>
            <para type="description">
                To Enable This Feature Use "Set-SnsAdGroupMembersPsModuleSettings" CmdLet, To Specify An AD Attribute And A
                Constant Value Which Shall Be Set On The AD Managed Groups. To Disable That Feature Use
                "Set-SnsAdGroupMembersPsModuleSettings" CmdLet To Clear Either The Value Or The AD Attribute Used By This Feature
                Or Both. When Enabled On A Scheduled Job After Actual Group Management "Invoke-SnsAdGroupMembersManage" Sets The
                Predefined Constant Value Into The Predefined AD Attribute Of All Enabled AD Managed Groups And Clears The Value
                From All Not Managed AD Groups. Therefore Once The Feature Is Disabled The User Have To Manually Clear The Value
                From The AD Attribute Of All The Groups In Case The Feature Was Ever Used. Changing The Attribute Will Not Clear
                The Value From The Old Attribute.
            </para>
            <para type="description">
                NOTE: This Feature Considers As Managed Only The Groups That Are Enabled In The Groups Configuration. Disabling A
                Group From Automatic Members Management, Even Temporary Will Clear The AD Attribute Used By This Feature,
                Indicating To The Corporate IT Administrators, That The Group Membership Can Be Managed Manually.
            </para>
            <para type="description">
                NOTE: This Feature Can Use Only AD Attributes With Type Of Single Valued String.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                Set-SnsAdGroupMembersPsModuleSettings Is Intended To Be Used Interactively By A User To Modify The PSModule
                Configuration Into The Configuration DataBase.
            </para>
            <para type="description">
                NOTE: Please Make Sure That The PowerShell Is Closed, When You Finish With The Work On The Managed AD Groups
                Configuration. Otherwise Either The Other Users Or Any Automated Task Will Be Prevented From Work With The
                PSModule.
            </para>
            <para type="description">
                NOTE: "Set-SnsAdGroupMembersPsModuleSettings" CmdLet Modifies "SnsPsAdGroupMembers" PSModule Configuration
                Settings Kept In The Configuration DataBase. The CmdLet Requires The Configuration DataBase To Exists And To
                Contain The Default Settings. The CmdLet Cannot Be Used To Modify The DataBase Paths. If You Need To Do So Please
                Check The Comments In "SnsPsAdGroupMembers.psm1" File. The Location Of That File Will Depend From The Instalation
                Scope When You Installed The PSModule. If You Followed The Warnings Above It Would Be:
            </para>
            <para type="description">
                "C:\Program Files\WindowsPowerShell\Modules\SnsPsAdGroupMembers\&lt;X&gt;.&lt;X&gt;.&lt;X&gt;.&lt;X&gt;\SnsPsAdGroupMembers.psm1"
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In Parameters Validation "Get-SnsAdManagedGroup" CmdLet Verifies Whether The Supplied By The User Values Are
                Valid, Within The Predefined Ranges And From Required Type. The Validation Of "AutomationManagedAttribute" And
                "VerifyLeaversOu" Parameters Actually Make Queries Against AD And Verifies The Attribute And The Organizational
                Units Existence.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                In "BeginProcessing" Method "Get-SnsAdManagedGroup" CmdLet Initializes The PSModule Configuration. Verifies The
                Existence, The Schema And The Integrity Of The Configuration DataBase. Verifies About Other PowerShell Processes
                Using "SnsPsAdGroupMembers" PSModule. This CmdLet Does Not Have "Force" Parameter. It Does Not Makes Any Sense To
                Modify The PSModule Configuration While Another Process Is Running And Possibly Manages The Groups Membership.
            </para>
            <para type="description">
                Next The CmdLet Evaluates The Arguments Supplied To The Parameters And Compare Them With The Current PSModule
                Configuration. Those That Are Different Are Modified. If No Differences To Be Set In The Configuration DataBase
                The CmdLet Reverts Warning That No Configuration Changes Are Made.
            </para>
            <para type="description">
                Then Sends Out The PSModule Configuration Object.
            </para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description"></para>
            <para type="description">
                The CmdLet Reverts SnsPsModuleSetting Object With The Following Properties:
            </para>
            <para type="description">
                - "AutomationManagedAttribute" Property Of Type String. Represents The AD Attribute Name As It Is Seen In
                Attributes Tab Of "Active Directory Users and Computers" Management Console, Used To Indicate Whether Or Not An AD
                Group Is Automatically Managed. Whenever The Property Have No Value The Feature Is Disabled.
            </para>
            <para type="description">
                - "AutomationManagedValue" Property Of Type String. Represents The Value Which The PSModule Put In
                "AutomationManagedAttribute" To Indicate Whether Or Not An AD Group Is Automatically Managed. Whenever The
                Property Have No Value The Feature Is Disabled.
            </para>
            <para type="description">
                - "BlockRemovalPercent" Property Of Type Int32. Contains The Threshold In Percent About Block Automated Group
                Members Removal. In Case Of Organization Changes Or Other Reason, After The AD Accounts Synchronization From An HR
                System, It Might Happen That All The Members Of An Automated Group Match The Removal Logic. To Prevent The Removal
                Of All The Members From A Group "SnsPsAdGroupMembers" PSModule Evaluate The Number Of The Current Members, The
                Members Evaluated For Removal And Calculates Removal Percentage. In case The Removal Percentage Is Bigger Than The
                Value Specified In This Parameter, No Members Are Removed And The Issue Is Reported.
            </para>
            <para type="description">
                - "VerifyLeaversAccountDisabled" Property Of Type Boolean. Indicates Whether The AD Managed Group Configuration Is
                Verified About Bindings To Disabled AD Accounts. Disabling This Verification Will Stop The Events Generation When
                Either Group Notification Contact Or Exclusion Or Inclusion User Leave The Company And His / Hers AD Account Get
                Disabled On All AD Managed Groups. In That Case An IT Administrator Should Regularly Check The AD Managed Groups
                Configuration. To Prevent False Positive Report Events, This Verification Have To Be Disabled Whenever Either
                Notification Contacts Or Inclusions Or Exclusions Or AddLogic Or RemoveLogic Contains Shared Mailboxes.
            </para>
            <para type="description">
                - "VerifyLeaversOu" Property Of Type String Array. Contains An Array With DistinguishedName Parts Of The
                Organizational Units Where The Leavers Accounts Are Kept. According To The Best Practices, When A User Leave The
                Company, The AD Account Is Kept Disabled For Certain Period Of Time. Whenever The Process Include Moving The
                Leavers Accounts To A Dedicated OU This Features Comes In Handy. The PSModule Verifies The Groups Configuration
                About Bindings To AD Accounts Located In Those OU's, And Report That. This Is Very Useful Whenever
                "VerifyLeaversAccountDisabled" Feature Is Disabled. To Disable This Feature Assign Empty Array.
            </para>
            <para type="description">
                - "ReportPositionIssuesWithPrerequisiteGroups" Property Of Type Boolean. Indicates Whether The AD Managed Group
                Configuration Is Verified About AD Managed Groups Used As Input In Other AD Managed Groups Logic, And Whether The
                Prerequisite Group Is Managed After The Dependent One. When The Prerequisite Group Is Managed Beforehand, On The
                Dependent Group Management Will Have Up To Date Input. Otherwise The Dependent Group Will Be Updated Accordingly
                Earliest On The Next Management Schedule.
            </para>
            <para type="description">
                - "WarnAboutMissingLogic" Property Of Type Boolean. Indicates Whether The PSModule Will Throw Warnings Whenever An
                AD Managed Group Have Either AddLogic Or RemoveLogic Missing. Whenever You Have Groups Without Automatic Adding Or
                Removing, Disable This Verification To Avoid Unnecessary Report Events. For Example Whenever You Have Sensitive
                Groups You May Want To Automate Only The Removal From The Group And Using Formal Approval Process With Manual
                Adding. This Will Allow No Room For Forgotten Group Members When They Change Their Position Or Leave The Company.
            </para>
            <para type="description">
                - "MonthsToKeepProcessingEvents" Property Of Type Int32. Contains The Time Interval In Months To Keep The
                Processing Events Into The Statistics DataBase. As Processing Events Are Considered Events Related With The
                Processing Of The Groups Which Lead To Neither Group Members Modification Nor Groups Configuration Modification.
            </para>
            <para type="description">
                - "MonthsToKeepProvisioningEvents" Property Of Type Int32. Contains The Time Interval In Months To Keep The
                Provisioning Events Into The Statistics DataBase. As Provisioning Events Are Considered Events Related With Group
                Members Modification Or Group Configuration Modification.
            </para>
            <list type="alertSet">
                <item>
                    <term> </term>
                    <description>
                        <para>AUTHOR: Svetoslav Nedyalkov Savov</para>
                        <para>THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK</para>
                        <para>OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.</para>
                        <para></para>
                        <para></para>
                        <para></para>
                    </description>
                </item>
            </list>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -AutomationManagedAttribute "extensionAttribute15" -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule To Indicate In "extensionAttribute15" Whether An AD Group Is Automatically Managed.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -AutomationManagedValue "Group Members Automation" -Verbose;
              </code>
              <para></para>
              <para>
                Configures The PSModule To Indicate With Value "Group Members Automation" Whether An AD Group Is Automatically
                Managed.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -BlockRemovalPercent 50 -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule To Prevent Members Removal When It Evaluates More Than 50% Of Members To Remove.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -VerifyLeaversAccountDisabled:$true -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule To Verify About Disabled Accounts In The AD Managed Group Configuration.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -VerifyLeaversOu ",OU=Leavers,", ",OU=Disabled Users," -Verbose;
              </code>
              <para></para>
              <para>
                Configures The PSModule To Consider As Leavers All Accounts Present In The AD Managed Groups Configuration Which
                DistinguishedName Contains At Least One Of The Specified Arguments.
              </para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -ReportPositionIssuesWithPrerequisiteGroups:$true -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule To Verify About Dependancies Between The AD Managed Groups.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -WarnAboutMissingLogic:$true -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule To Verify About AD Managed Groups Without AddLogic Or RemoveLogic.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -MonthsToKeepProcessingEvents 14 -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule Keep The Processing Events In The Statistics DataBase For 14 Months.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -MonthsToKeepProvisioningEvents 14 -Verbose;
              </code>
              <para></para>
              <para>Configures The PSModule Keep The Provisioning Events In The Statistics DataBase For 14 Months.</para>
              <para></para>
              <para></para>
            </example>
            <example>
              <code>
                [SnsAdGroupMembers.SnsPsModuleSetting]$objSettings = Set-SnsAdGroupMembersPsModuleSettings `
                -VerifyLeaversOu $null -Verbose;
              </code>
              <para></para>
              <para>
                Clears The Setting And Disables The Verification About AD Accounts Located In Leavers Organizational Units.
              </para>
              <para></para>
              <para></para>
            </example>
            </summary>
            <para type="link" uri="https://github.com/svesavov/SnsPsAdGroupMembers"> svesavov / SnsPsAdGroupMembers - </para>
            <para type="link" uri="https://www.powershellgallery.com/packages/SnsPsAdGroupMembers/"> PowerShell Gallery - </para>
            <para type="link" uri="https://www.linkedin.com/in/svetoslavsavov"> Svetoslav Savov on LinkedIn - </para>
            <para type="link" uri="https://sqlite.org/index.html"> SQLite V3 - </para>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.AutomationManagedAttribute">
            <summary>
            <para type="description">Specifies An AD Attribute Where Will Be Indicated Whether An AD Group Is Automatically Managed Or Not.</para>
            <para type="description">
                The Attribute Syntax Must Be Exactly As It Is Shown In Attributes Tab Of "Active Directory Users and
                Computers" Console.
            </para>
            <para type="description">To Clear Existing AutomationManagedAttribute Use Either $null Or "".</para>
            <para type="description">Clearing AutomationManagedAttribute Disables The Feature About Indicating Automatically Managed AD Groups.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.AutomationManagedValue">
            <summary>
            <para type="description">Specifies A Value To Indicat Whether An AD Group Is Automatically Managed Or Not.</para>
            <para type="description">
                The Specified Value Will Be Set In The AutomationManagedAttribute Of The Automatically Managed Groups. If Not
                Managed Or Disabled Group Contains The Specified AutomationManagedValue In The Specified
                AutomationManagedAttribute, It Will Be Cleared.
            </para>
            <para type="description">To Clear Existing AutomationManagedValue Use Either $null Or "".</para>
            <para type="description">Clearing AutomationManagedValue Disables The Feature About Indicating Automatically Managed AD Groups.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.BlockRemovalPercent">
            <summary>
            <para type="description">Specifies A Threshold In Precents To Block Automatic Members Removal.</para>
            <para type="description">To Allow Removal Of All Members Without Block, Set The Threshold To 100%.</para>
            <para type="description">When The Threshold Is 0% All Removals Will Be Blocked And This Will Be Reported.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.VerifyLeaversAccountDisabled">
            <summary>
            <para type="description">
                Enables And Disables The Evaluation Of The AD Managed Groups Configuration About Bindings To Disabled AD
                Accounts.
            </para>
            <para type="description">
                When Enabled The AddLogic, RemoveLogic, Notification Contacts, Explicit Inclusions And Explicit Exclusions Of
                The AD Managed Groups Will Be Verified About Values Which Corresponds To Disabled AD Accounts. If The
                Evaluation Reverts Any Results The Issue Will Be Included In The Reports. Whenever A Notification Contact Is
                Disabled AD Account It Will Be Amended With The Email Of The Manager Of The User Taken From "manager"
                Attribute Of The Disabled Account.
            </para>
            <para type="description">Disable This Feature When You Use Bindings To Shared Mailboxes, To Prevent False Positives.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.VerifyLeaversOu">
            <summary>
            <para type="description">
                Specifies An Array With Part Of Distinguished Names Which Uniquely Identify The AD Organizational Units
                Intended To Keep The Leavers AD Accounts.
            </para>
            <para type="description">EXAMPLE: ",OU=Leavers,", ",OU=Disabled Users,DC=contoso,DC=com"</para>
            <para type="description">
                Whenever The Leavers Process Requires The AD Accounts Of The Users Who Left The Company To Be Moved Into
                Dedicated OU's, The PSModule Verifies About Values That Corresponds To Leavers Accounts Located In Those OU's
                In The AD Managed Group Configuration.
            </para>
            <para type="description">
                Whenever Shared Mailboxes Are Used In The AD Managed Groups Configuration And VerifyLeaversAccountDisabled Is
                Disabled, Only This Feature Remains To Report When An AD Managed Group Configuration Is Outdated.
            </para>
            <para type="description">
                Whenever Your Company Leavers Process Does Not Require The Leavers AD Accounts To Be Moved Into Dedicated
                OU's, This Feature Must Be Disabled.
            </para>
            <para type="description">To Disable This Feature Set $null Or @().</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.ReportPositionIssuesWithPrerequisiteGroups">
            <summary>
            <para type="description">
                Enables And Disables The Evaluation Of The AD Managed Groups Configuration About Dependencies Between The
                Groups And Whether The Processing Order OF The Prerequisite And Dependent Groups Is Correct.
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.WarnAboutMissingLogic">
            <summary>
            <para type="description">
                Enables And Disables The Evaluation Of The AD Managed Groups Configuration About Groups With Missing Either
                AddLogic Or Remove Logic.
            </para>
            <para type="description">Whenever You Intentionally Need To Do So, This Verification Have To Be Disabled.</para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.MonthsToKeepProcessingEvents">
            <summary>
            <para type="description">Specifies A Threshold In Months To Preserve The Processing Events In The Statistics Database.</para>
            <para type="description">
                As Processing Events Are Considered Events Related With The Processing Of The Groups Which Lead To Neither
                Group Members Modification Nor Groups Configuration Modification.
            </para>
            <para type="description">
                Statistics DataBase Would Grow With The Time. In Case The Events Are Not Deleted The Growth Would Be Endless,
                Which Will Lead To Performance Issues. Depending On The Environment Size And The Number Of The Automated AD
                Groups The DataBase Might Have Significant Tendency To Grow. From That Perspective The Outdated Events
                Deletion Cannot Be Disabled.
            </para>
            <para type="description">
                Deletion Of Entries Within DataBase Tables Creates White Space Within The DataBase Files. The White Space Can
                Be Used For New Entries In The Tables, Which Leads Over The Time To DataBase File Fragmentation, Which Leads
                To Performance Issues As Well. To Avoid That The DataBase File Must Be Maintained On Regular Basis Using
                "Invoke-SnsStatisticsDataBaseDefragmentation".
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.MonthsToKeepProvisioningEvents">
            <summary>
            <para type="description">Specifies A Threshold In Months To Preserve The Processing Events In The Statistics Database.</para>
            <para type="description">
                As Provisioning Events Are Considered Events Related With Group Members Modification Or Group Configuration
                Modification. With Other Words The Ones Send To The Group Notification Contacts.
            </para>
            <para type="description">
                Statistics DataBase Would Grow With The Time. In Case The Events Are Not Deleted The Growth Would Be Endless,
                Which Will Lead To Performance Issues. Depending On The Environment Size And The Number Of The Automated AD
                Groups The DataBase Might Have Significant Tendency To Grow. From That Perspective The Outdated Events
                Deletion Cannot Be Disabled.
            </para>
            <para type="description">
                Deletion Of Entries Within DataBase Tables Creates White Space Within The DataBase Files. The White Space Can
                Be Used For New Entries In The Tables, Which Leads Over The Time To DataBase File Fragmentation, Which Leads
                To Performance Issues As Well. To Avoid That The DataBase File Must Be Maintained On Regular Basis Using
                "Invoke-SnsStatisticsDataBaseDefragmentation".
            </para>
            </summary>
        </member>
        <member name="P:SnsAdGroupMembers.SetSnsAdGroupMembersPsModuleSettings.DomainController">
            <summary>
            <para type="description">Specifies A Domain Controller Fully Qualified Domain Name.</para>
            <para type="description">If Omitted The CmdLet Will Run Against The Logon Server.</para>
            <para type="description">Using Single Domain Controller For All Tasks Prevents Issues Related With AD Replication Delays.</para>
            <para type="description">
                After Members Or Another Property Modification, The CmdLet Enumerates The Modified Value Back From AD To
                Verify Whether The Modifications Are Successful. To Ensure That The Enumeration Happens Against The Same
                Domain Controller Where The Changes Are Made, Instead Of One Where The AD Replication Did Not Occur Yet, The
                CmdLet Uses A Single Domain Controller.
            </para>
            <para type="description">
                In Case The Domain Controller Used By The CmdLet Goes Down, The CmdLet Will Fail. In That Case Run The CmdLet
                Again And Either Specify Different Domain Controller Or Do Not Specify Any, The CmdLet Will Pick Some Up And
                Running Global Catalog Server.
            </para>
            </summary>
        </member>
    </members>
</doc>