web-dev-qa-db-fra.com

Powershell - "Variable d'élément vide:" vs "Remove-Variable"

Lors du stockage temporaire de texte dans des variables Powershell au moment de l'exécution, quel est le moyen le plus efficace de supprimer le contenu d'une variable de la mémoire lorsqu'il n'est plus nécessaire?

J'ai utilisé à la fois Clear-Item variable: et Remove-Variable, mais à quelle vitesse quelque chose est-il supprimé de la mémoire avec ce dernier ou annule-t-il le contenu de la mémoire avec l'ancien?

EDIT: J'aurais dû préciser un peu plus la raison de ma demande.

J'automatise la connexion RDP pour un ensemble de machines virtuelles d'application (l'application ne s'exécute pas en tant que service, développeurs externalisés, longue histoire).

Je développe donc (en grande partie terminé) un script pour regrouper les sessions de lancement sur chacune des machines virtuelles.

L'idée est que la fonction de script qui stocke les informations d'identification utilise read-Host pour demander un nom d'hôte, puis get-credentials pour extraire le domaine/utilisateur/mot de passe.

La passe est ensuite convertie à partir de secure-string en utilisant une clé de 256 bits (clé d’exécution unique pour l’ordinateur/utilisateur qui a stocké les creds et exécuté le lancement du groupe).

Le nom des machines virtuelles, le domaine, l'utilisateur et la passe cryptée sont stockés dans un fichier. Lors du lancement d'une session, les détails sont lus, le mot de passe déchiffré, les détails passés à cmdkey.exe pour stocker les informations d'identification \generic:TERMSRV pour cette machine virtuelle, effacer la variable de passage en texte clair, lancer mstsc sur cet hôte, quelques secondes plus tard, supprimer les informations d'identification du magasin d'informations d'identification Windows. (Si je passais le mot de passe à cmdkey.exe sous un format autre que le texte en clair, la session RDP recevrait des informations d'identification incorrectes ou inexistantes).

Donc, d’où la question, j’ai besoin du mot de passe en texte brut pour exister en mémoire le plus rapidement possible.

Pour que les spécialistes de la sécurité soient satisfaits, le script lui-même est crypté aes256 et un wrapper c # avec son propre ps hôte lise, déchiffre et exécute le script. Il n'y a donc aucune source de texte en clair sur la machine qui l'exécute. (La source cryptée sur un partage de fichiers est si efficace que j'ai un kill switch, vous pouvez simplement remplacer le script crypté par un autre affichant un message l'informant que cette application a été désactivée.)

6
Graham Gold

Vous pouvez utiliser un chronomètre pour obtenir l'heure d'exécution des commandlets. Je pense qu'il n'y a pas vraiment une différence de temps entre ces deux cmdlets. J'utilise normalement "Remove-Item" car à mes yeux, il est préférable de supprimer une variable complète.

$a = "TestA"
$b = "TestB"
$c = "TestC"
$d = "TestD"

$time = New-Object system.Diagnostics.Stopwatch  

Start-Sleep 1
$time.Start() 
$time.Stop()
$system = $time.Elapsed.TotalMilliseconds
Write-Host "Stopwatch StartStop" $system
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:a
$time.Stop()
$aTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $aTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable b
$time.Stop()
$bTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $bTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Clear-Item Variable:c
$time.Stop()
$cTime = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Clear-Item in " $cTime
$time.Reset()

Start-Sleep 1
$time.Start() 
Remove-Variable d
$time.Stop()
$dTime  = $time.Elapsed.TotalMilliseconds - $system
Write-Host "Remove-Variable in " $dTime
$time.Reset()
4
LaPhi

La seule façon dont j'ai pu effacer, avec certitude, le contenu/données de variable est de supprimer toutes les variables en cours d'exécution dans la session en cours en utilisant:

Remove-Variable -Name * -ErrorAction SilentlyContinue

Cela supprime toutes les variables immédiatement. En fait, j'ajoute ceci à la fin de certains de mes scripts, afin de pouvoir être sûr que l'exécution d'un autre script portant potentiellement le même nom n'aura pas de nouvelles données ajoutées ni des résultats non souhaités.

DRAWBACK: Si vous n'avez besoin que d'une variable effacée, ce qui était mon cas il y a quelques minutes, vous devez alors ré-instancier les variables d'entrée requises par votre script.

5
itmadez

Le moyen le plus efficace est de laisser la récupération de place faire son travail. N'oubliez pas que Powershell est entièrement constitué de .NET, avec sa célèbre gestion de la mémoire. Contrôlez toujours votre portée et assurez-vous que les variables sortent de la portée dès qu'elles ne sont plus nécessaires. Par exemple, si des variables temporaires sont nécessaires à l'intérieur des boucles, elles seront automatiquement invalidées à la fin de la boucle, vous n'avez donc pas à vous en soucier, etc.

EDIT: Concernant votre mise à jour, pourquoi ne pas simplement faire $yourPasswordVariable = $null? Je pense que ce serait beaucoup plus facile à comprendre. Et ce devrait être le moyen le plus rapide de le faire. Étant donné que Remove-Item et Clear-Item sont en quelque sorte des gestionnaires tout-en-un, ils doivent d'abord traiter certaines choses avant de déterminer si vous voulez réellement effacer une variable.

5
Neolisk

Les deux suppriment efficacement "une" référence à un objet .NET. Maintenant, si cette référence est la dernière référence à l'objet, le CPG déterminera quand la mémoire de cet objet sera collectée. Cependant, si vous n'avez plus besoin de la variable, utilisez Remove-Variable pour permettre également à la mémoire associée à l'objet System.Management.Automation.PSVariable d'être également collectée.

2
Keith Hill

Pour mesurer le temps nécessaire à l'exécution de blocs de script et d'applets de commande, utilisez Measure-Command

0
syanzy