English 中文(简体)
AD组比较- PowerShell
原标题:
  • 时间:2008-12-08 15:12:52
  •  标签:

当使用以下功能(比较2个用户的组成员身份)时,我会得到不合理的结果。

function Compare-ADUserGroups <br>
{  #requires -pssnapin Quest.ActiveRoles.ADManagement  
    param (
        [string] $FirstUser = $(Throw "logonname required."),
        [string] $SecondUser = $(Throw "logonname required.")
    )

    $a = (Get-QADUser $FirstUser).MemberOf 
    $b = (Get-QADUser $SecondUser).MemberOf
    $c = Compare-Object -referenceObject $a -differenceObject $b 
    $c | Sort-Object InputObject
}

当我调用此函数(Compare-ADUserGroups User1 User2)时,我会得到类似以下的结果集:

  • CN=[All Users],OU=adm,DC=OSUMC,DC=EDU <=
  • CN=[All Users],OU=adm,DC=OSUMC,DC=EDU =>
  • CN=Extended Users,OU=MSG,DC=OSUMC,DC=EDU <=
  • CN=Extended Users,OU=MSG,DC=OSUMC,DC=EDU =>
  • CN=LCS2005,OU=Distribution Lists,DC=OSUMC,DC=EDU <=
  • CN=LCS2005,OU=Distribution Lists,DC=OSUMC,DC=EDU =>

我希望它们不会显示,因为它们是相等的,我没有使用“-IncludeEqual”参数。你有任何关于为什么它们会出现的想法吗?

问题回答

它们有一些东西使得比较失去了意义。如果你运行,你会看到类似的东西。

get-process | export-clixml cprocs.xml Diff (get-process) (import-clixml c:procs.xml)

因为那些对象的某些属性——例如VM和PM——在两个Get-Process运行之间的短时间间隔内会发生变化。因此,你可能会遇到类似的情况,其中两个对象之间的某些属性有所不同。默认情况下,Compare-Object会查看每个属性。

另一种选择是使用 Compare-Object 的 -property 参数,只比较特定的属性,而不是比较整个对象。由于 Compare-Object 使用对象属性而不仅仅使用文本的方式,因此在这方面它肯定有点棘手。

I write an User Interface to compare groups and apply change between 2 users enter image description here

#requires -version 2
<#
    .SYNOPSIS
        Compare les groupe entre 2 users
    .DESCRIPTION
        Affiche sur 2 colones les les groupes AD des 2 users a comparer et met en evidance les goupes mamquants de chaque user
    .PARAMETER user1
        Nom complet de l utilisateur 1 a comparer
        ex : domain.addsUserName
    .PARAMETER user2
        Nom complet de l utilisateur 2 a comparer
    .EXAMPLE
        .Compare-QadUsersGrp.ps1 $(whoami) $($UserNames)
    .EXAMPLE
        Start-Process -WindowStyle hidden powershell -ArgumentList "-WindowStyle Normal .Compare-QadUsersGrp.ps1 $(whoami) $($UserNames)"
#>


param( 
    [string]$SessionName1 =  Domain	estalb ,
    [string]$SessionName2 =  Domain	estalb2 
)

$currentRunner = $false
$version =  0.60 
$source = "Script Compare-Sessions (alopez)"
$lanStorage = "c:"

    add-content "$lanStorageGet-TSAdmin_Usage-Log.txt" -value "[$(Get-Date -Format  yyyy/MM/dd HH:mm:ss )]  $(whoami) - $($version) Compare-Sessions - $SessionName1  vs  $SessionName2"

