web-dev-qa-db-fra.com

Comment ajouter une nouvelle ligne à la sortie de commande dans PowerShell?

J'exécute le code suivant à l'aide de PowerShell pour obtenir une liste des programmes d'ajout/suppression du registre:

Get-ChildItem -path hklm:\software\Microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") } `
    | Out-File addrem.txt

Je veux que la liste soit séparée par des nouvelles lignes pour chaque programme. J'ai essayé:

Get-ChildItem -path hklm:\software\Microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") `n } `
    | out-file test.txt

Get-ChildItem -path hklm:\software\Microsoft\windows\currentversion\uninstall `
    | ForEach-Object {$_.GetValue("DisplayName") } `
    | Write-Host -Separator `n

Get-ChildItem -path hklm:\software\Microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { $_.GetValue("DisplayName") } `
    | foreach($_) { echo $_ `n }

Cependant, ils génèrent tous un formatage étrange lors de la sortie sur la console et trois caractères carrés après chaque ligne lors de la sortie dans un fichier. J'ai essayé Format-List, Format-Table, et Format-Wide sans chance. À l'origine, je pensais que quelque chose comme ça marcherait:

Get-ChildItem -path hklm:\software\Microsoft\windows\currentversion\uninstall `
    | ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }

Mais cela m'a juste donné une erreur.

65
mike

Ou bien, définissez simplement le séparateur de champ en sortie (OFS) sur le double interligne, puis assurez-vous d'obtenir une chaîne lorsque vous l'envoyez dans le fichier:

$OFS = "`r`n`r`n"
"$( gci -path hklm:\software\Microsoft\windows\currentversion\uninstall | 
    ForEach-Object -Process { write-output $_.GetValue('DisplayName') } )" | 
 out-file addrem.txt

Attention à utiliser le ` et pas le '. Sur mon clavier (disposition Qwerty en anglais américain), il se trouve à gauche de la 1.
(Déplacé ici à partir des commentaires - Merci Koen Zomers)

84
Jaykul

Essayez ceci:

PS> $nl = [Environment]::NewLine
PS> gci hklm:\software\Microsoft\windows\currentversion\uninstall | 
        ForEach { $_.GetValue("DisplayName") } | Where {$_} | Sort |
        Foreach {"$_$nl"} | Out-File addrem.txt -Enc ascii

Il génère le texte suivant dans mon fichier addrem.txt:

Adobe AIR

Adobe Flash Player 10 ActiveX

...

Remarque: sur mon système, GetValue ("DisplayName") renvoie la valeur null pour certaines entrées. Je les filtre donc. BTW, vous étiez proche avec ceci:

ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }

Sauf que dans une chaîne, si vous devez accéder à une propriété d'une variable, c'est-à-dire "évaluer une expression", vous devez utiliser une syntaxe de sous-expression comme suit:

Foreach-Object -Process { "$($_.GetValue('DisplayName'))`r`n" }

Essentiellement, dans une chaîne à double guillemet, PowerShell développera des variables telles que $_, mais il n'évaluera pas les expressions sauf si vous placez l'expression dans une sous-expression en utilisant la syntaxe suivante:

$(`<Multiple statements can go in here`>).
75
Keith Hill

En fin de compte, ce que vous essayez de faire avec les lignes vides EXTRA entre chacune est un peu déroutant :)

Je pense que ce que vous voulez vraiment faire est d'utiliser Get-ItemProperty . Vous obtiendrez des erreurs lorsque des valeurs seront manquantes, mais vous pourrez les supprimer avec -ErrorAction 0 ou simplement les laisser comme rappels. Étant donné que le fournisseur de registre renvoie des propriétés supplémentaires, vous souhaiterez vous en tenir à Select-Object qui utilise les mêmes propriétés que Get-Properties.

Ensuite, si vous voulez que chaque propriété soit sur une ligne avec une ligne vide, utilisez Format-List (sinon, utilisez Format-Table pour en obtenir une par ligne).

gci -path hklm:\software\Microsoft\windows\currentversion\uninstall |
gp -Name DisplayName, InstallDate | 
select DisplayName, InstallDate | 
fl | out-file addrem.txt
6
Jaykul

Je pense que vous aviez la bonne idée avec votre dernier exemple. Vous avez seulement obtenu une erreur parce que vous essayiez de mettre des guillemets dans une chaîne déjà citée. Cela résoudra le problème:

gci -path hklm:\software\Microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output ($_.GetValue("DisplayName") + "`n") }

Edit: L'opérateur $ () de Keith crée une meilleure syntaxe (j'oublie toujours celle-ci). Vous pouvez également échapper des guillemets entre guillemets de la manière suivante:

gci -path hklm:\software\Microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output "$($_.GetValue(`"DisplayName`"))`n" }
5
Ludovic Chabant

L'option que j'ai tendance à utiliser, principalement parce que c'est simple et que je n'ai pas à y penser, utilise Write-Output comme ci-dessous. Write-Output mettra un marqueur EOL dans la chaîne pour vous et vous pourrez simplement sortir la chaîne finie.

Write-Output $stringThatNeedsEOLMarker | Out-File -FilePath PathToFile -Append

Alternativement, vous pouvez également simplement construire la chaîne entière en utilisant Write-Output puis pousser la chaîne finie dans Out-File .

4
InfoSponge