{"id":1180,"date":"2022-04-01T11:14:57","date_gmt":"2022-04-01T14:14:57","guid":{"rendered":"https:\/\/gladiston.net.br\/?page_id=1180"},"modified":"2023-02-28T10:15:50","modified_gmt":"2023-02-28T13:15:50","slug":"lidando-com-parametros-de-entrada-em-seu-aplicativo","status":"publish","type":"page","link":"https:\/\/gladiston.net.br\/en\/programacao\/lazarus-ide\/lidando-com-parametros-de-entrada-em-seu-aplicativo\/","title":{"rendered":"Handling input parameters in your application"},"content":{"rendered":"<p>You are writing a core application or a basic utility and you want it to take parameters like&nbsp;<strong>myutility.exe verbose import=entry.log<\/strong>&nbsp;<strong>export=output.csv<\/strong>&nbsp;to indicate verbosity in the messages, also the file that will be read and finally, the file that will be generated after processing, but the question is: how to correctly detect them within the program? There are many different methods, I will demonstrate the way I use it over time which is simple and maintenance free. The example is for Delphi and Lazarus.<\/p>\n\n\n\n<p>The examples shown use the command line, without a graphical interface, but it wouldn&#039;t make any difference if there was one, I would just change the WriteLn that displays a message in the terminal for another that displays using any dialog window.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #1: Where to check or read the parameters that were informed?<\/h2>\n\n\n\n<p>The first question to consider is: Where do I put my programming code to read the input parameters? The simplest answer is: the best place to read the input parameters is in the very first lines of execution of your program so that they can be used before the process starts. In Delphi and Lazarus the strictest point would be the Project file (.dpr or .lpr), but some prefer to do it in OnCreate of the first form to be presented. Anyway, the next question will be: How to determine if the informed parameters make the execution of the program or utility eligible, that is, which ones will be optional and which ones will be mandatory? And if no parameter is informed, should I proceed anyway?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #2: Are the parameters mandatory or optional?<\/h2>\n\n\n\n<p>In general, the main executable of a system would not need parameters, since the general idea is that it has a graphical interface and could have a configuration screen with checkboxes, listboxes and many other visual options to visually indicate the process to follow. will unfold, this is much simpler than using a command line prompt with parameters. However, many programmers create applications or utilities that support a main program and it is the main program that calls these support programs to handle certain functionality, for example, reading the log file that is encoded and exporting it to a decoded spreadsheet. In this case, the main application calls its support utilities using some parameters to inform the desired action. But the user could also \u2013 with the technical knowledge to it \u2013 run it directly from the command line, the system task scheduler and other methods&nbsp;<strong>as long as you pass the parameters correctly<\/strong>. So, the first thing we will need to know how to do is determine which parameters would be mandatory and which optional. Let&#039;s see what a code like this would look like?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var ErrorMsg:String; sParam:String; iParamCount:Cardinal; bHasImport:Boolean; bHasExport:Boolean; i:Integer; begin \/\/ you will not see the messages on the console using Windows because \/\/ there is an option in Project|Project Options| \/\/ Compiler Options|Config and Target|Win32 gui application (-WG) \/\/ which stays on, so instead of showing the messages in the terminal \/\/ it will show them in a ShowMessage. Leave it off \/\/ if you want to see the messages directly in the terminal iParamCount:=ParamCount; bHasImport:=false; bHasExport:=false; ErrorMsg:=emptyStr; if iParamCount=0 then begin ErrorMsg:=&#039;There are no parameters&#039;; end else begin \/\/ in our example, two parameters will be required: \/\/ import=xxxx, export=yyyy for i:=1 to iParamCount do begin sParam:=ParamStr(i); if ContainsText(sParam, &#039;import=&#039;) then bHasImport:=true; if ContainsText(sParam, &#039;export=&#039;) then bHasExport:=true; end; if (ErrorMsg=emptyStr) and (not bHasImport) then ErrorMsg:=&#039;Missing parameter import=(...)&#039;; if (ErrorMsg=emptyStr) and (not bHasExport) then ErrorMsg:=&#039;Missing parameter export=(...)&#039;; end; if ErrorMsg&lt;&gt;emptyStr then begin writeln(stderr, ErrorMsg); Sleep(5000); \/\/ 5s wait Halt(2); \/\/ &lt;-- Exit Code 2 to indicate to the caller that there was a failure end;<\/code><\/pre>\n\n\n\n<p>Some important lessons in the code above that we can learn:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the count of input parameters starts at index 1 and not at zero, as ParamStr(0) would return the name of the program itself.<\/li>\n\n\n\n<li>we use the function&nbsp;<strong>ContainText<\/strong>&nbsp;which disregards uppercase and lowercase and correctly handles unicode characters, this is especially important on Windows because scripts can be created in the standard ansi(win1252), latin1(iso8859_1) and unicode. Many scripts just fail because of the encoding of the file and not because of the source code in it.<\/li>\n\n\n\n<li>we had the care to give a &#039;<a href=\"https:\/\/gladiston.net.br\/en\/programacao\/lazarus-ide\/exibir-ou-nao-exibir-gui-acompanhada-do-terminal\/\" target=\"_blank\" rel=\"noreferrer noopener\">exit code<\/a>&#039; if things went wrong, imagine your utility was used inside the task scheduler or a script, it would launch your program and need to know if your utility worked or failed to determine the next action.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step #3: Reading input parameters, validating and processing<\/h2>\n\n\n\n<p>After the first check found that the parameters exist and the mandatory ones were informed then it&#039;s time to understand the parameters, some like &quot;verbose&quot; don&#039;t have an equal sign because it just designates the action, in this case, asking the program to issue more messages of text than it would ordinarily show. But there are also parameters with the equal sign \u201c=\u201d, what does that mean? The concept of equality in a stringlist is usually called a key\/value or pairList, but here we are going to give it different names, to the left of the equal sign we will call it action (or verb) and to the right of the equality we have the action detail, for example ,&nbsp;<strong>import=file.log<\/strong>&nbsp;is to say that I must&nbsp;<strong>import<\/strong>(action or verb) the&nbsp;<strong>.log file<\/strong>(detail of action). Let&#039;s go to the code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var aList:TStringList; iParamCount:Cardinal; sParam:String; sImportFile:String; sExportFile:String; bHasVerbose:Boolean; ErrorMsg:String; i:Integer; begin ErrorMsg:=emptyStr; sImportFile:=emptyStr; sExportFile:=emptyStr; aList:=TStringList.Create; aList.CaseSensitive:=false; iParamCount:=ParamCount; \/\/ including all parameters in a stringlist, \/\/ you&#039;ll see how much easier it is to read for i:=1 to iParamCount do begin sParam:=ParamStr(i); \/\/ we don&#039;t want to duplicate equal parameters if aList.IndexOF(sParam)&lt;0 then aList.Add(sParam); end; \/\/ Want verbosity? bHasVerbose:=(aList.IndexOfName(&#039;verbose&#039;)&gt;=0); \/\/ looking if the parameter import=archive.log, it must exist to proceed if (ErrorMsg=emptyStr) and (aList.IndexOfName(&#039;import&#039;)&gt;=0) then begin sImportFile:=aList.Values[&#039;import&#039;] ; if not FileExists(sImportFile) then ErrorMsg:=&#039;File to import does not exist: &#039;+sImportFile end else begin ErrorMsg:=&#039;Where is the parameter import=file.log!&#039;; end; \/\/ looking if the parameter export=file.csv, it must not exist to proceed if (ErrorMsg=emptyStr) then begin if(aList.IndexOfName(&#039;export&#039;)&gt;=0) then begin sExportFile:=aList.Values[&#039; export&#039;]; if FileExists(sExportFile) then ErrorMsg:=&#039;File to export already exists: &#039;+sExportFile end else begin ErrorMsg:=&#039;Where is the parameter export=arquivo.csv!&#039;; end; end; if ErrorMsg&lt;&gt;emptyStr then begin writeln(stderr, ErrorMsg); Sleep(5000); \/\/ 5s wait Halt(2); \/\/ &lt;-- Exit Code 2 to indicate to the caller that it failed end else begin \/\/ processing the rest of the program... if bHasVerbose then writeln(StdOut, &#039;Importing &#039;+sImportFile+&#039; and exporting &#039;+sExportFile+&#039;. ..&#039;) else writeln(StdOut, &#039;Importing...&#039;); end; \/\/ Destroying objects aList.Free;<\/code><\/pre>\n\n\n\n<p>The other lessons we can learn from the code above:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The input parameters have their default values, the&nbsp;<strong>bVerbose<\/strong>, for example is false and sImportFile\/sExportFile are empty and unless the input parameters change this, empty is not acceptable.<\/li>\n\n\n\n<li>code with object creation \u2013 we had a TStringlist \u2013 we will avoid an &#039;exit&#039; in the middle of the code, because in each exit we would have to remember to destroy these objects so it is easier instead of an exit, to control the flow through a variable&nbsp;<strong>ErrorMsg<\/strong>&nbsp;where instead of Exit, store the reason for the exit and then control the flow, while&nbsp;<strong>ErrorMsg<\/strong>&nbsp;is empty all lines are executed, otherwise ignored until they encounter a halt, terminate or end of code where all created objects will be destroyed.<\/li>\n\n\n\n<li>we don&#039;t have one&nbsp;<strong>exit&nbsp;<\/strong>in the middle of the code, not only because we create objects at the beginning, but because it is a&nbsp;<strong>go to<\/strong>&nbsp;disguised and there are reasons why some people don&#039;t like him, on pascal,&nbsp;<strong>exit<\/strong>&nbsp;(or other forms of code bypass) misused creates a macaronic effect on the code making it difficult to understand the code or debug errors. But you don&#039;t have to be radical, personally I find an exit after some validations at the beginning of the code before the processing to be quite useful.<\/li>\n\n\n\n<li>the process only starts after all validations have been done and&nbsp;<strong>ErrorMsg<\/strong>&nbsp;is empty, in fact, we use this variable to control the flow and reuse it to say what went wrong in case an error arose.<\/li>\n\n\n\n<li>the Sleep(5000) command is just to be didactic, if you turned off the Project|Project Options|Compiler Options|Config and Target|Win32 gui application (-WG) option you will have time to see the error message in the terminal before it be closed.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Only for Lazarus and FreePascal<\/h2>\n\n\n\n<p>Lazarus, actually FreePascal(FPC) has a unit called&nbsp;<strong>CostApp<\/strong>, this library abstracts much of what we saw above with little code, we can check the presence of a parameter, even if it is of type key and value:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var ErrorMsg: String; sImportFile:String; begin \/\/ quickly checking the parameters ErrorMsg:=CheckOptions(&#039;i&#039;, &#039;import&#039;); if ErrorMsg&lt;&gt;emptyStr then begin ShowException(Exception.Create(ErrorMsg)); Terminate; exit; end; if HasOption(&#039;i&#039;, &#039;import&#039;) then begin sImportFile:=getOptionValue(&#039;i&#039;, &#039;import&#039;)); end;  <\/code><\/pre>\n\n\n\n<p>The interesting thing about this library is that it simplifies the many different ways of passing parameters, for example, -v, -verbose, \u2013verbose can be in a single call. But the&nbsp;<strong>CostApp&nbsp;<\/strong>for now it is only for Lazarus\/FPC and could not be used in Delphi. You can find more information here:<\/p>\n\n\n\n<p><a href=\"https:\/\/wiki.freepascal.org\/Command_line_parameters_and_environment_variables\">https:\/\/wiki.freepascal.org\/Command_line_parameters_and_environment_variables<\/a><\/p>\n\n\n\n<p>If you need an example to study, download the demos from github:<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/gladiston\/lazdemos_gsl\">https:\/\/github.com\/gladiston\/lazdemos_gsl<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Criando utilit\u00e1rios de linha de comando com o Lazarus no Linux e Windows<\/h2>\n\n\n\n<p>Se estiver usando Lazarus\/FPC, voc\u00ea deve tomar muito cuidado com as dependencias de projeto que necessitem do ambiente gr\u00e1fico, um modo de inibir o uso de interface gr\u00e1fica \u00e9 ir nas op\u00e7\u00f5es do Projeto, isto \u00e9, Project|Options|Compiler Options|Configs and Targets e ent\u00e3o ir em <strong>Select another LCL widgetset<\/strong> e trocar o conjunto de widgets para <strong>nogui<\/strong>, isso indicar\u00e1 ao compilador para n\u00e3o injetar dependencias com win23, gtk, qt,&#8230;ou qualquer conjunto de widgets do sistema operacional hospedeiro:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"532\" src=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2023\/02\/lazarus_nogui2.png\" alt=\"\" class=\"wp-image-2141\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2023\/02\/lazarus_nogui2.png 802w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2023\/02\/lazarus_nogui2-300x199.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2023\/02\/lazarus_nogui2-768x509.png 768w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2023\/02\/lazarus_nogui2-18x12.png 18w\" sizes=\"auto, (max-width: 802px) 100vw, 802px\" \/><\/figure>\n\n\n\n<p>Mas a op\u00e7\u00e3o acima n\u00e3o faz milagre, se voc\u00ea acidentalmente usar um Application.MessageBox ou exibir um form acidentalmente, voc\u00ea carregar\u00e1 uma dependencia de pacote chamado de LCL que cont\u00e9m componentes com widgets visuais com interatividade com o usu\u00e1rio e da\u00ed ent\u00e3o sua aplica\u00e7\u00e3o sendo para a linha de comando acidentalmente carregou as dependencia de widgets e ficar\u00e1 dificil usar seu utilit\u00e1rio num Linux, BSD, Solaris&#8230; que seja desprovido de interface grafica, mas funcionar\u00e1 no Windows &#8211; desde que n\u00e3o seja a vers\u00e3o Windows Core &#8211; porque ele tem UI o tempo inteiro.<\/p>\n\n\n\n<p>Se sua inten\u00e7\u00e3o \u00e9 criar um aplicativo cmd para interagir com aplica\u00e7\u00f5es REST, php, node ou qualquer linguagem server-side que chame pelo seu programa ent\u00e3o \u00e9 vital que nenhuma dependencia de interface gr\u00e1fica seja incluida; Da\u00ed componentes n\u00e3o visuais e geradores de relat\u00f3rios ao inv\u00e9s de usar forms, devem usar datamodules. Alguns dizem que formul\u00e1rios podem ser acrescidos ao projeto, mas jamais usar Show ou Showmodal neles, mas isso \u00e9 ainda lenda para mim, terei de testar isso na pr\u00e1tica mais tarde, por ora, recomendo que use apenas datamodules.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ecoando mensagens no terminal do Windows<\/h2>\n\n\n\n<p>Diferentemente do Linux, BSD, Solaris, Mac,.. onde os programas mesmo com interface gr\u00e1fica \u201cecoam\u201d mensagens no terminal, no Windows os programas precisam ser disparados pelo terminal para que suas mensagens sejam vistas. Se voc\u00ea usa o Lazarus, voc\u00ea teria de compilar o programa e depois ir para o terminal para execut\u00e1-lo para ver tais mensagens enviadas pelo comando Write. Por\u00e9m h\u00e1 uma configura\u00e7\u00e3o que nos permite executar estes programas de terminal no Lazarus sem precisar ir para o prompt, v\u00e1 em Project|Project Options|Compiler Options|Config and Target e desligue a op\u00e7\u00e3o Win32 gui aplication (-WG):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"799\" height=\"391\" src=\"https:\/\/i0.wp.com\/gladiston.net.br\/wp-content\/uploads\/2022\/02\/lazaus_ide_Win32_gui_aplications.png?resize=782%2C383&amp;ssl=1\" alt=\"\" class=\"wp-image-959\" srcset=\"https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/02\/lazaus_ide_Win32_gui_aplications.png 799w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/02\/lazaus_ide_Win32_gui_aplications-300x147.png 300w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/02\/lazaus_ide_Win32_gui_aplications-768x376.png 768w, https:\/\/gladiston.net.br\/wp-content\/uploads\/2022\/02\/lazaus_ide_Win32_gui_aplications-18x9.png 18w\" sizes=\"auto, (max-width: 799px) 100vw, 799px\" \/><figcaption class=\"wp-element-caption\">A op\u00e7\u00e3o Win32 gui aplication (-WG) nos permite ver a execu\u00e7\u00e3o do programa no terminal sem abandonar a IDE. Mas quando o projeto estiver conclu\u00eddo, n\u00e3o \u00e9 preciso estar habilitado.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusao\">Conclusion<\/h2>\n\n\n\n<p>In this article we learned some techniques for dealing with input parameters and other things besides, such as validations and the flow of execution of a program.<\/p>","protected":false},"excerpt":{"rendered":"<p>Voc\u00ea esta escrevendo um aplicativo principal ou um utilit\u00e1rio b\u00e1sico e deseja que ele receba par\u00e2metros como&nbsp;meuutilitario.exe verbose import=entrada.log&nbsp;export=saida.csv&nbsp;para indicar verbosidade nas mensagens, tamb\u00e9m o arquivo que ser\u00e1 lido e por fim, o arquivo que ser\u00e1 gerado ap\u00f3s o processamento, mas a pergunta \u00e9: como detect\u00e1-los corretamente dentro do programa? H\u00e1 muitos m\u00e9todos diferentes, vou [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"parent":159,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"templates\/template-full-width.php","meta":{"footnotes":""},"class_list":["post-1180","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/comments?post=1180"}],"version-history":[{"count":6,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1180\/revisions"}],"predecessor-version":[{"id":2143,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/1180\/revisions\/2143"}],"up":[{"embeddable":true,"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/pages\/159"}],"wp:attachment":[{"href":"https:\/\/gladiston.net.br\/en\/wp-json\/wp\/v2\/media?parent=1180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}