J'exécute un script PowerShell sur de nombreux serveurs et il enregistre la sortie dans un fichier texte.
J'aimerais capturer le serveur sur lequel le script est en cours d'exécution. Jusqu'à présent j'ai:
$file = "\\server\share\file.txt"
$computername = $env:computername
$computername | Add-Content -Path $file
Cette dernière ligne ajoute des points d'interrogation dans le fichier de sortie. Oops.
Comment exporter une variable dans un fichier texte dans PowerShell?
Après quelques essais et erreurs, j'ai trouvé que
$computername = $env:computername
travaille pour obtenir un nom d'ordinateur, mais l'envoi de $computername
dans un fichier via Add-Content ne fonctionne pas.
J'ai aussi essayé $computername.Value
.
Au lieu de cela, si j'utilise
$computername = get-content env:computername
Je peux l'envoyer dans un fichier texte en utilisant
$computername | Out-File $file
Le plus simple exemple de Hello World ...
$hello = "Hello World"
$hello | Out-File c:\debug.txt
Remarque: La réponse ci-dessous est écrite du point de vue de Windows PowerShell.
Cependant, il s’applique également à la multiplication des plates-formes PowerShell Coreédition), sauf que cette dernière - de manière louable - régulièrementpar défaut à BOM-less UTF-8encodage de caractères) , qui est le plus largement compatible entre plates-formes et cultures..
Pour compléter réponse utile de bigtv réponse utile avec une alternative plus concise et des informations de base:
# > $file is effectively the same as | Out-File $file
# Objects are written the same way they display in the console.
# Default character encoding is UTF-16LE (mostly 2 bytes per char.), with BOM.
# Use Out-File -Encoding <name> to change the encoding.
$env:computername > $file
# Set-Content calls .ToString() on each object to output.
# Default character encoding is "ANSI" (culture-specific, single-byte).
# Use Set-Content -Encoding <name> to change the encoding.
# Use Set-Content rather than Add-Content; the latter is for *appending* to a file.
$env:computername | Set-Content $file
Lorsque sortie dans un fichier texte _, vous avez 2 choix fondamentaux qui utilise différentes représentations d'objets et utilisez différent défautencodages de caractères} _:
Out-File
(ou >
)/Out-File -Append
(Ou >>
):
Convient aux objets de sortie de anytype _, car le formatage de sortie par défaut de PowerShell est appliqué aux objets de sortie.
Le codage par défaut}, qui peut être modifié avec le paramètre -Encoding
, Est Unicode
, ce qui est TF-16LE dans lequel la plupart des caractères sont codés sous la forme 2octets}. L'avantage d'un codage Unicode tel que UTF-16LE est qu'il s'agit d'un globalalphabet, capable de coder tous les caractères à partir de touteslangues humaines.
>
Et >>
, Via la variable de préférence $PSDefaultParameterValues
, profitant du fait que >
et >>
sont maintenant effectivement des alias de Out-File
et Out-File -Append
. Pour passer à UTF-8, par exemple, utilisez:$PSDefaultParameterValues['Out-File:Encoding']='UTF8'
Pour écrire chaînes et les instances de types connus pour avoir des représentations de chaîne significatives, tels que les types de données de base .NET (booléens, entiers, ...).
.psobject.ToString()
) est appelée sur chaque objet de sortie, ce qui donne des représentations dénuées de sens pour les types qui n'implémentent pas explicitement une représentation explicite; Les instances [hashtable]
En sont un exemple:@{ one = 1 } | Set-Content t.txt
Écrit littéralement System.Collections.Hashtable
Dans t.txt
, Qui est le résultat de @{ one = 1 }.ToString()
.Le codage par défaut}, qui peut être modifié avec le paramètre -Encoding
, Est Default
, qui est la page de code "ANSI") du système. _, un codage sur un octet codage spécifique à la culturelegacy} pour les applications non Unicode, le plus souvent Windows-1252 .
Notez que la documentation déclare actuellement à tort que ASCII est le codage par défaut).
Notez que le but de Add-Content
Est de append contenu dans un fichier existant, et il n’est équivalent à Set-Content
Que si le fichier cible n'existe pas encore.
En outre, le le codage par défaut ou spécifié est aveuglémentappliqué}, quel que soit le codage du contenu existant du fichier.
Out-File
/>
/Set-Content
/Add-Content
Tous agissent culture -sensible), c'est-à-dire qu'ils produisent des représentations adaptées à la culture actuelle (paramètres régionaux), si disponible (bien que les données de formatage personnalisées soient libres de définir leur propre représentation invariante de culture - voir Get-Help about_format.ps1xml
). Cette contraste avec la chaîne de PowerShell expansioninterpolation de chaîne dans les chaînes entre guillemets), qui est culture -_ (invariant - voir cette réponse of mine.
En ce qui concerne performance _: Puisque Set-Content
N'a pas à appliquer le formatage par défaut à son entrée, il fonctionne mieux.
Quant à le symptôme de l'OP avec Add-Content
}:
Puisque $env:COMPUTERNAME
Ne peut pas contenir de caractères non-ASCII, la sortie de Add-Content
, Utilisant le codage "ANSI", devrait pasdonner les caractères ?
Dans la sortie, et l'explication la plus probable est que le ?
faisait partie du contenu préexistantdans le fichier de sortie $file
, auquel Add-Content
ajouté à.
Votre exemple de code semble être OK. Ainsi, le problème fondamental doit être résolu d’une manière ou d’une autre. Éliminons les risques de fautes de frappe dans le script. Tout d’abord, assurez-vous de mettre Set-Strictmode -Version 2.0
au début de votre script. Cela vous aidera à détecter les noms de variables mal orthographiés. Ainsi,
# Test.ps1
set-strictmode -version 2.0 # Comment this line and no error will be reported.
$foo = "bar"
set-content -path ./test.txt -value $fo # Error! Should be "$foo"
PS C:\temp> .\test.ps1
The variable '$fo' cannot be retrieved because it has not been set.
At C:\temp\test.ps1:3 char:40
+ set-content -path ./test.txt -value $fo <<<<
+ CategoryInfo : InvalidOperation: (fo:Token) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
La partie suivante sur les points d’interrogation ressemble à un problème d’Unicode. Quelle est la sortie lorsque vous tapez le fichier avec Powershell,
$file = "\\server\share\file.txt"
cat $file