J'écris un script PowerShell qui exécute l'une des étapes de mon processus de construction / de déploiement et qu'il doit exécuter certaines actions sur une machine distante. Le script est relativement complexe, donc si une erreur se produit pendant cette activité à distance, je souhaite une trace de pile détaillée de l'endroit où le script est survenu (au-dessus et au-dessus de la journalisation déjà produite).
Le problème se pose dans celui invoqué -Command perd des informations de trace de pile lors de la relayation des exceptions de terminaison d'une machine distante. Si un bloc de script est invoqué sur la machine locale: p>
Test Error
At line:4 char:3
+ throw "Test Error";
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Test Error:String) [], RuntimeException
+ FullyQualifiedErrorId : Test Error
3 Réponses :
Je suis sûr que quelqu'un avec plus d'expérience peut aider, mais j'aimerais vous donner quelque chose à mâcher pendant la période moyenne. On dirait que vous voulez utiliser Capturer l'exception dans une variable est un bon départ pour cela, je vais donc recommander ce bloc de votre exemple: p> Vous pouvez également lancer un objet errorrecord ou une exception de framework Microsoft .NET. P>
BlockQuote> Mais dans ce cas, cela ne fonctionne pas qui est probablement dû à la désérialisation. À un moment donné, j'ai essayé de créer mon propre objet d'erreur, mais certaines des propriétés nécessaires étaient en lecture seule, alors j'ai sauté cela. p> Cependant, il suffit d'écrire sur le flux de sortie vous donne les informations correctes que vous l'avez vues. P> lancer code> puisque vous recherchez des exceptions de terminaison. Erreur d'écriture Code> Ecrivez-vous sur le flux d'erreur, mais il ne se termine pas. Quel que soit votre choix, ma suggestion est toujours la même. $ exception code> Ce cas devrait être un désériialized.system.management.Automation.errorrecord code>. Vous pouvez envoyer des objets personnalisés à lancer code> . .. P>
PS M:\Scripts> $exception.InvocationInfo.PositionMessage
At line:4 char:9
+ throw "Test Error";
+ ~~~~~~~~~~~~~~~~~~
Merci d'avoir fait plus de creuser sur ceci - on dirait que je devrai utiliser cette approche (messages d'exception empilés) combinés aux informations sérialisées de la réponse de Frode F. pour créer une entrée de journal informative.
Lorsque vous exécutez du code et que vous échouez, vous recevez un Lorsque vous utilisez Lorsque l'exception est lancée à l'origine sur l'ordinateur distant, errorrecord code> qui reflète le code lancer "erreur" code>, vous pouvez accéder à l'involocationInfo et à une exception pour ce code. invoke-commande code>, vous n'exécutez pas Lancer "Erreur" Code> plus, l'ordinateur distant est. Vous (ordinateur local) exécute invoke-commande .... code>, c'est pourquoi le errorrecord code> que vous obtenez reflète que (et pas la réelle exception comme vous le voulait). Ceci est la façon dont il doit être depuis une exception peut provenir de la scriptBlock le compteur distant exécuté, mais il pourrait aussi bien être une exception à partir de invoke-commande code> car il ne pouvait pas se connecter à L'ordinateur distant ou quelque chose de similaire. p> invoke-commande code> / powerShell jette un RemoteException sur l'ordinateur local. P> $localexception.Exception.GetType().FullName
System.Management.Automation.ItemNotFoundException
$remoteexception.Exception.SerializedRemoteException.GetType().FullName
System.Management.Automation.PSObject
#Get TypeName from psobject
$remoteexception.Exception.SerializedRemoteException.psobject.TypeNames[0]
Deserialized.System.Management.Automation.ItemNotFoundException
Super - cela me donne toutes les informations de l'exception dont j'ai besoin. Merci!
@Frodef. Réponse fantastique. Je peux obtenir la positionMessage, mais je ne peux pas sembler obtenir une stacktrace ou une script de script de l'exception sérialisée. Des idées?
La script ScripttackTrace fait partie de l'errorrecord, pas de l'exception. $ RemoteException.ScriptStackTrace code> fonctionne bien pour moi. En ce qui concerne l'exception StackTrace, je reçois la même sortie dans $ RemoteeException.Exception.serialiséRemoteException.innerex cetion.Stacktrace code> comme je le fais à partir de $ localException.Exception.innerException.StackTrace code> . L'exception externe StackTrace ne correspond pas à mon test, mais c'est simplement parce que invoke-commande code> requis -erroraction stop code> pour générer l'exception en tant que terminaison.
En espérant que quelqu'un avec plus d'expérience puisse commenter à ce sujet, mon commentaire semble être parti oublié.
J'ai trouvé cet article qui offre un aperçu de l'utilisation de ou même mieux, créez une session persistante p> pour déboguer à l'aide de la traçage, rappelez-vous que vous devez définir le verbosePreference, la transreurure, etc. dans la session distante P> Entrée-psession code> p> Invoke-Command $session {$VerbosePreference = âcontinueâ}
Invoke-Command $session {Write-Verbose hi}
Il souhaite accéder à l'exception qui est jetée à l'intérieur du scriptblock utilisé dans invoke-commande code>. L'utilisation d'une session vs. ComputerName avec la même cmdlet ne modifie pas la manière dont les exceptions sont transmises à «l'ordinateur de gestion».
Comme cela se produit, le script actuel que j'utilise utilise des sessions créées avec une nouvelle psession, mais comme cette partie est horriblement compliquée (beaucoup de déconnexion et de reconnecte de processus) et ne semble pas avoir une incidence sur la manipulation des exceptions dans ce cas, je omis de l'exemple du code. Merci quand même!
Utilisez quelque chose comme
Invoke-Command -errorvariable RougeError CODE> Les résultats du flux d'erreur doivent être dans$ RemoteRror CODE>?Je le reprends
-errorvariable code> ne doit pas contenir les informations dont vous avez besoin. Je pense avoir une idée pensée en utilisantlancer code>Est quelque chose sur Cet article utile? "Pour le débogage, au lieu de la commande invoke, il peut être préférable d'utiliser Enter-psession, de sorte que vous puissiez avoir une coquille sur la machine distante pour essayer les choses"
Vous ne pouvez pas utiliser
Entrée-psession code> dans les scripts