Redirection de STDIN/OUT/ERR pour CreateProcess - problème d'affichage
Publié : mar. 07/févr./2023 12:05
Bonjour tout le monde,
J'ai trouvé un (vieux) code sur le forum allemand qui redirige les STDOutput/In/Err pour une utilisation de CreateProcess.
Malheureusement, comme souvent avec des appels à "cmd", j'ai des problèmes d'affichage avec certains caractères.
J'ai besoin d'utiliser CreateProcessAsUser donc pas de possibilité de substituer avec un RunProgram().
Une idée ?
Merci par avance.
J'ai trouvé un (vieux) code sur le forum allemand qui redirige les STDOutput/In/Err pour une utilisation de CreateProcess.
Malheureusement, comme souvent avec des appels à "cmd", j'ai des problèmes d'affichage avec certains caractères.
J'ai besoin d'utiliser CreateProcessAsUser donc pas de possibilité de substituer avec un RunProgram().
Une idée ?
Merci par avance.
Code : Tout sélectionner
; German forum: http://www.purebasic.fr/german/viewtopic.php?t=2893&highlight=
; Author: Unknown (posted by MXVA)
; Date: 09. April 2005
; OS: Windows
; Demo: No
; Redirecting the (static) console output to a stringgadget
#D_ReadBufferSize = 2048
Structure D_ProgramInfo
StartUpInfo.STARTUPINFO
ProcessInfo.PROCESS_INFORMATION
SECURITYATTRIBUTES.SECURITY_ATTRIBUTES
hOutputPipeRead.i
hOutputPipeWrite.i
hInputPipeRead.i
hInputPipeWrite.i
hReadThread.i
ReadThreadStat.i
ReadBuffer.i
ReadDataLen.i
EndStructure
; Procedure.s _OEMToAnsi(sOEM.s)
; Protected iByteLength = Len(sOEM) + 2
; Protected sOem_in_Ascii.s = Space(iByteLength)
; PokeS(@sOem_in_Ascii, sOEM, -1, #PB_Ascii)
; Protected sUnicode.s = Space(iByteLength)
; OemToChar_(@sOem_in_Ascii, @sUnicode)
;
; ProcedureReturn sUnicode
; EndProcedure
Procedure D_ReadConsoleOutputThread(*ProgramInfo.D_ProgramInfo)
*ProgramInfo\ReadBuffer = AllocateMemory(#D_ReadBufferSize)
*ProgramInfo\ReadThreadStat = 1
Repeat
If *ProgramInfo\ReadThreadStat = 1
If ReadFile_(*ProgramInfo\hOutputPipeRead, *ProgramInfo\ReadBuffer, #D_ReadBufferSize, @*ProgramInfo\ReadDataLen, 0)
*ProgramInfo\ReadThreadStat = 2
EndIf
EndIf
Delay(1)
Until *ProgramInfo\ReadThreadStat = 0
FreeMemory(*ProgramInfo\ReadBuffer)
*ProgramInfo\hReadThread = #Null
EndProcedure
Procedure D_RunProgram(EXEFileName.s, Parameter.s, *ProgramInfo.D_ProgramInfo)
Protected result
Protected command.s
result = #False
*ProgramInfo\SECURITYATTRIBUTES\nLength = SizeOf(SECURITY_ATTRIBUTES)
*ProgramInfo\SECURITYATTRIBUTES\bInheritHandle = 1
*ProgramInfo\SECURITYATTRIBUTES\lpSecurityDescriptor = 0
If CreatePipe_(@*ProgramInfo\hOutputPipeRead, @*ProgramInfo\hOutputPipeWrite, @*ProgramInfo\SECURITYATTRIBUTES, 0) And
CreatePipe_(@*ProgramInfo\hInputPipeRead, @*ProgramInfo\hInputPipeWrite, @*ProgramInfo\SECURITYATTRIBUTES, 0)
*ProgramInfo\StartUpInfo\cb = SizeOf(STARTUPINFO)
*ProgramInfo\StartUpInfo\lpDesktop = @"WinSta0\Default"
*ProgramInfo\StartUpInfo\dwFlags = #STARTF_USESTDHANDLES | #STARTF_USESHOWWINDOW
*ProgramInfo\StartUpInfo\hStdOutput = *ProgramInfo\hOutputPipeWrite
*ProgramInfo\StartUpInfo\hStdError = *ProgramInfo\hOutputPipeWrite
*ProgramInfo\StartUpInfo\hStdInput = *ProgramInfo\hInputPipeRead
If Parameter <> ""
command = Chr(34) + EXEFileName + Chr(34) + " " + Parameter
Else
command = Chr(34) + EXEFileName + Chr(34)
EndIf
If CreateProcess_(#Null, command, @*ProgramInfo\SECURITYATTRIBUTES, @*ProgramInfo\SECURITYATTRIBUTES, 1, #NORMAL_PRIORITY_CLASS, #Null, #Null, @*ProgramInfo\StartUpInfo, @*ProgramInfo\ProcessInfo)
*ProgramInfo\hReadThread = CreateThread(@D_ReadConsoleOutputThread(), *ProgramInfo)
If *ProgramInfo\hReadThread
Delay(10)
result = #True
EndIf
EndIf
CloseHandle_(*ProgramInfo\hOutputPipeWrite)
CloseHandle_(*ProgramInfo\hInputPipeRead)
EndIf
ProcedureReturn result
EndProcedure
Procedure D_CloseProgram(*ProgramInfo.D_ProgramInfo)
*ProgramInfo\ReadThreadStat = 0
CloseHandle_(*ProgramInfo\ProcessInfo\hThread)
CloseHandle_(*ProgramInfo\hOutputPipeRead)
CloseHandle_(*ProgramInfo\hInputPipeWrite)
TerminateProcess_(*ProgramInfo\ProcessInfo\hProcess, 0)
CloseHandle_(*ProgramInfo\ProcessInfo\hProcess)
If *ProgramInfo\hReadThread
KillThread(*ProgramInfo\hReadThread)
EndIf
EndProcedure
Procedure D_GetOutput(*ProgramInfo.D_ProgramInfo, Buffer)
Delay(5)
If *ProgramInfo\ReadThreadStat = 2
OemToCharBuff_(*ProgramInfo\ReadBuffer, Buffer, *ProgramInfo\ReadDataLen)
*ProgramInfo\ReadThreadStat = 1
ProcedureReturn *ProgramInfo\ReadDataLen
EndIf
ProcedureReturn #False
EndProcedure
Procedure D_SendInputString(*ProgramInfo.D_ProgramInfo,string.s)
Protected tmp
CharToOemBuff_(string,string,Len(string))
If WriteFile_(*ProgramInfo\hInputPipeWrite,string,Len(string),@tmp,0)
ProcedureReturn tmp
EndIf
ProcedureReturn #False
EndProcedure
;__________________________________________________________________________________________________
#Gadget_String = 0
OpenWindow(0,0,0,400,200,"Console", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StringGadget(#Gadget_String,0,0,400,200,"", #ES_MULTILINE|#PB_String_ReadOnly)
Mem = AllocateMemory(#D_ReadBufferSize)
If D_RunProgram("cmd.exe", "/c dir", @ProgramInfo.D_ProgramInfo)
Repeat
len = D_GetOutput(@ProgramInfo, Mem)
If len
SetGadgetText(#Gadget_String, GetGadgetText(#Gadget_String) + PeekS(Mem,len))
EndIf
Until len = 0
tmpstring.s = ""
D_SendInputString(@ProgramInfo,tmpstring)
Repeat
len = D_GetOutput(@ProgramInfo, Mem)
If len
SetGadgetText(#Gadget_String, GetGadgetText(#Gadget_String) + PeekS(Mem,len))
Received + len
EndIf
Until WaitWindowEvent() = #PB_Event_CloseWindow
D_CloseProgram(@ProgramInfo)
Else
MessageRequester("","Exécutable introuvable",16)
EndIf
FreeMemory(Mem)