How can i correct a script that is not working in powershell and wpf displaying a active directory treeview

Tim siktas 0 Reputation points
2024-10-15T09:34:01.83+00:00

I don't want to load everything at the same time but when i click on a node display inside objects only permitting to not freeze the load , as almost is done in dsa.msc on active directory.

Code copy below: this script was given by chatgpt and i modified some different part . but it is not working well.

Importer l'assembly WPF pour utiliser XAML

Add-Type -AssemblyName PresentationFramework

Définir l'interface utilisateur WPF avec XAML

[xml]$xaml = @"

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="Gestion des Comptes AD" Height="500" Width="1400">

<Grid>

    <Label Content="Domaine :" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0"/>

    <ComboBox Name="domainComboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Margin="120,10,0,0"/>

    <Label Content="Nom d'utilisateur :" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,50,0,0"/>

    <TextBox Name="usernameTextBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Margin="120,50,0,0"/>

    <Label Content="New Password :" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,90,0,0"/>

    <TextBox Name="NewPasswordBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Margin="120,90,0,0"/>

    <Button Name="InfoButton" Content="Information User" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Margin="200,10,800,0"/>

    <Button Name="resetButton" Content="Réinitialiser le compte" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Margin="200,40,800,0"/>

    <Button Name="moveButton" Content="Déplacer le compte" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Margin="200,70,800,0"/>

    <Button Name="enableButton" Content="Réactiver le compte" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Margin="200,100,800,0"/>

    <GroupBox Header="Informations Utilisateur" HorizontalAlignment="Left" VerticalAlignment="Top" Width="650" Height="220" Margin="10,130,10,10">

        <Grid>

            <ScrollViewer>

                <TextBox Name="userInfoTextBox" IsReadOnly="True" HorizontalAlignment="Left" VerticalAlignment="Top" Width="650" Height="260" Margin="10,10,10,0" TextWrapping="Wrap" AcceptsReturn="True" Background="LightGray"/>

            </ScrollViewer>

        </Grid>

    </GroupBox>

    <Label Content="Info :" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,350,0,0"/>

    <TextBox Name="infoTextBox" IsReadOnly="True" HorizontalAlignment="Left" VerticalAlignment="Top" Width="660" Height="70" Margin="10,380,0,0" TextWrapping="Wrap" AcceptsReturn="True" Background="LightGray"/>

    <GroupBox Header="Arborescence Active Directory" HorizontalAlignment="Right" VerticalAlignment="Top" Width="300" Height="450" Margin="0,0,400,0">

        <Grid>

            <TreeView Name="adTreeView" HorizontalAlignment="Left" VerticalAlignment="Top" Width="280" Height="420"/>

        </Grid>

    </GroupBox>

</Grid>
```</Window>

"@

# Charger l'interface WPF

$reader = (New-Object System.Xml.XmlNodeReader $xaml)

$window = [Windows.Markup.XamlReader]::Load($reader)

# Remplir la liste déroulante avec des domaines

$window.FindName('domainComboBox').Items.Add('contoso.net')

$window.FindName('domainComboBox').Items.Add('contoso1.net')

$window.FindName('domainComboBox').Items.Add('contoso2.net')

$window.FindName('domainComboBox').Items.Add('contoso3.net')

# Fonction pour afficher les messages d'information dans le TextBox

function Show-Message {

```powershell
param (

    [string]$Message,

    [string]$Type = "Info"  # Par défaut, type "Info", peut être "Error" ou "Success"

)



$infoTextBox = $window.FindName('infoTextBox')



switch ($Type) {

    "Error" { $infoTextBox.Background = 'LightCoral'; }

    "Success" { $infoTextBox.Background = 'LightGreen'; }

    default { $infoTextBox.Background = 'LightGray'; }

}

$infoTextBox.Text = $Message
```}

# Fonction pour récupérer les informations d'un utilisateur

function Get-ADUserInfo {

```powershell
param (

    [string]$Domain,

    [string]$Username

)

