Problème pour lancer une commande DOS

cs_groslou2 Messages postés 3 Date d'inscription vendredi 22 décembre 2000 Statut Membre Dernière intervention 16 mars 2011 - 16 mars 2011 à 13:53
cs_groslou2 Messages postés 3 Date d'inscription vendredi 22 décembre 2000 Statut Membre Dernière intervention 16 mars 2011 - 16 mars 2011 à 19:48
Bonjour,

J'utilise le code suivant pour lancer une commande DOS depuis Excel en VBA:

Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As SECURITY_ATTRIBUTES, ByVal nSize As Long) As Long
Private Declare Sub GetStartupInfo Lib "kernel32" Alias "GetStartupInfoA" (lpStartupInfo As STARTUPINFO)
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
 
Private Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Long
End Type
 
Private Type PROCESS_INFORMATION
  hProcess As Long
  hThread As Long
  dwProcessId As Long
  dwThreadId As Long
End Type
 
Private Type STARTUPINFO
  cb As Long
  lpReserved As Long
  lpDesktop As Long
  lpTitle As Long
  dwX As Long
  dwY As Long
  dwXSize As Long
  dwYSize As Long
  dwXCountChars As Long
  dwYCountChars As Long
  dwFillAttribute As Long
  dwFlags As Long
  wShowWindow As Integer
  cbReserved2 As Integer
  lpReserved2 As Byte
  hStdInput As Long
  hStdOutput As Long
  hStdError As Long
End Type
 
Private Type OVERLAPPED
    ternal As Long
    ternalHigh As Long
    offset As Long
    OffsetHigh As Long
    hEvent As Long
End Type
 
Private Const STARTF_USESHOWWINDOW = &H1
Private Const STARTF_USESTDHANDLES = &H100
Private Const EM_SETSEL = &HB1
Private Const EM_REPLACESEL = &HC2
Private Const SW_HIDE As Long = 0
Private Const SW_SHOW As Long = 5
 
 
Sub Redirect(cmdLine As String)
  Dim i%, t$
  Dim pa As SECURITY_ATTRIBUTES
  Dim pra As SECURITY_ATTRIBUTES
  Dim tra As SECURITY_ATTRIBUTES
  Dim pi As PROCESS_INFORMATION
  Dim sui As STARTUPINFO
  Dim hRead As Long
  Dim hWrite As Long
  Dim bRead As Long
  Dim lpBuffer(1024) As Byte
  pa.nLength = Len(pa)
  pa.lpSecurityDescriptor = 0
  pa.bInheritHandle = True
  
  pra.nLength = Len(pra)
  tra.nLength = Len(tra)
 
  If CreatePipe(hRead, hWrite, pa, 0) <> 0 Then
    sui.cb = Len(sui)
    GetStartupInfo sui
    sui.hStdOutput = hWrite
    sui.hStdError = hWrite
    sui.dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES
    sui.wShowWindow = SW_HIDE
    If CreateProcess(vbNullString, cmdLine, pra, tra, True, 0, Null, vbNullString, sui, pi) <> 0 Then
      Do
        Erase lpBuffer()
        If ReadFile(hRead, lpBuffer(0), 1023, bRead, ByVal 0&) Then
          MsgBox ByteToString(lpBuffer)
          DoEvents
        Else
          CloseHandle pi.hThread
          CloseHandle pi.hProcess
          Exit Do
        End If
        CloseHandle hWrite
      Loop
      CloseHandle hRead
    End If
  End If
End Sub
 
 
Public Function ByteToString(ByRef bInput() As Byte) As String
    Dim i As Long
    
    ByteToString = ""
    i = 0
    
    Do While i < UBound(bInput) + 1
        ByteToString = ByteToString + Chr$(bInput(i))
        i = i + 1
    Loop
 
End Function


Pour lancer ma commande, je fais par exemple Call Redirect("ping"). Je récupère pour le moment le résultat de ma requête via un MsgBox. La commande marche bien, sauf que pour une raison que j'ignore, certaines commandes ne se comportent pas de la même manière que sous l'invite de commande DOS (cmd.exe). En particulier, je souhaite passer des commandes à un serveur distant via l'exécutable plink.exe (en le lançant en tant que commande DOS), tout se passe bien, alors que via la macro, il me renvoie une erreur: "Unknown network error".
Est-ce que quelqu'un saurait me dire comment modifier mon code pour avoir le même résultat qu'avec la commande DOS?
Merci d'avance pour votre aide.

2 réponses

cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
16 mars 2011 à 19:37
Salut

Quelle est la forme de la commande avec paramètres que tu tentes de passer ?
Méfie-toi des paramètres comportant des espaces : DOS considèrera qu'il y a n paramètres --> Utilisation des " pour encadrer de tels paramètres.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
cs_groslou2 Messages postés 3 Date d'inscription vendredi 22 décembre 2000 Statut Membre Dernière intervention 16 mars 2011 1
16 mars 2011 à 19:48
En fait j'utilise Call Redirect("plink.exe -l login -pw password serveur commande"). Si je mets ça, j'obtiens un network error. Si je mets Call Redirect("plink.exe"), j'obtiens la liste des options de plink.exe et si je tape "plink.exe -l login -pw password serveur ls" sous l'invite de commande DOS, j'ai bien le résultat du ls sous mon serveur. En fait j'ai un peu le même problème avec ping: il marche si je mets le nom de mon serveur ou son IP sous DOS. En revanche, ça ne marche qu'avec l'IP sous ma commande. Si je mets le petit nom de mon serveur, il me met un "host error".
0
Rejoignez-nous