> For the complete documentation index, see [llms.txt](https://docs.devolutions.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.devolutions.net/powershell-universal/fr/config/best-practices.md).

# Meilleures pratiques

## Général

### Envisager une configuration immuable en production

PowerShell Universal repose sur un système de configuration basé sur des scripts. Cela permet de configurer de nouvelles instances de PowerShell Universal sans appels à la base de données et directement depuis un référentiel de scripts. Ainsi, lors du déploiement en production, il est avantageux d'utiliser un artefact bien testé comme base pour votre configuration PowerShell Universal.

Vous pouvez utiliser des outils comme Docker Compose pour intégrer les fichiers de configuration de PowerShell Universal dans une image de conteneur sans avoir à mettre à jour manuellement un système de production. PowerShell Universal propose également une fonctionnalité de [Déploiement](/powershell-universal/fr/config/deployments.md) qui permet de publier des configurations directement sur une instance. Vous pouvez ensuite utiliser un système de déploiement continu pour mettre à jour vos instances de production dans le cadre d'un flux de travail automatisé.

Selon vos besoins, généralement déterminés par la taille de l'équipe et l'utilisation, ce type de configuration peut ne pas être nécessaire.

### Désactiver la modification code-first lorsqu'elle n'est pas utilisée

La fonctionnalité de modification code-first détecte les changements dans le répertoire du référentiel à l'aide d'un observateur du système de fichiers. Cette fonctionnalité est utile lors du développement d'une configuration PowerShell Universal directement depuis le système de fichiers avec des outils comme Visual Studio Code. Cela dit, elle peut avoir des effets secondaires inattendus si vous ne l'utilisez pas. Par exemple, l'écriture de fichiers dans le référentiel, comme des journaux, peut entraîner le rechargement inutile du système de configuration de PowerShell Universal.

{% hint style="info" %}
Le répertoire du référentiel est par défaut `C:\ProgramData\UniversalAutomation\Repository`
{% endhint %}

Si vous apportez des modifications via la console d'administration, via la synchronisation git ou en utilisant des déploiements, vous devriez désactiver le rechargement automatique. Cela améliorera les performances et réduira le risque de modifications inattendues de votre configuration déployée.

<figure><img src="/files/83plhekNDATq3HYff4lv" alt=""><figcaption></figcaption></figure>

### Privilégier les environnements non intégrés

{% hint style="info" %}
Ceci ne fait pas référence au paramètre de commutateur `-Integrated` des cmdlets PSU et s'applique uniquement aux environnements.
{% endhint %}

Bien que l'environnement intégré soit rapide et facile à utiliser, il exécute toutes vos opérations PowerShell au sein du service PowerShell Universal. Des problèmes avec un seul script ou point de terminaison peuvent affecter la stabilité du système.

Lorsque vous utilisez des environnements non intégrés, un processus PowerShell externe est démarré. Pour les API et les tableaux de bord, ce processus peut être de longue durée, mais peut être redémarré sans affecter le reste du système. Pour les tâches et les terminaux, un nouveau processus est démarré pour chaque instance de la tâche et du terminal. Lorsque les tâches et les terminaux sont arrêtés, le processus est terminé et toutes les ressources consommées par ce processus sont récupérées par le système.

De plus, lors du chargement de modules dans l'environnement intégré, l'espace de processus peut être pollué par différentes versions de DLL communes que PSU utilise lui-même. Cela peut entraîner des problèmes de liaison d'assembly qui peuvent empêcher les modules importés de fonctionner comme prévu.

Les environnements PowerShell 7 et Windows PowerShell 5.1 offriront la meilleure compatibilité avec les modules, car ils tirent parti de l'exécutable `Universal.Agent` qui peut contrôler le chargement des assemblies, contrairement à `pwsh.exe` ou `powershell.exe`.

### Isoler les modules problématiques

Les modules PowerShell complexes peuvent causer des problèmes avec PowerShell Universal. Certains modules ne sont pas conçus pour être hébergés dans un processus de longue durée comme PowerShell Universal. Vous devrez utiliser ces modules dans des opérations transitoires comme les tâches.

Par exemple, dbatools peut laisser fuir des connexions à la base de données lorsqu'il est utilisé directement dans l'environnement intégré de PowerShell Universal. Pour éviter cela, vous pouvez démarrer un processus externe en exécutant une tâche PowerShell Universal dans un environnement non intégré. Le script s'exécutera, le processus se terminera et la connexion à la base de données sera automatiquement récupérée.

Vous trouverez ci-dessous une liste de quelques modules avec lesquels nous avons rencontré des problèmes.

* VMware PowerCLI - La gestion des connexions est limitée au processus
* Az - La gestion des connexions est limitée au processus

### Exploiter les modules personnalisés

La création de modules personnalisés garantit que vous pouvez utiliser les mêmes fonctionnalités dans toute la plateforme PowerShell Universal sans dupliquer le code. Vous pouvez utiliser les mêmes fonctions dans les API, les scripts et les tableaux de bord sans avoir à dupliquer la logique.

Réduire la quantité de script dans chacun de ces endroits peut vous aider à mieux tester et isoler les problèmes causés par l'intégration avec la plateforme ou par le module lui-même.

Envisagez également de créer des fonctions pour encapsuler des composants de tableau de bord complexes. Cela réduit la complexité globale du script du tableau de bord et facilite le débogage et la lecture.

### Définir une durée de vie pour le cache

Lors de l'utilisation de `Set-PSUCache`, assurez-vous de définir une durée de vie pour le cache. Cela est particulièrement important si vous avez des données qui ne sont pas utilisées en permanence et qui sont volumineuses. Les données définies dans le cache sans durée de vie ne sont jamais restituées au système.

Par exemple, vous pouvez utiliser l'expiration glissante pour faire expirer les données du cache si elles ne sont pas utilisées pendant une heure.

```powershell
Set-PSUCache -Key 'Data' -Value (Get-Date) -SlidingExpiration (New-Timespan -Hours 1)
```

### Limiter ou partitionner la taille du cache persistant

Le cache persistant stocke les données dans la base de données PSU. Les données sont sérialisées avec la [classe PSSerializer](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.psserializer?view=powershellsdk-7.4.0) qui fait partie du SDK PowerShell. Ce format de données est le même que celui utilisé par PowerShell Remoting. Étant un format XML, ces données seront considérablement plus volumineuses que le stockage binaire. Le stockage de nombreux objets dans un seul élément de cache entraînera de mauvaises performances de désérialisation une fois que les données auront atteint certaines limites.

Cela peut affecter négativement le serveur PowerShell Universal, car il doit récupérer puis désérialiser une grande chaîne à chaque lecture des données depuis le cache.

Envisagez de sélectionner des sous-ensembles plus petits des objets que vous souhaitez stocker. Par exemple, sélectionnez uniquement les propriétés dont vous avez besoin plutôt que l'objet entier.

```powershell
$Data = Get-ADUser -Properties CN,Enabled 
Set-PSUCache -Key Users -Value $Data
```

Envisagez de stocker les données dans des partitions plus petites. Si possible, segmentez les données en morceaux plus petits pour éviter de récupérer une valeur volumineuse depuis la base de données.

```powershell
$OU1 = Get-ADUser -SearchBase "OU=OU1,DC=PSU" -Properties CN,Enabled 
Set-PSUCache -Key Users_OU1 -Value $OU1
$OU2 = Get-ADUser -SearchBase "OU=OU2,DC=PSU" -Properties CN,Enabled 
Set-PSUCache -Key Users_OU2 -Value $OU2
```

### Réduire le niveau de journalisation en production

Les niveaux de journalisation par défaut de PowerShell Universal sont détaillés. Pour améliorer les performances du système, vous pouvez réduire les niveaux de journalisation. Cela doit être effectué à deux endroits.

Premièrement, vous devrez réduire le paramètre de niveau de journal système. Celui-ci se trouve dans `appsettings.json`. Envisagez de modifier le niveau de Verbose à Warning ou Error.

```json
{
    "SystemLogLevel": "Error"
}
```

Deuxièmement, vous pouvez ajuster les cibles de journalisation pour modifier les niveaux ou réduire les fonctionnalités journalisées.

```powershell
New-PSULoggingTarget -Type "File" -Properties @{
    path = "C:\ProgramData\PowerShellUniversal\log.txt"
} -Level 'Error'

New-PSULoggingTarget -Type "Database" -Properties @{
} -Level 'Error'
```

## API

### Éviter de retourner des objets très complexes

Par défaut, les points de terminaison d'API sérialisent les objets retournés en JSON à l'aide de `ConvertTo-Json`. Bien que la plateforme limite la profondeur du JSON, des objets très complexes peuvent faire tourner la cmdlet hors de contrôle et consommer une grande quantité de CPU. PowerShell Universal tentera d'annuler ce traitement s'il est détecté, mais cela causera tout de même des problèmes avec votre environnement d'API.

Assurez-vous de comprendre la complexité des objets que vous retournez. Si les objets sont trop complexes, envisagez d'utiliser `Select-Object` pour sélectionner un sous-ensemble des données retournées. Vous pouvez également appeler `ConvertTo-Json` vous-même pour contrôler le paramètre `-Depth`.

Un exemple serait de retourner des objets Process avec `Get-Process`. En raison de la complexité du type Process, cela cause des problèmes lors de la sérialisation. À la place, sélectionnez uniquement un sous-ensemble des propriétés requises.

```powershell
Get-Process | Select-Object Name,Id
```

### Éviter les processus de longue durée dans les API

Le pool de threads HTTP est de taille limitée. Les processus de longue durée dans les API peuvent épuiser le pool, ce qui peut causer des problèmes pour l'ensemble du serveur PowerShell Universal. Si vous prévoyez d'avoir une API qui prend plus de quelques secondes, envisagez de faire démarrer une tâche par l'API. Vous pouvez ensuite créer une deuxième API pour vérifier l'état des tâches retournées par la première API. Cela garantira que l'opération continue de s'exécuter, mais le pool de threads HTTP récupère la connexion disponible.

Par exemple, vous pourriez avoir les API suivantes. Le premier point de terminaison démarre une tâche et retourne l'identifiant de la tâche. Le deuxième point de terminaison récupère la sortie de pipeline pour la tâche spécifiée.

```powershell
New-PSUEndpoint -Url '/createReport' -Method POST -Endpoint {
    (Invoke-PSUScript -Name CreateReport.ps1 -Integrated)
}

New-PSUEndpoint -Url '/createReport/:id' -Method GET -Endpoint {
     Get-PSUJob -Id $Id -Integrated | Get-PSUJobPipelineOutput -Integrated
}
```

Pour appeler ces points de terminaison, nous pourrions faire ce qui suit avec `Invoke-RestMethod`.

```powershell
$Id = Invoke-RestMethod http://localhost:5000/createReport -Method POST
Start-Sleep 5
Invoke-RestMethod http://localhost:5000/createReport/$Id -Method GET
```

## Automation

### Réduire la sortie de tâche inutile

Bien que le stockage de la sortie des tâches soit utile pour l'audit, le stockage de toutes les sorties peut faire gonfler la taille de votre stockage, ce qui ralentira les performances de votre système PowerShell Universal. Voici quelques mesures que vous pouvez prendre pour maintenir la sortie des tâches sous contrôle.

#### Ignorer la sortie du pipeline

Si vous n'allez pas utiliser la sortie du pipeline, vous pouvez demander à PowerShell Universal de la supprimer. Cela réduira la quantité de données stockées et améliorera les performances de vos tâches, car le système n'a pas besoin de sérialiser toutes les sorties pour le stockage. Vous verrez toujours vos flux de sortie dans le journal des tâches.

#### Tirer parti des flux

L'utilisation des flux Debug, Warning et Error peut aider à réduire ce qui est affiché par défaut dans la tâche. La définition de la préférence d'action par flux vous permet de désactiver certains flux pour les opérations régulières, mais d'activer les flux lorsque la tâche rencontre des problèmes.

Par exemple, si vous utilisez `Write-Debug` tout au long de votre script, vous pouvez le désactiver via la variable `$DebugActionPreference` en lui attribuant la valeur `SilentlyContinue`. Si la tâche devait commencer à rencontrer des problèmes, vous pourriez lui attribuer la valeur `Continue` pour afficher la sortie dans le journal.

#### Utiliser Out-Null

`Out-Null` peut capturer la sortie potentielle du pipeline et la supprimer. Si vous ne souhaitez pas supprimer toute la sortie du pipeline, vous pouvez en supprimer une partie en utilisant `Out-Null`. Cela améliorera les performances et réduira la taille de vos données de tâche.

### Éliminer agressivement les tâches sans importance

Certaines tâches, comme un déclencheur utilisé pour les notifications, ne seront presque jamais examinées. Dans ce cas, envisagez de définir un historique de tâches très bas.

## Applications

### Utiliser des fonctions dans les applications

Lors de la création de sections complexes d'une application, il est conseillé de les encapsuler dans une fonction pour mieux organiser et isoler cette section complexe. Les tableaux de bord très imbriqués sont difficiles à déboguer et facilitent l'introduction d'erreurs de syntaxe qui affecteront l'ensemble de l'application.

Nous recommandons également d'utiliser des modules pour stocker vos fonctions afin de réduire davantage la taille et la complexité de votre script d'application principal. De plus, les modules peuvent être partagés entre les applications.

Un exemple serait d'encapsuler la logique d'un tableau dans une fonction, puis d'utiliser la fonction dans l'application.

```powershell
function New-ProcessTable {
    $Data = Get-Process
    $Columns = @( 
        New-UDTableColumn -Title 'Name' -Property 'Name'
        New-UDTableColumn -Title 'Id' -Property 'Id'
    )
    New-UDTable -Data $Data -Columns $Columns -ShowSearch
}

New-UDApp -Content {
    New-ProcessTable
}
```

### Envisager d'exploiter les tâches

Les tâches sont utiles car elles démarrent un processus externe et peuvent être utilisées pour auditer les interactions avec l'application. Étant donné que les applications sont de longue durée, certaines opérations et certains modules peuvent commencer à causer des problèmes de mémoire ou d'autres ressources en cas de charge. Le démarrage de tâches garantit que l'environnement est récupéré après chaque exécution.

Les tâches sont appropriées pour les opérations qui apportent des modifications (par exemple, la création d'une VM ou d'un utilisateur), mais leurs caractéristiques de performance ne conviendront pas à tous les scénarios.

Un exemple serait d'appeler une tâche depuis un formulaire.

```powershell
New-UDForm -Content {
   New-UDTextbox -Id 'UserName' -Label 'UserName'
} -OnSubmit {
   Invoke-PSUScript -Name 'CreateUser.ps1' -UserName $EventData.UserName -Environment PS7 -Integrated -Wait
   Show-UDToast "User $($EventData.UserName) was created!"
}
```

### Planifier les redémarrages des applications

Si vous rencontrez des problèmes de ressources avec les applications, vous pouvez redémarrer les applications en utilisant une tâche planifiée qui s'exécute en dehors des heures de bureau. Vous pouvez utiliser les cmdlets `Get-PSUApp`, `Stop-PSUApp` et `Start-PSUApp` pour redémarrer les applications individuelles. Cette technique n'est valide que lorsque les applications s'exécutent dans des environnements non intégrés.

### Être conscient des performances de -Render avec New-UDTable

L'une des fonctionnalités de `New-UDTable` et `New-UDTableColumn` est la possibilité de rendre les colonnes pour afficher n'importe quel composant que vous souhaitez afficher en fonction de la ligne de données que vous fournissez au tableau. Cela est généralement utile pour personnaliser l'apparence ou pour fournir des actions pour les données de la ligne. Le rendu peut devenir un problème de performance s'il est utilisé incorrectement. Le rendu de nombreuses lignes à la fois ou l'utilisation du bloc de script de rendu pour exécuter des processus de longue durée causera des problèmes.

#### Rendu de trop nombreuses lignes

Si vous utilisez le paramètre `-Data` de `New-UDTable`, le bloc de script `-Render` sera appelé pour chaque élément que vous transmettez au paramètre de données. Si vous avez des centaines ou des milliers d'éléments, cela augmentera les temps de chargement des pages.

Envisagez d'utiliser `-LoadData` pour charger et afficher uniquement une page de données à la fois. Cela n'appelle `-Render` que pour les éléments affichés et non pour l'ensemble des données.

#### Rendus de longue durée

En raison des détails d'implémentation de `-Render`, il n'est pas conseillé d'utiliser des opérations de rendu de longue durée. Si vous prévoyez que votre `-Render` prendra plus de quelques millisecondes, envisagez d'utiliser `New-UDDynamic` pour décharger le rendu vers le serveur et afficher un squelette de chargement. Le serveur peut planifier efficacement l'opération de rendu à l'aide du pool de runspaces dans ce cas.

Un exemple de cela est présenté ci-dessous.

```powershell
$Data = @(
    @{Dessert = 'Frozen yoghurt'; Calories = 1; Fat = 6.0; Carbs = 24; Protein = 4.0 }
    @{Dessert = 'Ice cream sandwich'; Calories = 159; Fat = 6.0; Carbs = 24; Protein = 4.0 }
    @{Dessert = 'Eclair'; Calories = 159; Fat = 6.0; Carbs = 24; Protein = 4.0 }
    @{Dessert = 'Cupcake'; Calories = 159; Fat = 6.0; Carbs = 24; Protein = 4.0 }
    @{Dessert = 'Gingerbread'; Calories = 200; Fat = 6.0; Carbs = 24; Protein = 4.0 }
) 

$Columns = @(
    New-UDTableColumn -Property Dessert -Title Dessert -Render { 
        New-UDDynamic -Content {
            Start-Sleep (Get-Random -Min 1 -Max 5)
            New-UDButton -Text "Click for Dessert!" -OnClick { Show-UDToast -Message $EventData.Dessert } -Variant 'text'
        } -LoadingComponent {
            New-UDSkeleton
        }
    }
    New-UDTableColumn -Property Calories -Title Calories 
    New-UDTableColumn -Property Fat -Title Fat 
    New-UDTableColumn -Property Carbs -Title Carbs 
    New-UDTableColumn -Property Protein -Title Protein 
)
```

Le résultat est un tableau qui se charge immédiatement, mais qui affiche des squelettes de chargement dans les colonnes dont le rendu est lent.

<figure><img src="/files/6jVqeZPwHMdDRBfOg2IX" alt=""><figcaption></figcaption></figure>

## Portail

### Éviter les appels de cmdlets tiers dans les widgets

Dans la mesure du possible, évitez d'appeler des cmdlets tiers directement dans les widgets. Chaque widget possède son propre runspace, mais tous les widgets s'exécutent dans le processus du serveur PowerShell Universal. L'appel de cmdlets directement dans les widgets entraîne le chargement d'assemblies .NET dans le serveur. Cela peut provoquer des conflits avec d'autres chargements d'assemblies. De plus, la mémoire des commandes appelées dans le runspace peut ne pas être récupérée.

L'utilisation de `Invoke-PSUScript` et l'exécution d'un script dans un environnement externe garantissent que tous les chargements d'assemblies sont confinés à un processus séparé et que toute la mémoire est récupérée après la fin du processus.

Pour une bonne expérience utilisateur, il peut ne pas toujours être judicieux de démarrer une tâche pour chaque interaction sur une page. Envisagez d'utiliser les cmdlets PSUCache pour définir et récupérer des données depuis le cache afin d'améliorer les temps de chargement des pages.

Tous les modules ne causeront pas de problèmes, donc cette technique peut ne pas toujours être nécessaire. Les modules de script sont très peu susceptibles de causer des problèmes avec le chargement des assemblies.

## Infrastructure et hébergement

### Serveur PowerShell Universal dédié

Envisagez un serveur PowerShell Universal dédié pour héberger la plateforme. Évitez d'installer aux côtés d'autres plateformes qui pourraient causer une contention des ressources avec l'application. PowerShell Universal utilise des fonctionnalités PowerShell standard comme les modules, les politiques d'exécution et la configuration de remoting, et d'autres plateformes peuvent configurer ces paramètres d'une manière qui pourrait ne pas bien fonctionner avec PSU.

### Utiliser MS SQL ou PostgreSQL pour la production

Évitez d'utiliser SQLite pour les cas d'utilisation en production. Il ne permet pas de s'adapter à la montée en charge des charges de travail. Il empêche plusieurs serveurs PSU d'utiliser le même magasin de données. Il ne s'adapte pas lorsqu'il atteint des tailles supérieures à 2 Go.

La migration d'une base de données SQLite vers une base de données SQL peut être sujette aux erreurs et prendre du temps. Si vous envisagez un déploiement pour une utilisation en production, nous recommandons de commencer avec un serveur SQL centralisé.

### Effectuer des sauvegardes planifiées de la base de données

Nous recommandons de sauvegarder la base de données à intervalles réguliers. Bien que les données de configuration soient principalement stockées dans le référentiel, la base de données contient des ressources telles que les jetons d'application, les identités locales, l'historique des tâches, etc. Les sauvegardes régulières aident également à récupérer des mises à niveau de schéma échouées et permettent de revenir à des versions de schéma précédentes sans avoir à effectuer une rétrogradation de schéma.

### Cluster de base de données pour la redondance

Nous recommandons d'utiliser un cluster de basculement de base de données, si possible. Cela permet une récupération rapide et limite les temps d'arrêt du serveur PowerShell Universal si l'un des serveurs SQL devait se mettre hors ligne.

### Équilibrage de charge

Envisagez d'utiliser un équilibreur de charge devant vos instances PowerShell Universal. Les utilisateurs seront dirigés vers le serveur le moins occupé ou basculeront depuis les serveurs hors ligne. Cela offre également un meilleur moyen de planifier les mises à niveau de l'application PowerShell Universal.

PowerShell Universal prend en charge les équilibreurs de charge comme F5.

### Utiliser HTTPS

[HTTPS](/powershell-universal/fr/config/hosting.md#configuring-https) offre non seulement une protection contre les attaquants qui écoutent sur le réseau, mais il offre également de meilleures performances lors de l'utilisation des cmdlets PowerShell Universal. Ils s'appuient sur les fonctionnalités de HTTPS lors de la communication avec la plateforme et se rabattent sur des technologies de communication héritées si elles ne sont pas disponibles.

### Expédition des journaux

Les fichiers journaux système sont écrits dans le dossier `%ProgramData%\PowerShellUniversal\Logs` et seront purgés après 30 jours. Par défaut, un nouveau fichier journal est écrit chaque jour. Envisagez d'expédier les journaux depuis ce répertoire vers votre SIEM si vous avez l'intention de conserver les journaux plus de 30 jours.

Vous pouvez également configurer les [Cibles de journalisation](/powershell-universal/fr/developpement/logging.md#targets) pour envoyer des messages de journal directement à un SIEM.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.devolutions.net/powershell-universal/fr/config/best-practices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