try {

    $user = Get-ADUser -Identity $Username -Properties * -Server $Domain

    if ($user) {

        $info = "Nom complet: $($user.DisplayName)`n"

        $info += "SamAccountName: $($user.SamAccountName)`n"

        $info += if ($user.EmailAddress) {"Email: $($user.EmailAddress)`n"} else {"Email: Non disponible sur $Domain`n"}

        $info += "DistinguishedName: $($user.DistinguishedName)`n"

        $info += "Phone: $($user.telephoneNumber)`n"

        $info += "Last connexion: $($user.LastLogonDate)`n"

        $info += "Enable: $($user.Enabled)`n"

        $info += "PasswordExpired: $($user.PasswordExpired)`n"

        $info += "PasswordLastSet: $($user.PasswordLastSet)`n"

        $info += "PasswordNeverExpires: $($user.PasswordNeverExpires)`n"

        $info += "Compte actif: $($user.Enabled)`n"

        $window.FindName('userInfoTextBox').Text = $info

        Show-Message "Utilisateur trouvé : $Username." -Type "Success"

    } else {

        Show-Message "Utilisateur non trouvé." -Type "Error"

    }

} catch {

    Show-Message "Erreur lors de la récupération des informations utilisateur : $($_.Exception.Message)" -Type "Error"

}
```}

# Fonction pour afficher l'arborescence AD

function Load-ADTreeView {

```powershell
param (

    $D

)

$global:domain = $d

# Récupérer le contrôle TreeView

$adTreeView = $window.FindName('adTreeView')

$adTreeView.Items.Clear()

# Fonction pour ajouter les OUs à l'arborescence

function Add-ADNodes {

    param (

        [string]$distinguishedName,

        [System.Windows.Controls.TreeViewItem]$parentNode

    )

    try {

        $childOUs = Get-ADOrganizationalUnit -Filter * -SearchBase $distinguishedName -SearchScope OneLevel -Server $domain

        foreach ($ou in $childOUs) {

            $ouNode = [System.Windows.Controls.TreeViewItem]::new()

            $ouNode.Header = "OU: $($ou.Name)"

            $ouNode.Tag = $ou.DistinguishedName

            $ouNode.IsExpanded = $false  # Initialement, le nœud n'est pas expansé

            $parentNode.Items.Add($ouNode)

            # Enregistrer un événement pour charger dynamiquement les objets quand l'utilisateur clique sur le nœud

            $ouNode.add_Expanded({

                Load-ADObjects -DistinguishedName $ou.DistinguishedName -ParentNode $ouNode

            })

        }

    } catch {

        Write-Host "Erreur lors de l'ajout des nœuds AD: $_"

    }

}

# Fonction pour charger dynamiquement les objets AD (utilisateurs, groupes, ordinateurs) au clic sur un nœud

function Load-ADObjects {

    param (

        [string]$DistinguishedName,

        [System.Windows.Controls.TreeViewItem]$ParentNode

    )

    try {

        if (-not $ParentNode) {

            return

        }

        $adObjects = Get-ADObject -Filter * -SearchBase $DistinguishedName -SearchScope OneLevel -Server $global:domain | Where-Object { $_.ObjectClass -in ('user', 'computer', 'group', 'organizationalunit') }

        foreach ($adObject in $adObjects) {

            $adNode = [System.Windows.Controls.TreeViewItem]::new()

            $adNode.Header = "$($adObject.objectClass): $($adObject.Name)"

            $adNode.Tag = $adObject.DistinguishedName

            $ParentNode.Items.Add($adNode)

        }

    } catch {

        Write-Host "Erreur lors du chargement des objets AD: $_"

    }

}

# Ajouter le domaine racine

try {

    $global:domainDN = (Get-ADDomain -Server $Domain).DistinguishedName

    $rootNode = [System.Windows.Controls.TreeViewItem]::new()

    $rootNode.Header = "Domaine: $((Get-ADDomain -Server $Domain).DNSRoot)"

    $rootNode.Tag = $domainDN

    $rootNode.IsExpanded = $true

    $adTreeView.Items.Add($rootNode)

    # Charger les unités d'organisation (OUs) de la racine

    Add-ADNodes -distinguishedName $global:domainDN -parentNode $rootNode

} catch {

    Write-Host "Erreur lors du chargement de l'arborescence AD: $_"

}
```}

# Ajouter l'événement SelectionChanged pour charger l'arborescence AD quand un domaine est sélectionné

$window.FindName('domainComboBox').add_SelectionChanged({ 

```powershell
$Domain = $window.FindName('domainComboBox').SelectedItem

if ($Domain) {

    Load-ADTreeView -d $Domain

}
```})

# Fonction pour réinitialiser un compte AD

function Reset-ADAccountPassword {

```powershell
param (

    [string]$Domain,

    [string]$Username,

    [string]$NewPassword

)

