> 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

Suivez les meilleures pratiques de PowerShell Universal en matière d'environnements, de mise en cache, de conception d'API, de sortie des tâches, de performance des applis et de fiabilité de l'héberge

## 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 à partir d'un dépôt de scripts. Autrement dit, lors du déploiement en production, il est avantageux d'utiliser un artéfact bien testé comme base de 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 devoir mettre à jour manuellement un système de production. PowerShell Universal offre également une fonctionnalité de [Déploiement ](/powershell-universal/fr/config/deployments.md)qui peut servir à publier des configurations directement dans 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 en fonction de la taille de l'équipe et de l'utilisation, ce type de configuration peut ne pas être nécessaire.

### Désactiver l'édition Code First lorsqu'elle n'est pas utilisée

La fonctionnalité d'édition Code First détecte les changements dans le répertoire du dépôt à l'aide d'un observateur de système de fichiers. Cette fonctionnalité est utile lorsque vous développez une configuration PowerShell Universal directement à partir du 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 dépôt, comme des journaux, peut amener le système de configuration de PowerShell Universal à se recharger inutilement.

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

Si vous effectuez des changements par la console d'administration, par la synchronisation git ou à l'aide de déploiements, vous devriez désactiver le rechargement automatique. Cela augmentera la performance et réduira également le risque de changements inattendus à votre configuration déployée.

<figure><img src="https://3889731354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwUiExB0UUkGzbColxNZX%2Fuploads%2Fgit-blob-6254d59a2ee13f283ff93a12fcdba9496684522f%2Fimage%20(4).png?alt=media" alt=""><figcaption></figcaption></figure>

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

{% hint style="info" %}
Cela ne fait pas référence au paramètre de type switch `-Integrated` des applets de commande PSU et ne s'applique qu'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 terminal 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 il peut être redémarré sans affecter le reste du système. Avec 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 se termine 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 peut-être lui-même. Cela peut entraîner des problèmes de liaison d'assemblys qui peuvent empêcher les modules importés de fonctionner comme prévu.

Les environnements PowerShell 7 et Windows PowerShell 5.1 offriront la plus grande compatibilité avec les modules, car ils tirent parti de l'exécutable `Universal.Agent` qui peut contrôler le chargement des assemblys, 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 voudrez utiliser ces modules dans des opérations transitoires comme des tâches.

Par exemple, dbatools peut provoquer des fuites de 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 récupérée automatiquement.

Voici une liste de certains modules avec lesquels nous avons éprouvé des problèmes.

* VMware PowerCLI - La gestion des connexions est limitée à la portée du processus
* Az - La gestion des connexions est limitée à la portée du processus

### Tirer parti des modules personnalisés

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

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

Envisagez également de créer des fonctions pour encapsuler les composants complexes des tableaux de bord. Cela réduit la complexité globale du script du tableau de bord et le rend facile à déboguer et à lire.

### Définir une durée de vie du cache

Lorsque vous utilisez `Set-PSUCache`, assurez-vous de définir une forme de durée de vie pour le cache. C'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 placées dans le cache sans durée de vie ne sont jamais retournées au système.

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

```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 qu'un stockage binaire. Le stockage de nombreux objets dans un seul élément mis en cache entraînera une faible performance de désérialisation lorsque les données atteindront certaines limites.

Cela peut nuire au serveur PowerShell Universal, car il doit récupérer puis désérialiser une longue chaîne chaque fois que les données sont lues à partir du cache.

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

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

Envisagez de stocker les données dans de plus petites partitions. Si possible, segmentez les données en plus petits fragments pour éviter de récupérer une valeur volumineuse de 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 la performance du système, vous pouvez réduire les niveaux de journalisation. Cela doit être fait à deux endroits.

D'abord, vous voudrez réduire le paramètre System Log Level. Il se trouve dans `appsettings.json`. Envisagez de changer le niveau de Verbose à Warning ou Error.

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

Ensuite, vous pouvez ajuster les cibles de journalisation pour modifier les niveaux ou réduire les fonctionnalités qui sont 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 terminaux d'API sérialisent les objets retournés en JSON à l'aide de `ConvertTo-Json`. Bien que la plateforme restreigne la profondeur du JSON, des objets très complexes peuvent faire en sorte que l'applet de commande s'emballe et consomme des quantités élevées 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 bien 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 aussi 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. Sélectionnez plutôt seulement 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. Des 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 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 d'être traitée, mais que le pool de threads HTTP récupère la connexion disponible.

Par exemple, vous pourriez avoir les API suivantes. Le premier terminal démarre une tâche et retourne l'ID de la tâche. Le second terminal récupère la sortie du 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 terminaux, nous pourrions procéder comme 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
```

## Automatisation

### Réduire les sorties de tâches inutiles

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

#### Ignorer la sortie du pipeline

Si vous n'allez pas utiliser la sortie du pipeline, vous pouvez indiquer à PowerShell Universal de l'ignorer. Cela réduira la quantité de données stockées et augmentera la performance de vos tâches, car le système n'a pas besoin de sérialiser toute la sortie pour le stockage. Vous verrez toujours vos flux de sortie dans le journal de la tâche.

#### Tirer parti des flux

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

Par exemple, si vous utilisez `Write-Debug` dans tout votre script, vous pouvez le désactiver au moyen de la variable `$DebugActionPreference` en la réglant à `SilentlyContinue`. Si la tâche commençait à éprouver des problèmes, vous pourriez la régler à `Continue` pour voir la sortie dans le journal.

#### Utiliser Out-Null

`Out-Null` peut capturer une sortie de pipeline potentielle et l'ignorer. Si vous ne voulez pas ignorer toute la sortie du pipeline, vous pouvez en ignorer une partie en utilisant `Out-Null`. Cela améliorera la performance et réduira la taille des données de vos tâches.

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

Certaines tâches, comme un déclencheur utilisé pour des notifications, peuvent n'être presque jamais examinées. Envisagez dans ce cas de régler l'historique des tâches à un niveau très bas.

## Applis

### Utiliser des fonctions dans les applis

Lors de la création de sections complexes d'une appli, il est conseillé de les encapsuler dans une fonction afin de 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'appli.

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

Un exemple serait d'encapsuler la logique d'un tableau dans une fonction et d'utiliser ensuite cette fonction dans l'appli.

```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 de tirer parti des tâches

Les tâches sont utiles parce qu'elles démarrent un processus externe et peuvent servir à auditer les interactions avec l'appli. Comme les applis sont de longue durée, certaines opérations et certains modules peuvent commencer à causer des problèmes de mémoire ou d'autres ressources s'ils sont utilisés sous charge. Le démarrage de tâches garantit que l'environnement est récupéré après chaque exécution.

Les tâches sont logiques pour les opérations qui apportent des changements (p. ex. créer une machine virtuelle ou un utilisateur), mais leurs caractéristiques de performance ne conviendront pas à tous les scénarios.

Un exemple serait d'appeler une tâche à partir d'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 applis

Si vous éprouvez des problèmes avec les ressources des applis, vous pouvez redémarrer les applis à l'aide d'une tâche planifiée qui s'exécute en dehors des heures d'ouverture. Vous pouvez utiliser les applets de commande `Get-PSUApp`, `Stop-PSUApp` et `Start-PSUApp` pour redémarrer les applis individuelles. Cette technique n'est valide que lorsque les applis s'exécutent dans des environnements non intégrés.

### Soyez conscient de la performance de -Render avec New-UDTable

Une fonctionnalité de `New-UDTable` et `New-UDTableColumn` est la capacité de rendre des colonnes pour contenir tout composant que vous souhaitez afficher en fonction de la ligne de données que vous fournissez au tableau. C'est habituellement 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. Rendre de nombreuses lignes à la fois ou utiliser le ScriptBlock de rendu pour exécuter des processus de longue durée causera des problèmes.

#### Rendu d'un trop grand nombre de lignes

Si vous utilisez le paramètre `-Data` de `New-UDTable`, le ScriptBlock `-Render` sera appelé pour chaque élément que vous passez 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 une seule 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 suggéré 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éléguer le rendu au serveur et afficher un squelette de chargement. Le serveur peut alors planifier efficacement l'opération de rendu à l'aide du pool de runspaces.

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 lentes à rendre.

<figure><img src="https://3889731354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwUiExB0UUkGzbColxNZX%2Fuploads%2Fgit-blob-152cd1e662c50ff620fbe060bf9ea709af361eaf%2Fimage%20(375).png?alt=media" alt=""><figcaption></figcaption></figure>

## Portail

### Éviter les appels d'applets de commande tierces dans les Widgets

Lorsque c'est possible, évitez d'appeler des applets de commande tierces directement dans les Widgets. Chaque widget a son propre runspace, mais tous les Widgets s'exécutent dans le processus du serveur PowerShell Universal. Appeler des applets de commande directement dans les Widgets fait charger des assemblys .NET dans le serveur. Cela peut entraîner des conflits avec d'autres chargements d'assemblys. De plus, la mémoire peut ne pas être récupérée des commandes appelées dans le runspace.

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

Pour une bonne expérience utilisateur, il n'est pas toujours logique de démarrer une tâche pour chaque interaction sur une page. Envisagez d'utiliser les applets de commande PSUCache pour définir et récupérer des données du cache afin d'améliorer les temps de chargement des pages.

Tous les modules ne causeront pas de problèmes, donc cette technique n'est pas toujours nécessaire. Il est très peu probable que les modules de script causent des problèmes de chargement d'assemblys.

## Infrastructure et hébergement

### Serveur PowerShell Universal dédié

Envisagez un serveur PowerShell Universal dédié pour héberger la plateforme. Évitez de l'installer aux côtés d'autres plateformes qui pourraient créer des conflits de ressources avec l'application. PowerShell Universal utilise des fonctionnalités PowerShell standards comme les modules, les stratégies d'exécution et la configuration de la communication à distance, et d'autres plateformes pourraient configurer ces paramètres d'une manière qui convient mal à PSU.

### Utiliser MS SQL ou PostgreSQL en production

Évitez d'utiliser SQLite pour les cas d'utilisation en production. Il n'offre pas la capacité de mise à l'échelle lorsque les charges de travail augmentent. Il empêche plusieurs serveurs PSU d'utiliser le même magasin de données. Il ne s'adapte pas lorsque les tailles dépassent 2 Go.

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

### Effectuer des sauvegardes de données 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 dépôt, la base de données contient des ressources telles que les jetons d'application, les identités locales, l'historique des tâches et plus encore. Des sauvegardes de données régulières aident aussi à récupérer après l'échec d'une mise à niveau de schéma et permettent de revenir à des versions de schéma antérieures sans avoir à effectuer une rétrogradation de schéma.

### Grappe de bases de données pour la redondance

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

### Équilibrage des charges

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 une meilleure façon d'échelonner 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 le réseau, mais aussi une meilleure performance lors de l'utilisation des applets de commande PowerShell Universal. Elles s'appuient sur des fonctionnalités de HTTPS lors des communications avec la plateforme et se replient sur d'anciennes technologies de communication si celles-ci ne sont pas disponibles.

### Expédition des journaux

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

Vous pouvez également configurer des [cibles de journalisation](/powershell-universal/fr/developpement/logging.md#targets) pour envoyer les 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
