Last modified by Jannis Klein on 2024/08/13 08:19

Show last authors
1 {{aagon.priorisierung}}
2 160
3 {{/aagon.priorisierung}}
4
5 {{aagon.floatingbox/}}
6
7 = Initial situation =
8
9 This Use Case shows you step by step how to send the [[Form Editor>>doc:65.ACMP-Solutions.Client Commands.Client Command erstellen.Client Commands neu hinzufügen.Client Command Editor.Commandlist.Dialogs.Der Form Editor.WebHome]] to a Client via the AESB Interface using a Client Command. The available Clients are loaded from the database and displayed in a list. A search field allows the user to filter for specific Client Commands. The hits are retrieved from the database and also displayed in a list. To prevent the Client Commands from being sent inadvertently, the user must tick a checkbox. This is to confirm that the selected Client and Client Command are correct.
10
11 For ease of understanding, much of the content of the //Form Editor //is explained in the Code View.
12
13 {{figure}}
14 (% style="text-align:center" %)
15 [[image:66_Use Case Client Commands_AESB Code Ausschnitt_906.png]]
16
17 {{figureCaption}}
18 Code view for the following Client Command use case
19 {{/figureCaption}}
20 {{/figure}}
21
22 {{aagon.infobox}}
23 Read here how to [[install AESB>>doc:AESB.19.AESB installieren, konfigurieren und aktualisieren.AESB Core-Komponenten installieren.WebHome]] and how the [[ACMP and AESB components are connected>>doc:AESB.19.AESB installieren, konfigurieren und aktualisieren.SICS-Verbindung konfigurieren.WebHome]].
24 {{/aagon.infobox}}
25
26 == Select script ==
27
28 1. Navigate to the //Client Commands// > //Create// module.
29 1. Click //Add// on the ribbon bar. The Client Command Editor will open and you will need to decide whether it is a Console or Client Script. In this case select the Console Script.
30
31 == To select and edit the //Set project variable //Command ==
32
33 1. Select the //Variables// > //Set project variable// command from the Command list..
34 1. Double click the Command and select the //General// tab.
35 1. Enter a name under //Description of actions//. In this example, "Set the AESB user name here" is inserted. All other configuration options in this tab do not need to be customised.
36 1. Switch to the //Details// tab.
37 1. Under Variable Settings, click on the icon next to the variable name.
38 1. Optional: Create a new variable under //Actions//. Name it "USERNAME" and click on the plus sign. Then click on the //OK// button to complete the step and have the entry listed as the variable name.
39
40 {{aagon.infobox}}
41 This step is optional if this variable has not yet been created in your system.
42 {{/aagon.infobox}}
43
44 7. In the //Single line// text box, enter „Operator“. This is required here as an identifier for the user name.
45 8. Click //OK//.
46
47 {{figure}}
48 (% style="text-align:center" %)
49 [[image:66_Use Case Client Commands_AESB Form Editor Set project variable Username_570.png]]
50
51 {{figureCaption}}
52 Making variable settings
53 {{/figureCaption}}
54 {{/figure}}
55
56 == To select and edit a Command //Set project variable// ==
57
58 1. Select the Command //Set project variable// again.
59 1. Double click on the Command and open the //General// tab.
60 1. Under Description, enter the name of the action, e.g. //Set the AESB user password// here. Do not make any further changes to the other settings, they are not necessary.
61 1. Switch to the //Details// tab.
62 1. Optional: Create a new variable in the //variable settings//. To do this, click on the icon next to the list entries and a new window will open. Name the new variable "PASSWORD" and click on the plus sign. Click //OK// to complete this step.
63
64 {{aagon.infobox}}
65 This step is optional if you have not already created this variable.
66 {{/aagon.infobox}}
67
68 6. Select the //Plain text// option if you have not already done so. The clear text password will be added to this line later.
69 7. Finish your work on this Command and click //OK//.
70
71 {{figure}}
72 (% style="text-align:center" %)
73 [[image:66_Use Case Client Commands_AESB Form Editor Set project variable Password_476.png]]
74
75 {{figureCaption}}
76 Defining variable settings
77 {{/figureCaption}}
78 {{/figure}}
79
80
81 == Opening and editing the Command //Form Editor// ==
82
83 {{aagon.warnungsbox}}
84 The Client Command Form Editor is extremely complex and should only be used if you have sufficient knowledge of programming under Delphi scripts and also know how to use an [[IDE (Integrated Development Environment)>>doc:65.ACMP-Solutions.Client Commands.Client Command erstellen.Client Commands neu hinzufügen.Client Command Editor.Commandlist.Dialogs.Der Form Editor.Die IDE.WebHome]].
85 {{/aagon.warnungsbox}}
86
87 You can edit the elements of the [[Form Editors>>doc:65.ACMP-Solutions.Client Commands.Client Command erstellen.Client Commands neu hinzufügen.Client Command Editor.Commandlist.Dialogs.Der Form Editor.WebHome]] using either the code view or the design view. To make it easier to understand, the following section deals with the visual design view only in isolated cases, and more with the code. This means that the explanations of the properties and events of the Object Inspector, which you can read [[here>>doc:65.ACMP-Solutions.Client Commands.Client Command erstellen.Client Commands neu hinzufügen.Client Command Editor.Commandlist.Dialogs.Der Form Editor.WebHome||anchor="HObjectInspectorFormEditor"]], are no longer necessary.
88
89 Use this Client Command to create an interactive form where you can assign a selected Client Command to a Client. To do this, proceed as follows:
90
91 1. Select the Client Command Form Editor (//Dialogs// > //Form Editor//).
92 1. Double click on the Command, open the //General// tab and optionally customise the //description of the actions//. In this example the title remains //Form Editor//.
93 1. Switch to the //Edit Form// tab.
94 1. Click on the //Edit Form// button below the preview form. A new window opens for working with the Form Editor in the standard view, with some custom fields.
95
96 {{aagon.infobox}}
97 For more information on using the Form Editor or the IDE (Integrated Developer Environment) see [[here>>doc:65.ACMP-Solutions.Client Commands.Client Command erstellen.Client Commands neu hinzufügen.Client Command Editor.Commandlist.Dialogs.Der Form Editor.WebHome||anchor="HObjectInspectorFormEditor"]].
98 {{/aagon.infobox}}
99
100 5. Switch from the design view to the code view by clicking on the tab at the bottom (see illustration). The view will change.
101
102 {{figure}}
103 (% style="text-align:center" %)
104 [[image:66_Use Case Client Commands_AESB Form Editor Standard_1191.png]]
105
106 {{figureCaption}}
107 Form Editor view
108 {{/figureCaption}}
109 {{/figure}}
110
111 6. Switch to the //FormUnit// tab if you are not already there. Here you can see the code from the upper Custom Windows window from the design view. This code now needs to be customised for your purposes.
112
113 {{figure}}
114 (% style="text-align:center" %)
115 [[image:66_Use Case Client Commands_AESB Form Editor Code Ansicht_592.png]]
116
117 {{figureCaption}}
118 View of the code for the Custom Windows window
119 {{/figureCaption}}
120 {{/figure}}
121
122 == Customising the code ==
123
124 The code is divided into useful sections and explained below. Always insert the lines in the order shown here to ensure that the client commands work correctly. The form will be executed as it will be displayed later.
125
126 {{aagon.infobox}}
127 All information in the code that appears after a double slash is commented out and only serves to explain the following lines. They are not part of the execution.
128 {{/aagon.infobox}}
129
130
131 |(% style="width:859px" %)**Row section**|(% style="width:505px" %)**Description**
132 |(% style="width:859px" %)**Row 1 - 13**|(% style="width:505px" %)
133 |(% style="width:859px" %){{code language="none"}}{$FORM TCustomACMPWindow, FormUnit.sfm}
134
135 uses
136 Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls,
137 StdCtrls, SysUtils, Buttons, AagonSQLQuery, AagonAESBV1,
138 ComCtrls;
139 var
140 LClients, LClientCommands, ResultMessages: TStringlist;
141 IResult, Protocol, ExchangeType, AErrorCode, ConnectionTimeout: Integer;
142 Server, Port, SClientID, SClientCommandID, MessageID, AAckMessages, AResult, Username,
143 Passwort, ConnectionString, VirtualRouter, RoutingKey, Tag, CallbackVirtualRouter, CallbackRoutingKey,
144 TargetConnectionVariable : string;
145 {{/code}}|(% style="width:505px" %)(((
146 These rows define the display of the Form Editor for the user and describe what the display is filled with and what type of content is generated (data type: string, row 12).
147
148 In the rows, units are added (//uses//, rows 3 - 6) and variables (//var//, rows 7 - 12) are declared, which can be filled at a later time. The respective variable type (e.g. TStringlist, Integer or String) is shown after the variable names.
149
150
151 )))
152 |(% style="width:859px" %)**Row 14 - 21**|(% style="width:505px" %)
153 |(% style="width:859px" %){{code language="none"}}//
154 function EscapeValues(Value: String) : String;
155 begin
156 Value := '"'+StringReplace(Value,',','","')+'"';
157 Result := StringReplace(Value, '","","', ',');
158 end;
159
160 //{{/code}}|(% style="width:505px" %)This function is required to use certain special characters in strings. Some special characters in the string have a special meaning for the program: If you want to display these special characters, you must "escape" them. When escaping, the special character to be displayed is preceded by the same character or a specific other character, such as a "\".
161 |(% style="width:859px" %)**Row 22 - 45**|(% style="width:505px" %)
162 |(% style="width:859px" %){{code language="none"}}function SetAESBConfig;
163 begin
164 Protocol := 1; // HTTP (0) / HTTPS (1)
165 ConnectionTimeout:= 30; // Timeout in Sekunden
166 ExchangeType:= 1; // Direct (0) / Routing (1)
167 ResultMessages.Clear();
168 AAckMessages:= '';
169 AResult:= '';
170 AErrorCode:= 0;
171 IResult:= 0;
172 Server:= '127.0.0.1';
173 Port:= '3900';
174 Username:= GetVarContent('USERNAME');
175 Passwort:= GetVarContent('PASSWORD');
176 TargetConnectionVariable:= 'CONNECTION';
177 ConnectionString:= '';
178 MessageID:= '{43584358-4358-4358-4358-435843584358}'; //hier kann eine beliebige GUID verwendet werden
179 VirtualRouter:= 'VCMN';
180 RoutingKey:= '?.Aagon.Components.ACMPServer.*';
181 Tag:= 'ICQL';
182 CallbackVirtualRouter := '';
183 CallbackRoutingKey := '';
184 end;
185 {{/code}}|(((
186 In this section, the variables for the AESB service function (//function// //SetAESBConfig//, row 22) are defined and filled with values. The function is required later (from row 142), but you must already configure it at this point.
187
188 Fill the rows of the function as follows:
189
190 Row 24: Enter the type of protocol here. The value 0 stands for an HTTP page, 1 for an HTTPS page. Insert a 1 here, as this is an encrypted request.
191
192 Row 25: Specify a number of seconds when the request to the AESB runs into a timeout. The default value "30 seconds" was specified here.
193
194 Row 26: The ExchangeType can either be filled with the type "Direct (0)" or "Routing (1)". The latter option is selected here.
195
196 Row 27: ResultMessages.Clear() deletes the string list.
197
198 Rows 28 - 29: The two variables //AAckMessages// and //AResult// can be left clear. To do this, enter '' after the equals sign.
199
200 Rows 30 - 31: The //AErrorCode// and //IResult// are each filled with the value 0.
201
202 Row 32: Enter the name or IP of the AESB Server you want to connect to. In this example it is '127.0.0.1'.
203
204 Row 33: Enter the port number you need for the connection (here: '3900').
205
206 Row 34: The //GetVarContent// function is used here, which refers to the project variable ('USERNAME'). The project variable must be created and filled outside the Form Editor in the Client Commands themselves.
207
208 Row 35: The //GetVarContent// function is used here, which refers to the project variable ('PASSWORD'). This project variable must also be created and filled outside the Form Editor in the Client Command itself.
209
210 Row 36: The variable TargetConnectionVariable must be filled with the value 'CONNECTION'. The protocol requires this type for this type of connection (type: Connection).
211
212 Row 37: The value of the ConnectionString remains clear (' ') and will be filled with values later on.
213
214 Row 38: The MessageID is a GUID that can be exchanged and used as desired. When entering it, however, it is important that it follows the same input scheme: The number of digits must remain the same (8-4-4-4-8 digits each).
215
216 Row 39: The value 'VCMN' must be entered for the VirtualRouter. This is a virtual section within the AESB in which the ACMP Server is located. As this example communicates with the ACMP, this router must be specified.
217
218 Row 40: The RoutingKey specifies where the entered values are to be sent. Accordingly, the ACMP Server that is to receive the entries must be entered here. In this example it is called '?.Aagon.Components.ACMPServer.*'. The question mark and the asterisk both represent a wildcard. The asterisk represents the ACMP Server ID. If you have several ACMP Servers connected to the AESB, you can also enter the ID of one Server to route the data only to it.
219
220 Row 41: The input row //Tag// describes the type of message. As the ICQL protocol is used here, the value to be entered must be 'ICQL'.
221
222 Lines 42 - 43: The virtual router (CallbackVirtualRouter, row 42) and routing key (CallbackRoutingKey, row 43) are displayed here. No response is required, so a '' is sufficient as a clear value after the equals sign in both rows.
223 )))
224 |(% style="width:859px" %)**Row 46 - 55**|(% style="width:505px" %)
225 |(% style="width:859px" %){{code language="none"}}function GetClientID : String;
226 var
227 Ltemp : TStringList;
228 begin
229 LTemp := TStringList.Create();
230 LTemp.CommaText := LClients.Strings[LBClients.ItemIndex];
231 Result := LTemp.Values['CLIENTID'];
232 LTemp.Free();
233 end
234 {{/code}}|(% style="width:505px" %)(((
235 The //GetClientID// function, with a return value of the String type, is described in rows 46 - 50. The function determines the Client ID of the Client selected in the interface from the //LBClients// list.
236
237 Row 46: Start of the //GetClientID// function with a string as the return value.
238
239 Rows 47 - 54: The value //LClients.Strings// contains the index of the Client you have selected. With this index, the corresponding Client is selected from the //LClients.Strings// list and temporarily stored in a temporary variable. The return value of the function (row 52) is set to the value "Client ID" from the temporary variable and thus corresponds to the Client ID that you have chosen as the selected agent from the list. The working memory is released again via row 53.
240 )))
241 |(% style="width:859px" %)**Row 56 - 65**|(% style="width:505px" %)
242 |(% style="width:859px" %){{code language="none"}}function GetClientCommandID : String;
243 var
244 Ltemp : TStringList;
245 begin
246 LTemp := TStringList.Create();
247 LTemp.CommaText := LClientCommands.Strings[LBClientCommands.ItemIndex];
248 Result := LTemp.Values['SCRIPTID'];
249 LTemp.Free();
250 end
251 {{/code}}|(% style="width:505px" %)(((
252 Rows 56 - 65 describe the //GetClientCommandID// function. The function determines the Client Command ID of the Client Commands selected in the interface from the //LBClientCommands// list.
253
254 Row 56: Start of the //GetClientCommandID// function with a string as the return value.
255
256 Rows 57 - 65: //LBClientCommands.ItemIndex// contains the index of the Client Command you have selected. This index is used to select the corresponding Client Command from the //LClientCommands.Strings// list and temporarily store it in a temporary variable. The return value of the function (row 52) is set to the value "Script ID" from the temporary variable and thus corresponds to the Client Command ID that you have chosen as the selected Client Command from the list.
257
258 The working memory is released via row 63 (//LTemp.Free()//).
259 )))
260 |(% style="width:859px" %)**Row 66 - 80**|(% style="width:505px" %)
261 |(% style="width:859px" %){{code language="none"}}function CreateMessageBody : String;
262 var
263 MessageBody : TStringList;
264 begin
265
266 MessageBody := TStringList.Create();
267 MessageBody.Add('<ICQL><ACMP><EnqueueClientCommand version="1">');
268 MessageBody.Add('<TEnqueueClientCommandRequest_V1 xmlns:xsi="http:~/~/www.w3.org/2001/XMLSchema-instance">');
269 MessageBody.Add('<ClientId>'+GetClientID+'</ClientId>');
270 MessageBody.Add('<ClientCommandId>'+GetClientCommandID+'</ClientCommandId>');
271 MessageBody.Add('</TEnqueueClientCommandRequest_V1></EnqueueClientCommand></ACMP></ICQL>');
272 Result := MessageBody.Text;
273 MessageBody.Free();
274 end {{/code}}|(% style="width:505px" %)(((
275 The rows 66 - 80 describe the functions for creating the message that is sent to the SICS / AESB. In the section where the MessageBody is defined and filled, the data type must first be defined. Row 72 contains various values that must be adhered to. ICQL stands for the format in which the SICS expects the request, as well as the value ACMP. //EnqueueClientCommand// specifies that a function is to be called to queue a Client Commands in version 1.
276
277 Rows 74 and 75 specify that the request must contain the Client ID and the //GetClientCommandID// as a day so that the recipients (in this case the ACMP Server) know which Client Command to send to which Client.
278
279 The return value (row 77) then contains the complete message. This is followed by a network share of the working memory via row 78.
280 )))
281 |(% style="width:859px" %)**Row 81 - 109**|(% style="width:505px" %)
282 |(% style="width:859px" %){{code language="none"}}procedure GetClients;
283 var
284 LSQL, LTemp : TStringList;
285 I : Integer;
286 begin
287 LSQL := TStringList.Create();
288 LTemp := TStringList.Create();
289
290 // SQLStatement zum Ermitteln der Clients
291 LSQL.Add('SELECT COMPUTERNAME, CLIENTID');
292 LSQL.Add('FROM CLT_CLIENTS');
293 LSQL.Add('WHERE ismanaged = 1');
294 LSQL.Add('ORDER BY COMPUTERNAME');
295
296 // Leeren der Listbox der Clients
297 LBClients.Clear();
298 LClients.Clear;
299 // Ausführen des Statements zum Beziehen der Clients aus der DB
300 SQLQuery(LSQL.Text,'','',LClients,true,30);
301
302 for i := 0 to (LClients.Count-1) do
303 begin
304 LTemp.Commatext := EscapeValues(LClients.Strings[i]);
305 LBClients.Items.Add(LTemp.Values['COMPUTERNAME']);
306 end
307 LSQL.Free();
308 LTemp.Free();
309 end;
310 {{/code}}|(% style="width:505px" %)(((
311 Rows 81 - 109 (//procedure GetClients//) retrieve the agents from the database and save them in the left box, which is filled with the entries directly when the window is started. To do this, two lists are first defined and then created (86 and 87). The SQL Query/SQL statement is then assembled and filled with values, which enables the Clients to be determined. Only the computer name and the Client ID are retrieved from the //CLT_Clients// table. The condition //ismanaged=1// ensures that only managed agents are involved. The list returned by the SQL server is sorted according to the computer name (89 - 94). The list box is emptied once before it is filled to prevent entries from still being present (96 and 97).
312
313 The //SQL Query// function applies the SQL statement and writes all clients to the global string list (//LClients//) (line 99). Lines 101 - 107 fill the interface of the list box that is displayed to you as a user. The list box is filled with the computer names that were previously retrieved from the SQL query. The last two rows (106 and 107) release the previously created lists.
314 )))
315 |(% style="width:859px" %)**Row 110 - 141**|(% style="width:505px" %)
316 |(% style="width:859px" %){{code language="none"}}procedure GetClientCommands;
317 var
318 LSQL, LTemp : TStringList;
319 I : Integer;
320 begin
321
322 LSQL := TStringList.Create();
323 LTemp := TStringList.Create();
324 LSQL.Add('DECLARE @Search nvarchar(200) = ' + QuotedStr(EDCCSearch.Text) + ';')
325 LSQL.Add('SELECT DESCRIPTION, SCRIPTID');
326 LSQL.Add('FROM SYS_SCRIPTS');
327 LSQL.Add('WHERE HASCLIENTSCRIPT = 1');
328 LSQL.Add('AND State = 7');
329 LSQL.Add('AND DESCRIPTION LIKE @Search');
330 LSQL.Add('ORDER BY DESCRIPTION');
331
332 // Leeren der Listbox der ClientCommands
333 LBClientCommands.Clear();
334 LClientCommands.Clear();
335 // Ausführen des Statements zum Beziehen der ClientCommands aus der DB
336 SQLQueryEx(LSQL.Text,'','',LClientCommands,true,emOpen,30);
337
338 for I := 0 to (LClientCommands.Count-1) do
339 begin
340 LTemp.Commatext := EscapeValues(LClientCommands.Strings[i]);
341 LBClientCommands.Items.Add(LTemp.Values['DESCRIPTION']);
342 end
343
344 LSQL.Free();
345 LTemp.Free();
346 end;
347 {{/code}}|(% style="width:505px" %)(((
348 These rows (110 - 141) are used to fill the right box with the Client Commands entries by loading them from the SQL database and inserting them there. First, two lists are defined (116 and 117). To determine the Client Commands, an SQL Query is created in rows 119 - 124. Row 118 uses the search field of the interface to retrieve only Client Commands with this name from the database. Entering the wildcard "%" retrieves all Client Commands from the database, entering "Test_%" only retrieves all Client Commands that begin with "Test_" in their name.  (//LSQL.Add('DECLARE @Search nvarchar(200) = ' + QuotedStr(EDCCSearch.Text) + ';')).//
349
350 The list box and the global list of client commands are emptied via lines 127 and 128. The statement is then executed via the SQL query, whereby the retrieved client commands are written to the global string list (//LClientCommands//). Lines 132 - 136 fill the surface of the list box with the description (name) of the client command that was previously retrieved from the SQL query. The rows 138 and 139 release the functions again.
351 )))
352 |(% style="width:859px" %)**Row 142 - 151**|(% style="width:505px" %)
353 |(% style="width:859px" %){{code language="none"}}procedure FormActivate;
354 begin
355 LClients := TStringList.Create();
356 LClientCommands := TStringList.Create();
357
358 ResultMessages := TStringList.Create();
359 GetClients;
360 SetAESBConfig;
361 end;
362 {{/code}}|(% style="width:505px" %)//Procdure FormActivate// (rows 142 - 151) is called when the window is created. The global lists //LClients// and //LClientCommands// are created first (144 and 145). The //GetClients// method retrieves all Clients from the database and displays them in the interface (see upper function) (148). The //SetAESBConfig// function is called in row 149 and sets all variables that were previously set by you and that are necessary to communicate with the AESB (see function above).
363 |(% style="width:859px" %)**Row 152 - 160**|(% style="width:505px" %)
364 |(% style="width:859px" %){{code language="none"}}procedure OkButtonClick(Sender: TObject);
365 begin
366 LClients.Free();
367 LClientCommands.Free();
368
369 ResultMessages.Free();
370 CloseForm(0);
371 end;
372 {{/code}}|(% style="width:505px" %)(((
373 The function in rows 152 - 160 is called when the OK button is pressed. All lists are cleared so that there are no more entries in //LClients// or //LClientCommands//. Row 158 //CloseForm(0) //closes the form with the parameter 0.
374
375 {{aagon.infobox}}
376 You can enter any integer as a parameter in the brackets. By default, a -1 means that this block has failed. This number (-1) can be set when starting the Form Editor. If the CloseForm(-1) function is then called, this block will cause the Client Command to fail and no continuing Commands will be executed after this block.
377 {{/aagon.infobox}}
378 )))
379 |(% style="width:859px" %)**Row 161 - 169**|(% style="width:505px" %)
380 |(% style="width:859px" %){{code language="none"}}procedure CancelButtonClick(Sender: TObject);
381 begin
382 LClients.Free();
383 LClientCommands.Free();
384
385 ResultMessages.Free();
386 CloseForm(1);
387 end;
388 {{/code}}|(% style="width:505px" %)Rows 161 - 169 are called when the cancel button is pressed. As in the previous section, all lists are cleared and the //Closeform// (row 167) is filled with the parameter 1 in order to show a better distinction between the OK and Cancel button, whereby this value does not represent an error. This parameter can be used in the Client Command as the return value of the form to distinguish whether the OK or cancel button was pressed.
389 |(% style="width:859px" %)**Row 170 - 176**|(% style="width:505px" %)
390 |(% style="width:859px" %){{code language="none"}}procedure CBSureClick(Sender: TObject);
391 begin
392 if ((CBSure.Checked) AND (LBClients.ItemIndex > -1 ) AND (LBClientCommands.ItemIndex > -1 ))
393 then BtnSend.Enabled := True;
394 Else BtnSend.Enabled := False;
395 end;
396 {{/code}}|(% style="width:505px" %)(((
397 This line section is called when the //CBSure// checkbox is clicked ("I am sure"), which the user must enable before sending a Command. The process //procedure CBSureClick(Sender:TOBject//) (from row 170) ensures that the following conditions are met (171 - 175) and that the //Send Command// button is enabled as a result. The condition is:
398
399 If //CBSure (true)// (checkbox checked), a Client from the left box and a Client Command from the right box have been selected (ItemIndex must be larger than -1; so a selected item must be selected), then the Send Command button is enabled (//BtnSend.Enabled// :=True). Otherwise, the button is disabled on Else.
400 )))
401 |(% style="width:859px" %)**Row 177 - 194**|(% style="width:505px" %)
402 |(% style="width:859px" %){{code language="none"}}procedure BtnSendClick(Sender: TObject);
403 var
404 AESBMessage : String;
405 begin
406 AESBMessage := CreateMessageBody;
407 AddSICSConnectionV1(Protocol,Server,Port,Username,
408 Passwort,ConnectionTimeout,TargetConnectionVariable,false);
409 ConnectionString := GetVarContent('CONNECTION');
410 IResult := SICSPublishV1(ConnectionString, MessageID, VirtualRouter, RoutingKey, ExchangeType, Tag,
411 AESBMessage, CallbackVirtualRouter, CallbackRoutingKey, ResultMessages, AAckMessages, AResult, AErrorCode);
412 if (IResult = 0) then
413 begin
414 ShowMessage('Command has been send');
415 CBSure.Checked := false;
416 BtnSend.Enabled := false;
417 end;
418 Else Showmessage('An Error has occured: '+InttoStr(IResult));
419 end;
420 {{/code}}|(% style="width:505px" %)(((
421 The function procedure //BtnSendClick(Sender: TObject)// is defined in the following rows and then executed as soon as the user clicks on the button. The variable (AESBMessage), whose data type is a string, is declared (row 179).
422
423 The function //CreateMessageBody //is then called. In this function, the MessageBody is completely assembled once and returned as a return value. This return value is in turn inserted into the //AESBMessage// variable (row 181). The SICS connection is then created, which consists of the various parameters and the AddSICSConnectionV1 function. In line 183, the //ConnectionString// variable is filled with the //GetVarContent// function. The function retrieves the value from the client command variable with the name (parameter of the function) "Connection". Line 184 continues with the //IResult// variable, where the result of the function is saved as SICSPublishV1. The various parameters are sent to the AESB. This is followed by an if. then clause follows: The result (IResult) of the function is checked to see if the result is 0 and therefore there were no errors. The //ShowMessage// function is called, which opens a dialog box with the text "Command has been send" (line 188). In the next two lines, the properties "Checked" for the checkbox and "Enabled" for the button are set to //False//. This restores the objects to their original state. If an error has occurred, the Else part is executed (line 192) and a dialog "An Error has occured" is displayed, as well as the result of IResult (the error code).
424 )))
425
426 7. Once you have inserted or customised all the relevant information in the code, you can run the form from the quick selection bar using the //Start //button [[image:image-20240205143129-1.png]] (F9). Note that this is not only a test to check for any syntax, spelling or logic errors, but also to send client commands to an agent. The following image shows the finished form as it may appear in your system.
427
428 {{figure}}
429 (% style="text-align:center" %)
430 [[image:66_Client Command_Use Case Form Editor Design Ansicht_832.png]]
431
432 {{figureCaption}}
433 Completed Client Commands in the Custom Window
434 {{/figureCaption}}
435 {{/figure}}
436
437 8. Close the open windows (Custom Window and Form Editor). You will be returned to the Form Editor interface and its preview.
438
439 9. Check the value entered under //Script Return Value//. It should be the integer '-1'.
440
441 {{figure}}
442 (% style="text-align:center" %)
443 [[image:66_Use Case Client Commands_AESB Form Editor fertig_510.png]]
444
445 {{figureCaption}}
446 Form Editor preview
447 {{/figureCaption}}
448 {{/figure}}
449
450 10. Click //OK//.
451
452 ~11. Save the finished Client Command and close the editor.
453
454 {{figure}}
455 (% style="text-align:center" %)
456 [[image:66_Use Case Client Commands_AESB fertiges Script_1487.png]]
457
458 {{figureCaption}}
459 Client Command Editor: Sending a Client Command statically to a Client using the Form Editor via AESB
460 {{/figureCaption}}
461 {{/figure}}
462
463 == Running through the Client Command phases ==
464
465 Before the Client Command can be used, it must go through the [[Test>>doc:ACMP.65.ACMP-Solutions.Client Commands.Client Command testen.WebHome]], [[Synchronise>>doc:ACMP.65.ACMP-Solutions.Client Commands.Client Command synchronisieren.WebHome]], [[Release>>doc:ACMP.65.ACMP-Solutions.Client Commands.Client Command freigeben.WebHome]] und [[Execute>>doc:ACMP.65.ACMP-Solutions.Client Commands.Client Command ausführen.WebHome]] phases. It is then possible to send the Client Commands statically to a Client via the AESB using the Form Editor.
© Aagon GmbH 2025
Besuchen Sie unsere neue Aagon-Community