try {

    Set-ADAccountPassword -Identity $Username -Server $Domain -NewPassword (ConvertTo-SecureString -AsPlainText $NewPassword -Force)

    Unlock-ADAccount -Identity $Username -Server $Domain

    Enable-ADAccount -Identity $Username -Server $Domain

    Show-Message "Mot de passe réinitialisé et compte réactivé avec succès pour l'utilisateur $Username dans $Domain" -Type "Success"

} catch {

    Show-Message "Erreur lors de la réinitialisation du compte : $($_.Exception.Message)" -Type "Error"

}
```}

# Fonction pour déplacer un compte AD

function Move-ADAccount {

```powershell
param (

    [string]$Domain,

    [string]$Username

)

try {

    Move-ADObject -Identity "CN=$Username,OU=OldOU,$Domain" -TargetPath "OU=NewOU,$Domain"

    Show-Message "Compte déplacé avec succès pour l'utilisateur $Username dans $Domain" -Type "Success"

} catch {

    Show-Message "Erreur lors du déplacement du compte : $($_.Exception.Message)" -Type "Error"

}
```}

# Fonction pour réactiver un compte AD

function FEnable-ADAccount {

```powershell
param (

    [string]$Domain,

    [string]$Username

)

try {

    Get-ADUser $Username -Server $Domain | Enable-ADAccount

    Show-Message "Compte réactivé avec succès pour l'utilisateur $Username dans $Domain" -Type "Success"

} catch {

    Show-Message "Erreur lors de la réactivation du compte : $($_.Exception.Message)" -Type "Error"

}
```}

# Actions sur les boutons

$window.FindName('InfoButton').Add_Click({

```powershell
$Domain = $window.FindName('domainComboBox').SelectedItem

$Username = $window.FindName('usernameTextBox').Text



if ($Domain -and $Username) {

    Get-ADUserInfo -Username $Username -Domain $Domain

} else {

    Show-Message "Veuillez remplir le domaine et le nom d'utilisateur." -Type "Error"

}
```})

$window.FindName('resetButton').Add_Click({

```powershell
$Domain = $window.FindName('domainComboBox').SelectedItem

$Username = $window.FindName('usernameTextBox').Text

$newpassword = $window.FindName('NewPasswordBox').Text 



if ($Domain -and $Username -and $newpassword) {

    Reset-ADAccountPassword -Username $Username -Domain $Domain -NewPassword $newpassword

} else {

    Show-Message "Veuillez remplir le domaine, le nom d'utilisateur et le mot de passe." -Type "Error"

}
```})

$window.FindName('moveButton').Add_Click({

```powershell
$Domain = $window.FindName('domainComboBox').SelectedItem

$Username = $window.FindName('usernameTextBox').Text

if ($Domain -and $Username) {

    Move-ADAccount -Domain $Domain -Username $Username

} else {

    Show-Message "Veuillez remplir le domaine et le nom d'utilisateur." -Type "Error"

}
```})

$window.FindName('enableButton').Add_Click({

```powershell
$Domain = $window.FindName('domainComboBox').SelectedItem

$Username = $window.FindName('usernameTextBox').Text

if ($Domain -and $Username) {

    FEnable-ADAccount -Domain $Domain -Username $Username

} else {

    Show-Message "Veuillez remplir le domaine et le nom d'utilisateur." -Type "Error"

}
```})

# Afficher la fenêtre

$window.ShowDialog() | Out-Null
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,784 questions
Active Directory
Active Directory
A set of directory-based technologies included in Windows Server.
6,639 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Hongrui Yu-MSFT 2,465 Reputation points Microsoft Vendor
    2024-10-18T03:57:35.1333333+00:00

    Hi,@Tim siktas.

    Reason: $ouNode.add_Expanded event registration failed.

     

    Solution: You could refer to the following method to register your event.

    Adjust the code in Add-ADNodes( Here I register the logic to be executed by Load-ADObjects directly in $ouNode.add_Expanded)

     

    From

    
    $ouNode.add_Expanded({
         Load-ADObjects -DistinguishedName $ou.DistinguishedName -ParentNode $ouNode
    })
    
    

    To

    
    $ouNode.add_Expanded({
          param($sender, $e)
          $window.Dispatcher.Invoke([System.Action]{
                $ParentNode = $sender
                $OuDistinguishedName = $sender.Tag
                $adObjects = Get-ADObject -Filter * -SearchBase $OuDistinguishedName -SearchScope OneLevel -Server $global:domain | Where-Object { $_.ObjectClass -in ('user', 'computer', 'group', 'organizationalunit') }
                foreach ($adObject in $adObjects) {
                     $adNode = [System.Windows.Controls.TreeViewItem]::new()
                     $adNode.Header = "$($adObject.objectClass): $($adObject.Name)"
                     $adNode.Tag = $adObject.DistinguishedName
                     $ParentNode.Items.Add($adNode)
                 } 
          })                            
    })   
    
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.