Partage
  • Partager sur Facebook
  • Partager sur Twitter

Execution powershell en VB.net

Sujet résolu
    2 août 2019 à 10:51:50

    Salut,

    J'essaye d’exécuter un script powershell à partir de mon programme .net.

    J'y arrive plus ou moins ça mais mon projet étant un windows forms donc sans console, lorsque j'ai un argument dans mon script ou une interaction avec l'utilisateur mon programme plante.

    Est-ce que quelqu'un sait comment faire passer un argument au script ou autoriser l'interaction avec l'utilisateur ?

    Je vous met le code ici. C'est un copié collé de la doc microsoft que j'essaye d'implémenter dans une application qui va entre autre exécuter des scripts powershell

    Imports System.Collections.ObjectModel
    Imports System.Management.Automation
    Imports System.Management.Automation.Runspaces
    Imports System.Text
    Imports System.IO
    
    Public Class Form1
        ' Takes script text as input and runs it, then converts
        ' the results to a string to return to the user
        Private Function RunScript(ByVal scriptText As String) As String
    
            ' create Powershell runspace
            Dim MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
    
            ' open it
            MyRunSpace.Open()
    
            ' create a pipeline and feed it the script text
            Dim MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
    
            MyPipeline.Commands.AddScript(scriptText)
    
            ' add an extra command to transform the script output objects into nicely formatted strings
            ' remove this line to get the actual objects that the script returns. For example, the script
            ' "Get-Process" returns a collection of System.Diagnostics.Process instances.
            MyPipeline.Commands.Add("Out-String")
    
            ' execute the script
            Dim results As Collection(Of PSObject) = MyPipeline.Invoke()
    
            ' close the runspace
            MyRunSpace.Close()
    
            ' convert the script result into a single string
            Dim MyStringBuilder As New StringBuilder()
    
            For Each obj As PSObject In results
                MyStringBuilder.AppendLine(obj.ToString())
            Next
    
            ' return the results of the script that has
            ' now been converted to text
            Return MyStringBuilder.ToString()
    
        End Function
    
        ' helper method that takes your script path, loads up the script
        ' into a variable, and passes the variable to the RunScript method
        ' that will then execute the contents
        Private Function LoadScript(ByVal filename As String) As String
    
            Try
    
                ' Create an instance of StreamReader to read from our file.
                ' The using statement also closes the StreamReader.
                Dim sr As New StreamReader(filename)
    
                ' use a string builder to get all our lines from the file
                Dim fileContents As New StringBuilder()
    
                ' string to hold the current line
                Dim curLine As String = ""
    
                ' loop through our file and read each line into our
                ' stringbuilder as we go along
                Do
                    ' read each line and MAKE SURE YOU ADD BACK THE
                    ' LINEFEED THAT IT THE ReadLine() METHOD STRIPS OFF
                    curLine = sr.ReadLine()
                    fileContents.Append(curLine + vbCrLf)
                Loop Until curLine Is Nothing
    
                ' close our reader now that we are done
                sr.Close()
    
                ' call RunScript and pass in our file contents
                ' converted to a string
                Return fileContents.ToString()
    
            Catch e As Exception
                ' Let the user know what went wrong.
                Dim errorText As String = "The file could not be read:"
                errorText += e.Message + "\n"
                Return errorText
            End Try
    
        End Function
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            'run our script and put the result into our textbox
            'NOTE: make sure to change the path to the correct location of your script
            TextBox1.Text = RunScript(LoadScript("C:\Users\240479\Documents\temp\SC_test.ps1"))
        End Sub
    End Class

    et le script powershell

    Param(
    [parameter(mandatory=$true)][string]$temp
    )
    
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"
    write "jambon"
    write "pantoufle"

    et un screenshot de l'appli de test pour visualiser



    Merci à ceux qui prendront la peine de m'aider

    -
    Edité par DarkJambon 2 août 2019 à 10:54:15

    • Partager sur Facebook
    • Partager sur Twitter
      29 août 2019 à 16:48:56

      Messages d'erreur, SVP.
      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        2 septembre 2019 à 9:36:56

        Il n'y a pas de message d'erreur, juste exception non géré

        Depuis j'ai quand même finit par trouver une solution mais je pense qu'il y a mieux

        la fonction runscript prend une string qui contient tout le script et l'exécute

        Donc j'ai rajouté des balises dans mon scripts et j'ai fait une fonction qui rajoute des variables dans cette string

        Par exemple

        #variables
        
        $jambon
        
        $pantoufle
        
        #script
        
        write $jambon
        
        write $pantoufle

        devient

        #variables
        
        $jambon = "Bonjour"
        
        $pantoufle = "Hello"
        
        #script
        
        write $jambon
        
        write $pantoufle

        Mais cela ne règle pas tout.

        Il y a des interaction que j'aurai bien aimé faire et qui là crash comme get-credential

        -
        Edité par DarkJambon 2 septembre 2019 à 9:37:32

        • Partager sur Facebook
        • Partager sur Twitter
          2 septembre 2019 à 10:31:57

          >Il n'y a pas de message d'erreur, juste exception non géré

          Il y a toujours un message dans l'exception, et même une stacktrace.

          Prenez la peine de lire ces informations dans le débogueur.

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            2 septembre 2019 à 11:12:42

            Import-Module ActiveDirectory
            
            #variables
            $Path=C:\Users\240479\Documents\temp\logs.txt
            #script
            get-credential

            c'est mon script une fois que la transformation pour les variables est faite.

            Le message d'erreur est :

            System.Management.Automation.ParameterBindingException : 'Impossible de traiter la commande, car un ou plusieurs paramètres obligatoires sont absents :  Credential.'

            Je ne pense quand même pas que ça vienne du script puisque si je copie colle dans Powershell ISE je peux l'exécuter sans problème

            • Partager sur Facebook
            • Partager sur Twitter
              2 septembre 2019 à 11:51:53

              >Je ne pense quand même pas que ça vienne du script

              Vous avez raison, car le débogueur vous indique que le problème n'est pas là mais dans la Propriété "Credential" de votre objet.

              https://stackoverflow.com/questions/17067260/invoke-powershell-command-from-c-sharp-with-different-credential

              Le débogueur est votre ami.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                2 septembre 2019 à 12:09:26

                Peut-être que j'ai pas tout compris mais j'ai l'impression que d'après ton lien la solution pour get-credential c'est de passer par VB et pas par powershell

                ça résous un cas mais la question c'était plus comment gérer les interactions avec utilisateurs en général

                Le get-credential était juste un exemple. Le problème reste le même pour readhost par exemple que j'ai remplacé par des inputbox pour l'instant

                Est-ce qu'il n'y aurai pas moyen de mettre en place quelque chose pour pouvoir exécuter get-credential ou readhost depuis le script ou je dois absolument passer par le vb ?

                • Partager sur Facebook
                • Partager sur Twitter
                  3 septembre 2019 à 9:48:55

                  Ok, j'avais pas fait attention au contenu du script.

                  Je pensais que le l'exception était forcément liée au "shell" du script et pas au script lui-même.

                  Vérifiez avec le débogueur si cela vient du "shell" ou du script via la callstack/stacktrace de l'exception.

                  Les contextes de sécurité de ce transmettent pas forcement et pas complètement entre Thread/AppDomain/Processus pour des problématique de sécurité.

                  Il faut bien faire attention à comment ce contexte de sécurité initial est passé/cloné à l'"autre partie".

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                    3 septembre 2019 à 10:21:28

                    J'ai peut-être encore rien compris mais il me semble que si l'erreur venait du script, il ne crasherait pas en l'exécutant via powershell ISE ?

                    Sinon j'ai fait un copié collé des détails de ce que me donne le débogueur si tu y comprend quelque chose parce que je n'ai absolument pas compris ce qu'était le callstack/stacktrace thread etc..

                    Je précise que je suis un vrai débutant c'est ma première application

                    System.Management.Automation.ParameterBindingException
                      HResult=0x80131501
                      Message=Impossible de traiter la commande, car un ou plusieurs paramètres obligatoires sont absents :  Credential.
                      Source=System.Management.Automation
                      Arborescence des appels de procédure :
                       à System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
                       à System.Management.Automation.Runspaces.Pipeline.Invoke()
                       à Stage.GB_files.RunScript(String scriptText) dans C:\Users\240479\source\repos\Stage\Form1.vb :ligne 15
                       à Stage.GB_files.BT_exec_Click(Object sender, EventArgs e) dans C:\Users\240479\source\repos\Stage\Form1.vb :ligne 88
                       à System.Windows.Forms.Control.OnClick(EventArgs e)
                       à System.Windows.Forms.Button.OnClick(EventArgs e)
                       à System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
                       à System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
                       à System.Windows.Forms.Control.WndProc(Message& m)
                       à System.Windows.Forms.ButtonBase.WndProc(Message& m)
                       à System.Windows.Forms.Button.WndProc(Message& m)
                       à System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
                       à System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
                       à System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
                       à System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
                       à System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
                       à System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
                       à System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
                       à Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
                       à Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
                       à Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
                       à Stage.My.MyApplication.Main(String[] Args) dans  :ligne 81

                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 septembre 2019 à 10:45:39

                      >il ne crasherait pas en l'exécutant via powershell ISE ?

                      Non, si c'est lié au contexte de sécurité, il est différent dans un PowerShell ISE et dans une application "lambda".

                      Donc, le comportement sera différent, même avec le même code.

                      Il existe d'autres choses que le contexte de sécurité qui peut varier mais le contexte de sécurité est clairement le plus impactant.

                      >Je précise que je suis un vrai débutant c'est ma première application

                      Vous n'avez clairement pas choisi la facilité.

                      Si vous n'êtes pas obligé de faire des scripts, qui ne se justifient que pour la possibilité d'être modifier par l'utilisateur final (ou pour des scenarii très évolué de customisation), je vous conseillerais de tout faire dans votre application sans passer par des scripts.

                      La pile, ça se lit de bas en haut, le plus souvent.

                      Ligne 88 de votre Form1.vb, vous appelez "RunScript"

                      Ligne 15 de votre Form1.vb, vous appelez, directement ou indirectement, la méthode "Invoke" d'un objet "System.Management.Automation.Runspaces.Pipeline" qui doit être votre variable "MyRunSpace".

                      Le message d'erreur indique qu'il manque un paramètre "Credential", vraisemblablement récupéré dans ce champ

                      https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspaceconnectioninfo.credential?view=pscore-6.2.0

                      Les codes fournis par les articles déjà données en lien font ce travail d'initialisation avec des "Credential" spécifiques.

                      Faites de même mais en utilisant le "Credental" de votre contexte de sécurité, à partir de :

                      https://docs.microsoft.com/fr-fr/dotnet/api/system.security.principal.windowsidentity.getcurrent?view=netframework-4.8

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                      Execution powershell en VB.net

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown