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)