Question sur ReadProgramString()

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
gildev
Messages : 380
Inscription : mar. 19/juin/2007 10:28
Localisation : Picardie (France)

Question sur ReadProgramString()

Message par gildev »

Bonjour à tous! Je viens de reprendre Purebasic car ça m'a trop manqué depuis des années. Du coup je galère sur une incompréhension.

Code : Tout sélectionner

EnableExplicit
Define Commande = RunProgram("chkdsk", " c: /i", "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Ascii|#PB_Program_Hide)
Define Sortie.s

If Commande
	While ProgramRunning(Commande)
		If AvailableProgramOutput(Commande)
			Sortie = ReadProgramString(Commande)
			Debug Sortie
		EndIf
	Wend
	CloseProgram(Commande)
EndIf
ATTENTION : il faut obligatoirement activer "Utiliser les droits administrateur" dans les options du compilateur pour lancer le programme.

Le programme lance la commande CHKDSK C: /i et affiche le résultat dans le debug. Sauf qu'il y a une couille dans la pâté : il manque les lignes de l'état d'avancement en temps réel de chacune des étapes. Pourtant elles apparaissent bien si on lance la commande dans la fenêtre CMD de Windows. Mon objectif est de récupérer justement ce pourcentage dans mon appli. Si l'un de vous a une idée je suis preneur. Merci d'avance.

PS : J'espère que les anciens sont encore là vous me manquez. :wink:
Avatar de l’utilisateur
gildev
Messages : 380
Inscription : mar. 19/juin/2007 10:28
Localisation : Picardie (France)

Re: Question sur ReadProgramString()

Message par gildev »

En fait je pense que la commande AvailableProgramOutput() ne permet pas de récupérer tout le flux. Il faut donc trouver un autre moyen mais là je sèche...
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Question sur ReadProgramString()

Message par cage »

Bonjour,

J'ai essayé avec OpenConsole() et PrintN, après il faut gérer la sortie.

cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Question sur ReadProgramString()

Message par Mesa »

Code : Tout sélectionner

; https://www.purebasic.fr/german/viewtopic.php?t=2893&highlight=
#D_ReadBufferSize = 1024

Structure D_ProgramInfo
	StartUpInfo.STARTUPINFO
	ProcessInfo.PROCESS_INFORMATION
	SECURITYATTRIBUTES.SECURITY_ATTRIBUTES
	hOutputPipeRead.l
	hOutputPipeWrite.l
	hInputPipeRead.l
	hInputPipeWrite.l
	hReadThread.l
	ReadThreadStat.l
	ReadBuffer.l
	ReadDataLen.l
EndStructure

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
	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\dwFlags = #STARTF_USESTDHANDLES | #STARTF_USESHOWWINDOW
		*ProgramInfo\StartUpInfo\hStdOutput = *ProgramInfo\hOutputPipeWrite
		*ProgramInfo\StartUpInfo\hStdError = *ProgramInfo\hOutputPipeWrite
		*ProgramInfo\StartUpInfo\hStdInput = *ProgramInfo\hInputPipeRead
		If CreateProcess_(#Null,Chr(34)+EXEFileName+Chr(34)+" "+Parameter,@*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
		Debug *ProgramInfo\ReadBuffer
		Debug 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.l
	CharToOemBuff_(string,string,Len(string))
	If WriteFile_(*ProgramInfo\hInputPipeWrite,string,Len(string),@tmp,0)
		ProcedureReturn tmp
	EndIf
	ProcedureReturn #False
EndProcedure

Procedure D_SendInput(*ProgramInfo.D_ProgramInfo,Buffer.l,Bufferlen.l)
	Protected tmp.l
	If WriteFile_(*ProgramInfo\hInputPipeWrite,Buffer,Bufferlen,@tmp,0)
		ProcedureReturn tmp
	EndIf
	ProcedureReturn #False
EndProcedure

;Win only
Procedure.s OemToChar(String.s) 
	OemToChar_(@String, @String) 
	ProcedureReturn String 
EndProcedure

#Gadget_String = 0

OpenWindow(0,0,0,400,200,"Console",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
; StringGadget(#Gadget_String,0,0,400,200,"",#PB_String_MultiLine|#PB_String_ReadOnly)
EditorGadget(#Gadget_String,0,0,400,200)

Mem = AllocateMemory(#D_ReadBufferSize)

If D_RunProgram("CHKDSK"," C: /i",@ProgramInfo.D_ProgramInfo) ; Les données sont stockées dans ProgramInfo
	
	; If D_RunProgram("ping","localhost",@ProgramInfo.D_ProgramInfo) ; Les données sont stockées dans ProgramInfo
	
	Repeat
		len = D_GetOutput(@ProgramInfo,Mem)
		If len
			;       SetGadgetText(#Gadget_String,GetGadgetText(#Gadget_String)+PeekS(Mem,len))
			AddGadgetItem(#Gadget_String, -1, PeekS(Mem,len) );OemToChar(PeekS(Mem,len))
			
		EndIf
	Until len = 0
	
	
	
	; tmpstring.s = "netstat"+Chr(13)+Chr(10) ; !IMPORTANT! CHR(10) doit se produire, sinon la commande ne sera pas acceptée
	; D_SendInputString(@ProgramInfo,tmpstring)
	
	
	Repeat
		len = D_GetOutput(@ProgramInfo,Mem)
		If len
			;     	SetGadgetText(#Gadget_String,GetGadgetText(#Gadget_String)+PeekS(Mem,len))
			AddGadgetItem(#Gadget_String, -1, PeekS(Mem,len))
			Received + len
		EndIf
	Until WaitWindowEvent() = #PB_Event_CloseWindow
	
	D_CloseProgram(@ProgramInfo)
	
Else
	MessageRequester("","Impossible d'exécuter le programme !",16)
EndIf

;Fuite de mémoire ????
; If Mem
; 	FreeMemory(Mem)
; EndIf
Avatar de l’utilisateur
gildev
Messages : 380
Inscription : mar. 19/juin/2007 10:28
Localisation : Picardie (France)

Re: Question sur ReadProgramString()

Message par gildev »

Tout au début j'étais parti sur la méthode OpenConsole() mais comme je n'avais pas eu de résultat probant je suis parti sur RunProgram() qui m'a semblé plus prometteur. En tout cas merci cage pour ta suggestion :)

La solution de Mesa répond au besoin, merci beaucoup :) Je vais étudier ça ce weekend avec attention.

Ca me fait plaisir de savoir que ce forum est toujours là avec une communauté active. J'ai bien fait de revenir.
Répondre