I am trying to make an application to test certain functionality that I intend to add later to my main program, but without the risk of breaking my main program.
I'm new to Pascal, and I still don't understand how many things work.
The objective of this program is, through a PowerShell command executed in the same application, to obtain several JSON, each one from a specific directory to go through them and check certain things.
These things can be the presence of specific file extensions in certain directories, or the presence of a large volume of information in them.
Create 3 objects in Delphi for this application. A button to start the program, a Timer and a JvCreateProcess.
The interval property of the timer is 10 (ms). The onTimer
property is the Timer1Timer
method.
Timer1Timer
code:
procedure TUProbando.Timer1Timer(Sender: TObject);
var
Comando: TStrings;
ValorJSON: TStrings;
begin
if ContadorDirectorios = Length(rutas) then
begin
Timer1.Enabled := false;
exit;
end;
Timer1.Enabled := false;
Lista.Clear;
// Separador para mejorar la visibilidad de los elementos de los directorios
// a la hora de listarlos
memo_Salida_Command_gci.Lines.Add('******* ' rutas[ContadorDirectorios]
' *******');
Comando := TStringList.Create;
try
// Abro Powershell
Comando.Add('C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe "');
// Comando.Add(comandoPowerShell);
// Agrego la línea de comando siguiente para volcar el contenido del
// directorio especificado en un JSON
Comando.Add('"gci ' rutas[ContadorDirectorios]
' -Recurse | ConvertTo-Json"');
// JvCreateProcess1.Tag:= ;
// Agrego la linea de comando al proceso
JvCreateProcess1.CommandLine := Comando.Text;
// Ejecuto el proceso
JvCreateProcess1.run;
ValorJSON := JvCreateProcess1.ConsoleOutput;
finally
begin
Comando.Free;
end;
end;
end;
The rutas[]
array is a String array containing the directories to check.
rutas: array [0 .. 2] of String = ('C:\Users\operario43\Desktop',
'C:\Users\operario43\Documents', 'C:\Users\operario43\Pictures');
Now, JvCreateProcess1
code:
procedure TUProbando.JvCreateProcess1Terminate(Sender: TObject;
ExitCode: Cardinal);
begin
// Calculo el tamaño del directorio actual
// I WANT GET JSON OF PREVIOUS POWER SHELL COMMAND HERE
SizeDirectory := GetSizeFromJson('JSON HERE', Extensiones);
// el codigo llega aqui, tengo q sacar el json de alguna parte
if checkSizeDirectory(SizeDirectory, SizeControlDirectory) then
begin
ShowMessage('El directorio ' rutas[ContadorDirectorios]
' tiene archivos importantes que no estan protejidos por Backup');
end;
// incremento en 1 la posicion en el array de directorios
// para que la siguiente vez que se ejecute el proceso tome la siguiente
// posición
inc(ContadorDirectorios);
end;
Other methods that I use:
function GetSizeFromJson(JSON: String; vExtensiones: array of string): integer;
var
// Contenedor - Array que contiene los elementos del JSON de cada directorio
Contenedor: TJSONArray;
// Jfichero- Objeto JSON que individualiza cada elementos del JSON
Jfichero: TJSONObject;
// JNombre -Nombre del elemento correspondiente del Jfichero
JNombre: TJSONValue;
// JSizeFile - Valor del elemento 'lenght' de cada elemento del JSON
JSizeFile: TJSONNumber; //
// elemento de bucle for
I: integer;
// Tamaño de un directorio en Bytes
SizeDirectory: Int64;
begin
SizeDirectory := 0;
result := -1;
try
Contenedor := TJSONObject.ParseJSONValue(JSON) as TJSONArray;
// Controlamos el caso de que Contenedor sea null
if Contenedor = nil then
begin
ShowMessage('Error al parsear el json' JSON);
exit;
end;
// Este for recorre el 'array' del JSON contabilizando cada elemento
for I := 0 to Contenedor.Count - 1 do
begin
Jfichero := Contenedor.Items[I] as TJSONObject;
if Jfichero <> nil then
begin
// Extraigo el nombre del elemento
JNombre := Jfichero.GetValue('Name');
// Si las extensiones de los archivos del directorio estan en
// nuestro tracker de extensiones
if MatchStr(ExtractFileExt(JNombre.Value), vExtensiones) then
begin
// Saco el valor del tamaño del elemento en Bytes
JSizeFile := Jfichero.GetValue('Length') as TJSONNumber;
if JSizeFile <> nil then
begin
// Incremento el contador de tamaño del directorio en una cantidad
// igual al tamaño del elemento
inc(SizeDirectory, JSizeFile.AsInt);
end; // if JSizeFile <> nil
end; // if MatchStr(ExtractFileExt(JNombre.Value), vExtensiones)
end; // if Jfichero <> nil
end; // for I := 0 to Contenedor.Count - 1
// Devuelvo el valor de tamaño del directorio
result := SizeDirectory;
except
on E: Exception do
ShowMessage(E.Message);
end;
end;
// metodo para saber si el directorio en cuestion supera el tamaño de directorio
function checkSizeDirectory(vSizeDirectory, vSizeControlDirectory
: Int64): Boolean;
var
Contenedor: TJSONArray;
begin
result := false;
vSizeDirectory := GetSizeFromJson(Contenedor.ToString, Extensiones);
if vSizeDirectory > vSizeControlDirectory then
begin
ShowMessage('El directorio ' rutas[ContadorDirectorios]
' tiene archivos importantes que no estan protejidos por Backup');
end;
end;
My question is, how do I get JSON for JvCreateProcess1Terminate method?.
I've made a lot of changes trying to get it to work, and made small pieces of code to make it more manageable.
CodePudding user response:
Just a note may be It helps someone.
You can save the output of any windows terminal command or application into a file. Just add " > FileName" after the ExeName or commandm then the output will saved to "FileName".
I can use this from Delphi too.
Suppose I want the output of a program called MyApp.exe to be saved to a file then I can use the following command:
Myprog := 'd:\MyApp.exe > FullOutputFileName';
r := ShellExecute(0, 'open', PChar(Myprog), nil, nil, SW_HIDE);
if r <> o then
//Check for error
else
//load the file FullOutputFileName and get results
When using some terminal internal commands like 'dir, ver, vol, ...' I create a batch file (FileName.bat) that contains the command or commands I want to execute then I use shellexecute to execute this file.
Notes:
- You can also use " >> FileName" to append the output to the end of the file.
- This method is slow so it is not advised to use it in loops.
- mORMot has a good and easy to use JSON implementation.
CodePudding user response:
Here comes a little piece of a Code-Snippet which you can use, to execute an DOS Application with the JVCreateProcess Component:
procedure TForm2.JvImgBtn6Click(Sender: TObject);
var
path : String;
begin
try
path := ExtractFilePath(Application.ExeName);
with JvCreateProcess1 do
begin
ApplicationName := 'C:\windows\system32\cmd.exe';
CurrentDirectory := path;
CommandLine := '/c '
path 'build.bat ' path;
ShowMessage(ApplicationName #13#10 CommandLine);
Run;
end;
finally
end;
end;
In this Code, I use the cmd.exe Parameter /C - this close the DOS Terminal Process Window after the execution of "build.bat" is finished.
If you would like to hold open the DOS-Terminal Window, use the /k Parameter.
The path variable before, and after the 'build.bat' stand for:
C:\path\to\build.bat C:\path\as\parameter
So, the build.bat can have the demonstrated content:
@echo off
set DEVPATH=%1
dir