2010-10-22 6 views
4

J'ai écrit un programme avec C#, qui crée un fichier journal et remplit ceci en utilisant log4net. Ce programme démarre powershell-scripts. Les scripts utilisent aussi log4net. Il fonctionne:"Write-Error" (écrire dans Powershell, utilisé en C#) fonctionne MAIS Write-Debug ne fonctionne pas - Pourquoi?

> C#: 
> ps.Runspace.SessionStateProxy.SetVariable("myMethod",(Action<Level,string>)myMethod); 
> ps.AddCommand(System.IO.Path.Combine(pathScripts, testSkripte[i].ToString())); 
> ps.Invoke(); 

> Powershell:      
> $ScriptLog.Invoke([log4net.Core.Level]::Debug, "TestFile_Debug")      
> $ScriptLog.Invoke([log4net.Core.Level]::Warn, "TestFile_Warn") $ScriptLog   
> $ScriptLog.Invoke([log4net.Core.Level]::Error, "TestFile_Error") 

Maintenant, je veux ajouter utiliser la norme Write-Error, Write-Debug, etc. CmdLets dans mon script.
(looks like here - réponse de Hinek).

Powershell: 
    Write-Warning "Write-Warning"  
    AND   
    Write-Error "Write-Error" 
œuvres

, mais les travaux suivants Indifférent Fume:

Write-Debug "Write-Debug"   (I don´t get an item in my logfile) OR  
Write-Debug "Write-Debug" -debug (for this I get an item in my logfile, but ...) 

... je reçois une erreur dans mon fichier journal aussi. L'erreur ressemble à ceci:

[2010-10-22 13:10:58,097] DEBUG : Write-Debug          
[2010-10-22 13:10:58,113] ERROR : Cannot invoke this function because the current 
            host does not implement it 

(je pense avoir tous les espaces de noms.)

Qu'est-ce que le message d'erreur signifie et que puis-je faire à nouveau cela?

grâce

Répondre

1

Maintenant, je l'avais trouvé la réponse moi-même:

C#-Code: 
    using (ps = PowerShell.Create()) 
    { 
     int a = testSkripte.Count; 
     for (int i = 0; i < a; i++) 
     {       
      ps.Runspace.SessionStateProxy.SetVariable("portalpfad", pathExecuteScript); 
      ps.Runspace.SessionStateProxy.SetVariable("ScriptLog", (Action<Level, string>)ScriptLog); 


    //add following row: 
    ps.Runspace.SessionStateProxy.SetVariable("DebugPreference", "Continue"); 



     ps.AddCommand(System.IO.Path.Combine(pathScripts, testSkripte[i].ToString())); 
     ps.Streams.Debug.DataAdded += new EventHandler<DataAddedEventArgs>(Debug_DataAdded); 
     ps.Streams.Warning.DataAdded += new EventHandler<DataAddedEventArgs>(Warning_DataAdded); 
     ps.Streams.Error.DataAdded += new EventHandler<DataAddedEventArgs>(Error_DataAdded); 
     ps.Invoke();       
    } 

et ceci pour write-debug:

Powershell-Code: 

    usings ... 

    #set variable 
    $DebugPreference 

    #Now Write (-Debug) without Error 
        Write-Debug "Write-Debug" 
        Write-Warning "Write-Warning" 
        Write-Error "Ende --> Write-Error" 
+0

Bonne trouvaille. Pourtant, il semble que votre application n'est pas si triviale. Une approche hôte personnalisée est évolutive et donc plus attrayante pour des solutions non triviales. Imaginez: demain, votre script de travail veut appeler 'Write-Progress',' Read-Host', et ainsi de suite. Avoir un hôte personnalisé vous permettra d'ajouter des fonctionnalités encore manqué relativement facile. –

4

Le message « l'hôte actuel n'implémente pas » indique que vous devez fournir un hôte qui implémente des fonctionnalités manquées. Vraisemblablement, vous devez mettre en œuvre votre propre PSHost et PSHostUserInterface, au moins ce dont vous avez vraiment besoin là. Dans cette dernière classe, vous implémentez des méthodes telles que WriteDebugLine et WriteErrorLine. Ensuite, les cmdlets Write-Warning et Write-Debug déclenchent ces méthodes en interne.

exemple complet d'un hôte avec l'interface utilisateur et les méthodes: http://msdn.microsoft.com/en-us/library/ee706577(v=VS.85).aspx (Peut-être que vous n'avez pas besoin la plupart des autres méthodes, fournissent des mannequins alors)

+1

Ok. Maintenant, j'ai testé votre suggestion. Je veux dire que c'est très détourné, parce que j'ai besoin de trois classes, qui ont beaucoup de méthodes dont je n'ai pas besoin. N'y a-t-il pas un moyen plus court (Je pensais aux paramètres ou à tout, parce que les messages d'erreur et les avertissements fonctionnent.) Avez-vous une autre idée aussi? Merci – Rotaney

+2

@ Roman a définitivement raison, et il n'y a pas de raccourcis L'API d'hébergement PowerShell est TRÈS compliquée.Ce que vous voudrez faire est juste de fournir des méthodes factices (lancer une nouvelle NotImplementedException) pour tout ce dont vous n'avez pas besoin. – Jaykul

+0

@Rotaney: vous avez besoin de 2 classes (hôte et interface utilisateur). La "3ème classe" est votre application, vous l'avez quand même. –

3

Voici une solution de contournement: remplacer la commande par défaut Write-Debug (qui est en réalité pas mis en œuvre) avec une fonction:

function global:Write-Debug 
(
    [string] 
    $Message, 
    [switch] 
    $Debug 
) 
{ 
    # check both the $Debug switch and the $DebugPreference variable: 
    if ($Debug -or ($DebugPreference -ne 'SilentlyContinue')) { 
     # do job; in this demo just write to the console: 
     [Console]::WriteLine("DEBUG: $Message") 
    } 
} 

en C# mettre ce code dans une chaîne et invoquez une fois dans la même instance d'exécution où le script principal sera invoqué. Ce code "profile" installe la fonction globale Write-Debug qui est sémantiquement la même que la cmdlet d'origine. Ensuite, lorsque le code principal appelle Write-Debug cette fonction est appelée, pas la cmdlet par défaut.

P.S. Je n'ai pas essayé de cette façon, je préfère utiliser mon propre hôte (voir mon autre réponse). Mais cette façon devrait fonctionner correctement dans de nombreux cas (pas tous, peut-être).

Questions connexes