IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scripts/Batch Discussion :

Exécution silencieuse d'un script avec boite de dialogue


Sujet :

Scripts/Batch

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Octobre 2005
    Messages
    908
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 908
    Par défaut Exécution silencieuse d'un script avec boite de dialogue
    Bonjour à tous,

    J'ai un script qui s'exécute de manière transparente sur tous les postes d'un parc informatique.
    Le script est lancé par un service avec le compte système.
    Dans de rares cas, j'ai besoin d'afficher une boite de dialogue.
    J'ai le script suivant qui fonctionne seulement sur Windows XP !!! pas W7 ni W8.1...

    Code POWERSHELL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $logName="C:\_logs\transcript_"+(Get-Date -format 'yyyyMMdd-HHmmss')+".log"
    Start-Transcript -path $logName -force | Out-Null
    Write-Host
    Write-Host "script version 5"
    [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
    $A = [System.Windows.Forms.MessageBox]::Show(
    	"Le Message",
    	"Le titre", 
    	[System.Windows.Forms.MessageBoxButtons]::OKCancel,
    	[System.Windows.Forms.MessageBoxIcon]::Information,
    	[System.Windows.Forms.MessageBoxDefaultButton]::Button1,
    	[System.Windows.Forms.MessageBoxOptions]::DefaultDesktopOnly)
    	#ServiceNotification
     
    if ($A -eq "OK" ) {
    	Write-Host "L'utilisateur a cliqué sur <OK>"
    } else {
    	Write-Host "L'utilisateur a cliqué sur <Annuler>"
    }
    Write-Host
    Stop-Transcript

    Au début je n'avait pas l'option DefaultDesktopOnly mais cela provoqué l'erreur :
    Exception lors de l'appel de «*Show*» avec «*2*» argument(s)*: «*L'affichage d'une boîte de dialogue modale ou d'un formulaire lorsque l'application ne s'exécute pas en mode UserInteractive n'est pas une opération valide. Spécifiez le style ServiceNotification ou DefaultDesktopOnly pour afficher une notification à partir d'une application de service.*»
    Auriez-vous une idée ?
    Merci d'avance


  2. #2
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par Tchupacabra Voir le message
    Le script est lancé par un service avec le compte système.
    Vérifie le comportement en utilisant la valeur ServiceNotification.

  3. #3
    Membre éclairé
    Inscrit en
    Octobre 2005
    Messages
    908
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 908
    Par défaut
    ça change rien...
    de plus, dans le log, il y a :
    L'utilisateur a cliqué sur <OK>
    alors que rien n'a été cliqué puisque rien ne s'est affiché !


  4. #4
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Billets dans le blog
    1
    Par défaut
    Essaie avec une API WTS.

  5. #5
    Membre éclairé
    Inscrit en
    Octobre 2005
    Messages
    908
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 908
    Par défaut
    Merci pour cette info mais cela me parait trop complexe...

  6. #6
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Tchupacabra Voir le message
    Merci pour cette info mais cela me parait trop complexe...
    Tu es seul juge.
    Je viens de tester avec cet outil, le déclenchement se fait dans le script exécuté par le service, la fenêtre de dialogue s'affiche dans ma session et le résultat sélectionné est bien récupéré dans le script déclencheur.
    L'exemple donné dans le script proposé concerne plusieurs machine, d'où l'usage de PSSession.

    Le xml a associer à l'outil cité :
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <service>
      <id>TestLaurent</id>
      <name>PSLaurent</name>
      <description>This service runs Powershell test.</description>
      <env name="PSLAURENT_HOME" value="%BASE%"/>
      <executable>Powershell</executable>
      <arguments>-noProfile -noExit -Command " &amp;{G:\PS\Service\ScriptInsideService.ps1}"</arguments>
      <logmode>rotate</logmode>
    </service>
    L'installation du service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #.\winsw.exe install
    Get-Service TestLaurent
    Start-Service TestLaurent
    #pour relancer le test
    #Stop-Service TestLaurent;Start-Service TestLaurent
    Le script utilisé, j'ai ajouté du code de vérification de contexte :
    Code Powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
     
    #ScriptInsideService.ps1
    #Démo de Winsw.exe
     
    <# Send-TSMessageBox  
    .SYNOPSIS    
        Send a message or prompt to the interactive user with the ability to get the results. 
       
    .DESCRIPTION    
        Allows the administrator to send a message / prompt to an interactive user.  
       
    .EXAMPLE    
        "Send a message immediately w/o waiting for a responce." 
        Send-TSMessageBox -Title "Email Problem" -Message "We are currently having delays and are working on the issue." 
         
        "Send a message waiting 60 seconds for a reponse of [Yes / No]." 
        $Result = Send-TSMessageBox -Title "System Updated" -Message "System requires a reboot. Would you like to the reboot system now?" ` 
         -ButtonSet 4 -Timeout 60 -WaitResponse $true  
          
    .ButtonSets 
        0 = OK 
        1 = Ok/Cancel 
        2 = Abort/Retry/Ignore 
        3 = Yes/No/Cancel 
        4 = Yes/No 
        5 = Retry/Cancel 
        6 = Cancel/Try Again/Continue     
         
    .Results 
        "" = 0 
        "Ok" = 1 
        "Cancel" = 2   
        "Abort" = 3 
        "Retry" = 4     
        "Ignore" = 5 
        "Yes" = 6 
        "No" = 7 
        "Try Again" = 10 
        "Continue" = 11 
        "Timed out" = 32000 
        "Not set to wait" = 32001  
              
    .NOTES    
        Author: Raymond H Clark
        Twitter: @Rowdybullgaming 
     
    .RESOURCES 
        http://technet.microsoft.com/en-us/query/aa383488  
        http://technet.microsoft.com/en-us/query/aa383842 
        http://pinvoke.net/default.aspx/wtsapi32.WTSSendMessage 
    #>  
     
    Function Send-TSMessageBox 
    { 
      param([string]$Title = "Title", [string]$Message = "Message", [int]$ButtonSet = 0, [int]$Timeout = 0, [bool]$WaitResponse = $false) 
     
      $Signature = @" 
        [DllImport("wtsapi32.dll", SetLastError = true)] 
        public static extern bool WTSSendMessage( 
          IntPtr hServer, 
          [MarshalAs(UnmanagedType.I4)] int SessionId, 
          String pTitle, 
          [MarshalAs(UnmanagedType.U4)] int TitleLength, 
          String pMessage, 
          [MarshalAs(UnmanagedType.U4)] int MessageLength, 
          [MarshalAs(UnmanagedType.U4)] int Style, 
          [MarshalAs(UnmanagedType.U4)] int Timeout, 
          [MarshalAs(UnmanagedType.U4)] out int pResponse, 
          bool bWait); 
         
        [DllImport("kernel32.dll")] 
        public static extern uint WTSGetActiveConsoleSessionId(); 
    "@ 
     
          [int]$TitleLength = $Title.Length; 
          [int]$MessageLength = $Message.Length; 
          [int]$Response = 0; 
     
          $MessageBox = Add-Type -memberDefinition $Signature -name "WTSAPISendMessage" -namespace "WTSAPI" -passThru    
          $SessionId = $MessageBox::WTSGetActiveConsoleSessionId() 
     
          #todo return objet ResultOfWTSSendMessage
          $result=$MessageBox::WTSSendMessage(0, $SessionId, $Title, $TitleLength, $Message, $MessageLength, $ButtonSet, $Timeout, [ref] $Response, $WaitResponse) 
     
          $Response 
    } 
     
    function Test-IsAdministrator
    {
     param() 
      $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
     (New-Object Security.Principal.WindowsPrincipal $currentUser).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
    }
     
    Function Get-ParentProcess {
    #Permet de retrouver le process parent ayant exécuté 
    #la session Powershell exécutant ce script/module
     param($ID)
     $parentID=$ID         
     $Result=@(
       Do {
         $Process=Get-WmiObject Win32_Process -Filter "ProcessID='$parentID'" -property Name,CommandLine,ParentProcessID
          #Permet de retrouver la tâche appelante
          #On peut inclure le nom de la tâche dans la ligne d'appel :
          # ... -Command "$TaskName='MyTask';..."
        #$Logger.DebugFormat("Name :{0}`t cmdLine={1}",@($Process.name,$Process.CommandLine))
         $parentID=$Process.ParentProcessID
         try {
          (get-process -ID $parentID).Name
          $exit=$true
          }
         catch [Microsoft.PowerShell.Commands.ProcessCommandException] {
          $exit=$false       
         }
       } until ($Exit)
     )
     
     $ofs='.'
     [Array]::Reverse($Result)
     "$Result"
    } #Get-ParentProcess
     
    $title = "Test DialogBox inside a service" 
    $message = "Message Yes No Cancel" 
    $Result=Send-TSMessageBox -Title $title -Message $message -ButtonSet 3 -WaitResponse $true -Timeout 60 
     
    $ResultTSMessageBox =@{
      0="" 
      1="Ok" 
      2="Cancel"   
      3="Abort" 
      4="Retry"     
      5="Ignore" 
      6="Yes"
      7="No" 
      10="Try Again" 
      11="Continue" 
      32000="Timed out" 
      32001="Not set to wait"
    }   
    $title = "DialogBox result" 
    $ParentProcess=Get-ParentProcess $pid
     
    $message = @"
     Le process parent = $ParentProcess
     compte administrateur : $(Test-IsAdministrator)
     Resultat précédent = $($ResultTSMessageBox.$result)
    "@ 
    $Result=Send-TSMessageBox -Title $title -Message $message -ButtonSet 1 -WaitResponse $true -Timeout 60
    Il y a juste une correction/reste à faire dans le code de la fonction Send-TSMessageBox, sinon le code d'origine émet deux objets.
    Je pense que ce code fonctionne également dans une tâche planifié, dans ce cas l'appel à Get-ParentProcess renvoi 'services', ici il renvoi le nom de l'exécutable du service 'winsw'.
    Ce test permet de déterminer si on se trouve dans une session PS utilisateur ou dans une service/tâche planifié.

Discussions similaires

  1. Importation avec boite de dialogue
    Par dams95190 dans le forum VBA Access
    Réponses: 16
    Dernier message: 07/09/2007, 11h45
  2. Problème avec boite de dialogue pour fermer JFrame
    Par adn013 dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 04/09/2007, 15h37
  3. Pb avec boite de dialogue
    Par cjacquel dans le forum MFC
    Réponses: 1
    Dernier message: 26/12/2006, 15h15
  4. [VBA-E] Petit souci avec boites de dialogues
    Par SybVicious dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 12/09/2006, 21h18
  5. [MFC] DLL avec boite de dialogue
    Par ricky78 dans le forum MFC
    Réponses: 2
    Dernier message: 17/06/2005, 12h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo