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>
                        <par