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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
Public Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
'** Type pour gérer les lancement de process
Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
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 Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
'** Info sur process
Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadID As Long
End Type
'** Type pour E/S avec recouvrement
Public Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type
Public Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Public Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Public Const SUBLANG_DEFAULT = &H1 ' user default
Public Const LANG_NEUTRAL = &H0
Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const FILE_SHARE_DELETE = &H4
Public Const FILE_ATTRIBUTE_NORMAL = &H80
Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
Public Const INVALID_HANDLE_VALUE = -1
Public Const STARTF_USESTDHANDLES = &H100
Public Const CREATE_NO_WINDOW = &H8000000
Public Const CREATE_ALWAYS = 2
Public Const STILL_ACTIVE = &H103&
Public Const FILE_FLAG_DELETE_ON_CLOSE = &H4000000
Function GetSystemErrorMsg(num As Long) As String
'** Renvoie message d'erreur
Dim sMsg As String * 128
Dim i As Integer
If FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, 0&, num&, (SUBLANG_DEFAULT * (2 ^ 10)) Or LANG_NEUTRAL, sMsg, 128&, 0&) = 0 Then
Debug.Print Err.LastDllError
End If
i = InStr(sMsg, Chr(13))
If i > 0 Then
GetSystemErrorMsg = Left(sMsg, i - 1)
Else
GetSystemErrorMsg = sMsg
End If
End Function
sub commandeDOS(sCommande as String, sSortieCommande as String)
Dim Ret As Long
Dim hOut As Long: hOut = INVALID_HANDLE_VALUE
Dim bytesreaded As Long
Dim exitCode As Long: exitCode = -1
Dim buffer(0 To 127) As Byte
Dim sCommand As String
Dim strOut As String
Dim ov As OVERLAPPED
Dim secattr As SECURITY_ATTRIBUTES
Dim proc As PROCESS_INFORMATION: proc.hProcess = INVALID_HANDLE_VALUE: proc.hThread = INVALID_HANDLE_VALUE
Dim start As STARTUPINFO: start.hStdOutput = INVALID_HANDLE_VALUE: start.hStdError = INVALID_HANDLE_VALUE
on error goto errotag
'** Security attributes pour le fichier de sortie de la commande
secattr.bInheritHandle = 1
secattr.nLength = Len(secattr)
secattr.lpSecurityDescriptor = 0
'** Creation du fichier de sorite de la commande
hOut = CreateFile("outfile.txt", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, secattr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
If hOut = INVALID_HANDLE_VALUE Then
Err.Raise Err.LastDllError, "commandeDOS", GetSystemErrorMsg(Err.LastDllError)
End If
'** StartupInfo pour le processus qui lancera la commande
start.cb = Len(start)
start.hStdOutput = hOut
start.hStdError = hOut
start.dwFlags = STARTF_USESTDHANDLES
'** Lancement la commande
Ret& = CreateProcess(0&, sCommande, 0&, 0&, 1&, CREATE_NO_WINDOW, 0&, 0&, start, proc)
If Ret = 0 Then
Err.Raise Err.LastDllError, "commandeDOS", GetSystemErrorMsg(Err.LastDllError)
End If
'** Attendre la fin de la commande
Ret = GetExitCodeProcess(proc.hProcess, exitCode)
Do While Ret <> 0 And exitCode = STILL_ACTIVE
Ret = GetExitCodeProcess(proc.hProcess, exitCode)
DoEvents
Sleep 100
'Penser à gerer un timeout ici
Loop
If Err.LastDllError <> 0 Then
Err.Raise Err.LastDllError, "commandeDOS", GetSystemErrorMsg(Err.LastDllError)
End If
'** Recupération de la sortie de la commande
Ret = ReadFile(hOut, buffer(0), 128, bytesreaded, ov)
Do While Ret <> 0
'** Test de finc de fichier
If bytesreaded = 0 Then
Exit Do
End If
'** Transformation des bytes en charactères
For i = 0 To bytesreaded - 1
sSortieCommande = sSortieCommande & Chr(buffer(i))
buffer(i) = 0
Next
'** Lecture suivante
ov.offset = ov.offset + bytesreaded
Ret = ReadFile(hOut, buffer(0), 128, bytesreaded, ov)
Loop
If Err.LastDllError <> 0 And Err.LastDllError <> 38 Then
Err.Raise Err.LastDllError, "commandeDOS", GetSystemErrorMsg(Err.LastDllError)
End If
'** Fermeture handles
CloseHandle hOut
CloseHandle proc.hProcess
CloseHandle proc.hThread
Exit Sub
errotag:
If hOut <> INVALID_HANDLE_VALUE Then CloseHandle hOut
If proc.hProcess <> INVALID_HANDLE_VALUE Then CloseHandle proc.hProcess
If proc.hThread <> INVALID_HANDLE_VALUE Then CloseHandle proc.hThread
Err.Raise Err.number, Err.source, Err.Description, Err.HelpFile, Err.HelpContext
end sub
sub test()
dim sortie as string
on error GoTo testerror
CommandeDos("ping -a 127.0.0.1",sortie)
debug.print sortie
exit sub
testerror:
Msgbox err.number & " - " & err.Description
end sub |
Partager