1
votes

Mesurer le temps d'exécution du processus de démarrage avec des paramètres

J'ai un script qui exécute les commandes suivantes:

$args = @"
& -quit -batchmode -logFile "$logfile" -buildWindows64Player "$($fullpath)\Project.exe"
"@

Je veux mesurer combien de temps cela prend. Basé sur cet article , j'essaye ce qui suit:

Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null, empty, or an element of
the argument collection contains a null value. Supply a collection that does not contain any null values and then try
the command again.
At C:\!scripts\pullandbuild.ps1:78 char:90
+ ... d -expression { $result = Start-Process -Wait -PassThru $proc $args }
+                                                                   ~~~~~
    + CategoryInfo          : InvalidData: (:) [Start-Process], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand

Malheureusement, cela génère l'erreur suivante:

$buildtime = measure-command -expression { $result = Start-Process -Wait -PassThru $proc $args }

En raison d'autres problèmes que j'ai rencontrés avec les chaînes et l'expansion des variables, $ args est défini comme ceci:

$result = Start-Process -Wait -PassThru $proc $args

Comment peut Je répare ça? Ou existe-t-il un autre moyen de capturer le runtime du script? J'essaie d'apprendre PS donc je préfère éviter de simplement capturer le temps avant de l'exécuter et après avoir exécuté et comparé, mais si c'est ma seule option, je le ferai.


1 commentaires

N'écrivez pas manuellement dans $ args , c'est un variable automatique


3 Réponses :


3
votes

Edit: Je viens de vérifier, votre variable $ args est vide, il s'avère que $ args est une variable intégrée. Une fois que j'ai changé le nom de la variable, il n'est plus nul, essayez ça.

Et si vous essayez l'une de ces approches:

1.

$startTime = Get-Date
$processToRun = Start-Process notepad.exe -PassThru -Wait
$finishTime = Get-Date
$timeDifference = New-TimeSpan -Start $startTime -End $finishTime
  1. Utilisez les propriétés StartTime et ExitTime de $ result, puis comparez les heures à l'aide de New-Timespan


1 commentaires

Autres approches: l'utilisation de Get-Date est pratique, surtout si vous voulez voir la sortie de la commande, mais notez qu'il est préférable d'utiliser (Get-Date) .ToUniversalTime () ou, dans PSv5 +, [datetime] :: UtcNow . Measure-Command utilise une synchronisation plus précise, bien que cela importera probablement rarement dans la pratique. Notez que vous pouvez soustraire directement 2 instances [datetime] pour obtenir une instance [timespan] ( $ finishTime - $ startTime ) - pas besoin de New-TimeSpan . Une mise en garde concernant System.Diagnostics.Process.StartTime : il ne fonctionne pas sur les plates-formes de type Unix dans PowerShell Core et renvoie $ null .



-1
votes

Pour mettre des guillemets:

"Start-Process -Wait -PassThru $ proc $ args"

devrait être:

$ buildtime = mesure-commande -expression {$ results = "Start-Process -Wait -PassThru $ proc $ args"}

et

'@ & -quit -batchmode "-logFile $ logfile" -buildWindows64Player "$ ($ fullpath) \ Project.exe" @'


2 commentaires

Veuillez formater correctement votre code et votre exemple d'entrée / sortie .


Ce que vous proposez est une chaîne extensible , pas une commande à exécuter.



2
votes

la réponse de stivix contient le pointeur crucial - $ args est un variable automatique à ne pas utiliser en tant que variable personnalisée - mais cela vaut la peine d'approfondir:

$ args est automatiquement défini sur le tableau ( [object []] ) d'arguments de position passés à un script simple [bloc] ou fonction [1] , à l'intérieur de cette unité de code; si aucun argument n'est passé, $ args contient un tableau vide.

Puisque vous ne pouvez pas passer d'arguments destinés à être vus par un bloc de script passé à Measure-Command Le paramètre -Expression de code>, $ args est par définition le tableau vide à l'intérieur de ce bloc de script, ce qui a provoqué l'échec de Start-Process .

En passant: ce Start-Process échoue avec un tableau vide - au lieu de l'interpréter comme "aucun argument à passer" - est un problème dans Windows PowerShell qui a depuis été corrigé dans PowerShell Core.

Ce PowerShell vous permet d'attribuer un la valeur de $ args est problématique. Malheureusement, cela fait partie d'un problème plus vaste consistant à ne pas empêcher l'utilisation personnalisée des variables automatiques - voir ce problème GitHub .

L'aspect insidieux de ce comportement est que le problème n'apparaît que lorsque vous entrez un script [bloc] ou une fonction; dans la portée de l'appelant , la valeur personnalisée affectée à $ args prend effet, comme le montre l'exemple suivant:

after assignment: [hi]
in script block: []; element count: 0

Ce qui précède donne:

$args = 'hi'  # !! To be avoided. Assign a custom value to $args
# Echo the custom value, in the same scope.
"after assignment: [$args]"         
# Call a script block and echo $args there. 
& { "in script block: [$args]; element count: $($args.Count)" }  

La première ligne de sortie montre que l'affectation dans la portée de l'appelant a fonctionné comme prévu.

La deuxième ligne de sortie montre que $ args a été automatiquement défini sur un tableau vide lors de l'entrée dans le bloc de script, car aucun argument n'a été passé au bloc de script ( {.. .} ).

Note: Techniquement, une variable locale $ args est créée à l'intérieur du bloc de script, et la copie de l'appelant est toujours accessible si vous accédez explicitement à la portée de l'appelant (par exemple via (Get-Variable args -Scope 1 -ValueOnly) ), mais l'approche la plus judicieuse est d'éviter l'utilisation personnalisée de $ args code> complètement.


[1] $ args contient uniquement les arguments qui ne sont pas liés aux paramètres explicitement déclarés , si seulement. Dans le script avancé ou des fonctions , vous ne pouvez jamais passer d'arguments qu'à des paramètres explicitement définis, donc $ args n'est pas défini ici, car son utilisation serait inutile; en fait, dans un script / fonction avancé, $ args conserve la définition personnalisée $ args d'un appelant si elle est exécutée dans le même domaine de portée, mais il ne faut pas s'y fier.


0 commentaires