############################################### Zone liée a l affichage (refresh) ################################################

    function Refresh-Tabs {
        $loadBar.Visible = $true
        $loadBar.Value = 0

        $ListCompared = Get-vsGrps

        $loadBar.Value = 90
        $SrvForm.height = 178 + $ListCompared.count * 22

        $DefaultColor =  DarkBlue 
        Set-DataGridView -DataGridView $Grille -AlternativeRowColor -ForeColor $DefaultColor -BackColor  AliceBlue 

        Load-DataGridView -DataGridView $Grille -Item (ConvertTo-DataTable -InputObject ($ListCompared | ?{$_}))
        $Grille.Columns["$SessionName2"].Width=320
        $Grille.Columns["$SessionName2"].HeaderCell.Style.Alignment =  MiddleRight 
        #$Grille.Columns["$SessionName2"].AutoSizeMode = $true
        $Grille.Columns["$SessionName2"].DefaultCellStyle.Alignment =  MiddleRight 
        $Grille.Columns[ # ].Width=20
        $Grille.Columns["$SessionName1"].Width=330
        #$Grille.Columns["$SessionName2"].AutoSizeMode = $true

        $Grille.Columns[ DN ].Width = 0
        Find-DataGridViewValue -DataGridView $Grille -Value  ==  -FindingColumns  #  -RowForeColor Gray
        Find-DataGridViewValue -DataGridView $Grille -Value  =>  -FindingColumns  #  -RowForeColor Green
        #Find-DataGridViewValue -DataGridView $Grille -Value  <=  -FindingColumns  #  -RowForeColor Blue

        $loadBar.Value = 100
        $loadBar.Visible = $false

    }

    function Set-DataGridView  {
        PARAM (
            [ValidateNotNull()]
            [Parameter(Mandatory = $true)]
            [System.Windows.Forms.DataGridView]$DataGridView,

            [Parameter(ParameterSetName = "AlternativeRowColor")]
            [Switch]$AlternativeRowColor,

            [Parameter(Mandatory = $true, ParameterSetName = "AlternativeRowColor")]
            [System.Drawing.Color]$ForeColor,

            [Parameter(Mandatory = $true, ParameterSetName = "AlternativeRowColor")]
            [System.Drawing.Color]$BackColor,

            [Parameter(ParameterSetName = "Proper")]
            [Switch]$ProperFormat
        )
        PROCESS
        {

            $DataGridView.DefaultCellStyle.ForeColor = $DefaultColor

            if ($psboundparameters[ AlternativeRowColor ]) { # les ligne PAIRES
                $DataGridView.AlternatingRowsDefaultCellStyle.ForeColor = $ForeColor
                $DataGridView.AlternatingRowsDefaultCellStyle.BackColor = $BackColor
            }


            if ($psboundparameters[ ProperFormat ]) {
                #$Font = New-Object -TypeName System.Drawing.Font -ArgumentList "Segoi UI", 10
                $Font = New-Object -TypeName System.Drawing.Font -ArgumentList "Consolas", 10
                #[System.Drawing.FontStyle]::Bold

                $DataGridView.ColumnHeadersBorderStyle =  Raised 
                $DataGridView.BorderStyle =  Fixed3D 
                $DataGridView.SelectionMode =  FullRowSelect 
                $DataGridView.AllowUserToResizeRows = $false
                $datagridview.DefaultCellStyle.font = $Font
            }
        }  
    }

    function ConvertTo-DataTable {
        <#
            .SYNOPSIS
                Converts objects into a DataTable.
            .DESCRIPTION
                Converts objects into a DataTable, which are used for DataBinding.
            .PARAMETER  InputObject
                The input to convert into a DataTable.
            .PARAMETER  Table
                The DataTable you wish to load the input into.
            .PARAMETER RetainColumns
                This switch tells the function to keep the DataTable s existing columns.
            .PARAMETER FilterWMIProperties
                This switch removes WMI properties that start with an underline.
            .EXAMPLE
                $DataTable = ConvertTo-DataTable -InputObject (Get-Process)
        #>
        [OutputType([System.Data.DataTable])]
        param(
            [ValidateNotNull()]
                $InputObject, 
            [ValidateNotNull()]
                [System.Data.DataTable]
                    $Table,
            [switch]    $RetainColumns,
            [switch]    $FilterWMIProperties
        )

        if($Table -eq $null) {
            $Table = New-Object System.Data.DataTable
        }

        if($InputObject-is [System.Data.DataTable]) {
            $Table = $InputObject
        } else {
            if(-not $RetainColumns -or $Table.Columns.Count -eq 0) {
                #Clear out the Table Contents
                $Table.Clear()

                if($InputObject -eq $null){ return } #Empty Data

                $object = $null
                #find the first non null value
                foreach($item in $InputObject) {
                    if($item -ne $null) {
                        $object = $item
                        break
                    }
                }

                if($object -eq $null) { return } #All null then empty

                #Get all the properties in order to create the columns
                foreach ($prop in $object.PSObject.Get_Properties()) {
                    if(-not $FilterWMIProperties -or -not $prop.Name.StartsWith( __ )) #filter out WMI properties
                    {
                        #Get the type from the Definition string
                        $type = $null

                        if($prop.Value -ne $null) {
                            try{ $type = $prop.Value.GetType() } catch {}
                        }

                        if($type -ne $null) # -and [System.Type]::GetTypeCode($type) -ne  Object )
                        {
                            [void]$table.Columns.Add($prop.Name, $type) 
                        }
                        else #Type info not found
                        { 
                            [void]$table.Columns.Add($prop.Name)    
                        }
                    }
                }

                if($object -is [System.Data.DataRow]) {
                    foreach($item in $InputObject) {   
                        $Table.Rows.Add($item)
                    }
                    return  @(,$Table)
                }
            } else {
                $Table.Rows.Clear() 
            }

            foreach($item in $InputObject) {       
                $row = $table.NewRow()

                if($item) {
                    foreach ($prop in $item.PSObject.Get_Properties()) {
                        if($table.Columns.Contains($prop.Name)) {
                            $row.Item($prop.Name) = $prop.Value
                        }
                    }
                }
                [void]$table.Rows.Add($row)
            }
        }

        return @(,$Table)   
    }

    function Load-DataGridView {
        <#
            .SYNOPSIS
                This functions helps you load items into a DataGridView.
            .DESCRIPTION
                Use this function to dynamically load items into the DataGridView control.
            .PARAMETER  DataGridView
                The ComboBox control you want to add items to.
            .PARAMETER  Item
                The object or objects you wish to load into the ComboBox s items collection.
            .PARAMETER  DataMember
                Sets the name of the list or table in the data source for which the DataGridView is displaying data.
        #>
        Param (
            [ValidateNotNull()]
                [Parameter(Mandatory=$true)]
                    [System.Windows.Forms.DataGridView]
                        $DataGridView,
            [ValidateNotNull()]
                [Parameter(Mandatory=$true)]
                    $Item,
            [Parameter(Mandatory=$false)]
                [string]
                    $DataMember
        )
        $DataGridView.SuspendLayout()
        $DataGridView.DataMember = $DataMember

        if ($Item -is [System.ComponentModel.IListSource] -or $Item -is [System.ComponentModel.IBindingList] -or $Item -is [System.ComponentModel.IBindingListView] ) {
            $DataGridView.DataSource = $Item
        } else {
            $array = New-Object System.Collections.ArrayList

            if ($Item -is [System.Collections.IList]) {
                $array.AddRange($Item)
            } else {   
                $array.Add($Item)   
            }
            $DataGridView.DataSource = $array
        }
        $DataGridView.ResumeLayout()
    }

    function Find-DataGridViewValue {
        # https://github.com/lazywinadmin/WinFormPS/blob/master/WinFormPS.psm1
        <#
            .SYNOPSIS
                The Find-DataGridViewValue function helps you to find a specific value and select the cell, row or to set a fore and back color.

            .DESCRIPTION
                The Find-DataGridViewValue function helps you to find a specific value and select the cell, row or to set a fore and back color.

            .PARAMETER DataGridView
                Specifies the DataGridView Control to use

            .PARAMETER RowBackColor
                Specifies the back color of the row to use

            .PARAMETER RowForeColor
                Specifies the fore color of the row to use

            .PARAMETER SelectCell
                Specifies to select only the cell when the value is found

            .PARAMETER SelectRow
                Specifies to select the entire row when the value is found

            .PARAMETER FindingColumns
                Specifies the column(s) to search Value or NotValue

            .PARAMETER Value
                Specifies the value to search

            .PARAMETER NotValue
                Specifies the value to not match in all column (param FindingColumns is recomanded)

            .EXAMPLE
                PS C:> Find-DataGridViewValue -DataGridView $Grille -Value $textbox1.Text

                This will find the value and select the cell(s)

            .EXAMPLE
                PS C:> Find-DataGridViewValue -DataGridView $Grille -Value $textbox1.Text -RowForeColor  Red  -RowBackColor  Black 

                This will find the value and color the fore and back of the row
            .EXAMPLE
                PS C:> Find-DataGridViewValue -DataGridView $Grille -Value $textbox1.Text -SelectRow

                This will find the value and select the entire row

            .NOTES
                Francois-Xavier Cat
                @lazywinadm
                www.lazywinadmin.com
        #>
        [CmdletBinding(DefaultParameterSetName = "Cell")]
        PARAM (
            [ValidateNotNull()]
            [Parameter(Mandatory = $true)]
            [System.Windows.Forms.DataGridView]$DataGridView,
            $Value,
            $NotValue,
            [string[]]$FindingColumns,
            #[Parameter(ParameterSetName = "Cell")]
            [Switch]$SelectCell,
            #[Parameter(ParameterSetName = "Row")]
            [Switch]$SelectRow,
            #[Parameter(ParameterSetName = "Column")]
            #[Switch]$SelectColumn,
            [Parameter(ParameterSetName = "RowColor")]
            [system.Drawing.Color]$RowForeColor,
            [Parameter(ParameterSetName = "RowColor")]
            [system.Drawing.Color]$RowBackColor
        )

        PROCESS
        {
            $DataGridView.ClearSelection()
            ForEach ($Col in  $DataGridView.Columns) {
                if ($FindingColumns -contains $Col.Name -or !$FindingColumns) {
                    ForEach ($Row in $DataGridView.Rows) {
                        $CurrentCell = $dataGridView.Rows[$Row.index].Cells[$Col.index]

                        if ((-not $CurrentCell.Value.Equals([DBNull]::Value)) -and ( ($Value -and ($CurrentCell.Value.ToString() -like "$Value")) -or ($NotValue -and ($CurrentCell.Value.ToString() -notlike "$NotValue")) ))
                        {
                            # Append-RichtextboxStatus -ComputerName $textboxSocieteName.Text -Source "Find $Value$NotValue" -Message "Colonne:$($col.name) ligne:$($row.index)"
                            # Row Selection
                            IF ($PSBoundParameters[ SelectRow ])
                            {
                                $dataGridView.Rows[$Row.index].Selected = $true
                            }

                            # Row Fore Color
                            IF ($PSBoundParameters[ RowForeColor ])
                            {
                                $dataGridView.Rows[$Row.index].DefaultCellStyle.ForeColor = $RowForeColor
                            }

                            # Row Back Color
                            IF ($PSBoundParameters[ RowBackColor ])
                            {
                                $dataGridView.Rows[$Row.index].DefaultCellStyle.BackColor = $RowBackColor
                            }
                            # Cell Selection
                            ELSEIF (-not ($PSBoundParameters[ SelectRow ]) -and -not ($PSBoundParameters[ RowForeColor ]) -and -not ($PSBoundParameters[ SelectColumn ]))
                            {
                                $CurrentCell.Selected = $true
                            }
                        }#IF not empty and contains value
                    }
                }
            }
        }#PROCESS
    }
############################################### Zone liée aux actions sur les objects ############################################

    $CommonObject = [hashtable]::Synchronized( @{
    })

    function Get-vsGrps {
        Add-PSSnapin  Quest.ActiveRoles.ADManagement 

        $loadBar.Value = 10
        $User1 = Get-QADUser -identity $SessionName1
        $loadBar.Value = 20
        $User2 = Get-QADUser -identity $SessionName2
        $loadBar.Value = 30
        $ListCompared = Compare-Object $User1.memberof $User2.memberof -IncludeEqual | %{
            #$_.InputObject=(Get-QADGroup $_.InputObject).Name
            #$_.InputObject = ($_.InputObject -split( , ))[0] -replace( CN= ,  )
            [pscustomobject][ordered]@{
                "$SessionName2" = $(
                    if ($_.SideIndicator -eq  ==  -or $_.SideIndicator -eq  => ) {
                        ($_.InputObject -split( , ))[0] -replace( CN= ,  )
                    } else {
                          
                    }
                )
                 #  = $_.SideIndicator
                "$SessionName1" = $(
                    if ($_.SideIndicator -eq  ==  -or $_.SideIndicator -eq  <= ) {
                        ($_.InputObject -split( , ))[0] -replace( CN= ,  )
                    } else {
                          
                    }
                )
                DN = $_.InputObject
            }
        } | Sort-Object DN
        $loadBar.Value = 40
        $ListCompared
    }

    function Toggle-Group {
        $loadBar.Value = 0
        $loadBar.Visible = $true
        $loadBar.Value = 50

        $line = $Grille.CurrentCell.RowIndex
        $col = $Grille.CurrentCell.ColumnIndex
        $DN = $Grille.currentrow.Cells[3].value
        $Grp = ($DN -split( , ))[0] -replace( CN= ,  )

        if (@(0,2) -contains $col -and $edit.Checked) {
            $user = $Grille.columns[$Col].HeaderText
            if ($Grille.CurrentCell.value -eq    -or $Grille.CurrentCell.value -like " Supp ($Grp) ! ") {
                add-QADGroupMember -identity $DN -member $user
                retour-email -title "$user : Add  $Grp " -msg "Add $DN"
                $Grille.CurrentCell.value =  " Add ($Grp) ! "
                $Grille.CurrentCell.Style.ForeColor =  Magenta 
            }
            else {
                Remove-QADGroupMember -identity $DN -member $user
                retour-email -title "$user : Supp  $Grp " -msg "Supp $DN"
                $Grille.CurrentCell.value = " Supp ($Grp) ! "
                $Grille.CurrentCell.Style.ForeColor =  Red 
            }
            $Grille.currentrow.Cells[1].value = "><"
            $Grille.currentrow.Cells[1].style.ForeColor =  Red 
        }

        $loadBar.Value = 100
        $loadBar.Visible = $false
    }

    function retour-email {
        param (
            [string] $email = $script:currentRunner,
            [switch] $force = $edit.Checked,
            [string] $title =  . ,
            [string] $msg =  . 
        )
        if ( $email -and $force) {
            Send-MailMessage -To $email -from  Script@mydomain.com  -Subject "$title" -SmtpServer mySmtpServer -BodyAsHtml -Body "$msg"
        }
        add-content "$lanStorageGet-TSAdmin_Usage-Log.txt" -value "[$(Get-Date -Format  yyyy/MM/dd HH:mm:ss )]  $(whoami) - $($version) Compare-Sessions - $title"
    }


############################################### Zone GUI / Interface - formulaire ###############################################

#requires -version 2

Add-Type -AssemblyName  System.Drawing 
Add-Type -AssemblyName  System.Windows.Forms 
[System.Windows.Forms.Application]::EnableVisualStyles()

# permet de faire les requette serveur apres ouverture du formulaire
    $timerOnload = New-Object System.Windows.Forms.Timer 
    $timerOnload.Interval = 500
    $timerOnload.add_Tick({
            Refresh-Tabs

            $script:currentRunner = (whoami | Get-QADUser).email

            $edit.Text = "Edit Mode, with email return ($($script:currentRunner))"
            $timerOnload.Enabled = $false
        })
    $timerOnload.Enabled = $true
    $timerOnload.Start()
# 

#region $SrvForm
$SrvForm = New-Object -TypeName  System.Windows.Forms.Form 
$SrvForm.Name =  SrvForm 
$SrvForm.MaximumSize = New-Object -TypeName  System.Drawing.Size  -ArgumentList @(0, 1200)
$SrvForm.MinimumSize = New-Object -TypeName  System.Drawing.Size  -ArgumentList @(670, 180)
$SrvForm.Size = New-Object -TypeName  System.Drawing.Size  -ArgumentList @(670, 350)
$SrvForm.Padding = New-Object -TypeName  System.Windows.Forms.Padding  -ArgumentList @(1,1,1,0)
$SrvForm.KeyPreview = $True
$SrvForm.Add_KeyDown({ if ($_.KeyCode -eq  Escape ) {$SrvForm.Close()} })
$SrvForm.Add_KeyDown({ if ($_.KeyCode -eq  F5 ) {
            Refresh-Tabs
        }
    })
$icon1 = & {
    $iconString =  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 
    $iconStream = New-Object -TypeName  System.IO.MemoryStream  -ArgumentList @(,([System.Convert]::FromBase64String($iconString)))
    $icon = New-Object -TypeName  System.Drawing.Icon  -ArgumentList $iconStream
    $iconStream.Dispose()
    return $icon
}
$SrvForm.text = "$SessionName2 vs $SessionName1"
$SrvForm.Icon = $icon1
$SrvForm.Topmost = $True
$SrvForm.Topmost = $false

$SrvForm.SuspendLayout()

    #region $groupBox1
    $groupBox1 = New-Object -TypeName  System.Windows.Forms.GroupBox 
    $groupBox1.Text =  Comparatif des groupes (direct) 
    $groupBox1.Dock = [System.Windows.Forms.DockStyle]::Fill
    $groupBox1.SuspendLayout()

        #region $Grille
        $Grille = New-Object -TypeName  System.Windows.Forms.DataGridView 
        $Grille.Name =  Grille 
        $Grille.Dock = [System.Windows.Forms.DockStyle]::Fill
        $Grille.ReadOnly = $true
        $Grille.SelectionMode = [System.Windows.Forms.DataGridViewSelectionMode]::FullRowSelect
        $Grille.RowHeadersVisible = $false
        $Grille.AllowUserToAddRows = $false
        $Grille.AllowUserToResizeRows = $false
        $Grille.AllowUserToDeleteRows = $false
        $Grille.PerformLayout()

        #endregion $Grille

        [System.Void]$groupBox1.Controls.Add($Grille)

        #region $aide
        $aide = New-Object -TypeName  System.Windows.Forms.Label 
        $aide.Name =  aide 
        $aide.Text =  Double-click sur un groupe ajoute ou supprime le groupe pour cet utilisateurs 
        $aide.Visible = $false
        $aide.ForeColor = [System.Drawing.Color]::Red
        $aide.Dock = [System.Windows.Forms.DockStyle]::Bottom
        $aide.TextAlign = [System.Drawing.ContentAlignment]::MiddleRight
        #endregion $aide

        [System.Void]$groupBox1.Controls.Add($aide)

    $groupBox1.ResumeLayout($false)
    $groupBox1.PerformLayout()
    #endregion $groupBox1

    [System.Void]$SrvForm.Controls.Add($groupBox1)

    #region $panel1
    $panel1 = New-Object -TypeName  System.Windows.Forms.Panel 
    $panel1.Size = New-Object -TypeName  System.Drawing.Size  -ArgumentList @(0, 30)
    $panel1.Padding = New-Object -TypeName  System.Windows.Forms.Padding  -ArgumentList @(4)
    $panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
    $panel1.SuspendLayout()

        #region $edit
        $edit = New-Object -TypeName  System.Windows.Forms.CheckBox 
        $edit.Name =  edit 
        $edit.Text =  Mode Edition, avec retour par email de chaque modif 
        $edit.Checked = $false
        $edit.Width = 480
        $edit.Dock = [System.Windows.Forms.DockStyle]::Left
        #endregion $edit

        [System.Void]$panel1.Controls.Add($edit)

        #region $button1
        $button1 = New-Object -TypeName  System.Windows.Forms.Button 
        $button1.Text =  Retour Email complet 
        $button1.Width = 150
        $button1.Dock = [System.Windows.Forms.DockStyle]::Right
        #endregion $button1

        [System.Void]$panel1.Controls.Add($button1)

    $panel1.ResumeLayout($false)
    $panel1.PerformLayout()
    #endregion $panel1

    [System.Void]$SrvForm.Controls.Add($panel1)

    #region $statusStrip1
    $statusStrip1 = New-Object -TypeName  System.Windows.Forms.StatusStrip 
    $statusStrip1.SuspendLayout()

        #region $LabelVersion
        $LabelVersion = New-Object -TypeName  System.Windows.Forms.ToolStripStatusLabel 
        $LabelVersion.Text =  V0.00 
        $LabelVersion.Spring = $true
        $LabelVersion.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
        #endregion $LabelVersion

        [System.Void]$statusStrip1.Items.Add($LabelVersion)

        #region $loadBar
        $loadBar = New-Object -TypeName  System.Windows.Forms.ToolStripProgressBar 
        $loadBar.Style = [System.Windows.Forms.ProgressBarStyle]::Continuous
        $loadBar.Value = 100
        $loadBar.Visible = $true
        #endregion $loadBar

        [System.Void]$statusStrip1.Items.Add($loadBar)

    $statusStrip1.ResumeLayout($false)
    $statusStrip1.PerformLayout()
    #endregion $statusStrip1

    [System.Void]$SrvForm.Controls.Add($statusStrip1)

############################################### Zone personalisation du formilaire ##############################################

$LabelVersion.Text = "[PID:$pid] $($script:MyInvocation.MyCommand) - V $Version"

$button1.add_click({
        retour-email -title "$SessionName2  vs  $SessionName1" -msg (Get-vsGrps | ConvertTo-Html)
    })

$Grille.add_DoubleClick({
        Toggle-group
    })

$Grille.add_ColumnHeaderMouseClick({
        Find-DataGridViewValue -DataGridView $Grille -Value  ==  -FindingColumns  #  -RowForeColor Gray
        Find-DataGridViewValue -DataGridView $Grille -Value  =>  -FindingColumns  #  -RowForeColor Green
    })

$edit.Add_CheckStateChanged({
        $aide.visible = $edit.Checked
    })

$SrvForm.ResumeLayout($false)
$SrvForm.PerformLayout()
#endregion $SrvForm

#region GUI Startup
$SrvForm.ShowDialog()
#endregion GUI Startup

#$powershell.Dispose()
#$runspace.close()
$timerOnload.stop()

Get-vsGrps

我最好的猜测是,Get-QADUser提供的MemberOf属性可能返回一个对象,而不仅仅是作为字符串的分明名称。下面是我用于比较Active Directory组成员资格的脚本:

# Compare the group memberships of 2 Active Directory Users or the user memberships of 2 Active Directory Groups.
# Requires the ActiveDirectory PowerShell module from the Microsoft s Remote Server Administration Tools.

Import-Module ActiveDirectory

function Get-ComparisonResult ($name1, $name2, $sideIndicator)
{
    $comparisonResult = $null

    switch ($_.SideIndicator)
    {
         <=  { $comparisonResult = "$($name1) Only" }
         ==  { $comparisonResult = "$($name1) and $($name2)" }
         =>  { $comparisonResult = "$($name2) Only" }
    }

    return $comparisonResult
}

function Compare-ADUserGroupMembership($userName1, $userName2)
{
    $userComparisonResultColumn = @{ name =  Comparison Result ; expression = { Get-ComparisonResult $user1.DisplayName $user2.DisplayName  $_.SideIndicator } }
    $groupNameColumn = @{ name =  Group Name ; expression = { (Get-ADGroup $_.InputObject).Name } }

    $user1 = Get-ADUser $userName1 -Properties memberOf, displayName
    $user2 = Get-ADUser $userName2 -Properties memberOf, displayName

    $userGroupComparison = Compare-Object -IncludeEqual $user1.MemberOf $user2.MemberOf | Select $userComparisonResultColumn, $groupNameColumn

    return $userGroupComparison
}

function Compare-ADGroupMembership($groupName1, $groupName2)
{
    $groupComparisonResultColumn = @{ name =  Comparison Result ; expression = { Get-ComparisonResult $groupName1 $groupName2 $_.SideIndicator } }
    $userNameColumn = @{ name =  User Name ; expression = { $_.InputObject.name } }

    $groupMembers1 = Get-ADGroupMember $groupName1
    $groupMembers2 = Get-ADGroupMember $groupName2

    $groupMemberComparison = Compare-Object -IncludeEqual $groupMembers1 $groupMembers2 | Select $groupComparisonResultColumn, $userNameColumn

    return  $groupMemberComparison
}

Compare-ADUserGroupMembership  userone   usertwo  | ft -AutoSize
Compare-ADGroupMembership  Group One   Group Two  | ft -AutoSize




相关问题
热门标签