Tiny Server Inventory

Check-in [129cec8cc7]
Login

Check-in [129cec8cc7]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Transferred from Bitbucket
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 129cec8cc7f00d694b21ff5bbe9b1c77f38da3a0f271edaf7ba111840ffd4aba
User & Date: Cthulhux 2019-11-16 17:27:31
Context
2019-11-16
17:27
Added versions Leaf check-in: c466598341 user: Cthulhux tags: trunk
17:27
Transferred from Bitbucket check-in: 129cec8cc7 user: Cthulhux tags: trunk
17:21
initial empty check-in check-in: 596edda346 user: Cthulhux tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added AddNewServerForm.dfm.

















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
object AddServerForm: TAddServerForm
  Left = 0
  Top = 0
  BorderStyle = bsDialog
  Caption = 'Add A New Server'
  ClientHeight = 343
  ClientWidth = 344
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poMainFormCenter
  DesignSize = (
    344
    343)
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 15
    Width = 79
    Height = 13
    Caption = 'Displayed name:'
  end
  object Label2: TLabel
    Left = 7
    Top = 80
    Width = 68
    Height = 13
    Caption = 'IPv4 Address:'
  end
  object Label3: TLabel
    Left = 283
    Top = 79
    Width = 46
    Height = 13
    Caption = '(optional)'
  end
  object Label4: TLabel
    Left = 8
    Top = 112
    Width = 68
    Height = 13
    Caption = 'IPv6 Address:'
  end
  object Label5: TLabel
    Left = 283
    Top = 111
    Width = 46
    Height = 13
    Caption = '(optional)'
  end
  object Label6: TLabel
    Left = 8
    Top = 144
    Width = 90
    Height = 13
    Caption = 'Operating System:'
  end
  object Label7: TLabel
    Left = 283
    Top = 144
    Width = 46
    Height = 13
    Caption = '(optional)'
  end
  object Label8: TLabel
    Left = 8
    Top = 176
    Width = 49
    Height = 13
    Caption = 'Comment:'
  end
  object Label9: TLabel
    Left = 8
    Top = 48
    Width = 78
    Height = 13
    Caption = 'Primary Domain:'
  end
  object Label10: TLabel
    Left = 283
    Top = 47
    Width = 46
    Height = 13
    Caption = '(optional)'
  end
  object btnAddServer: TButton
    Left = 247
    Top = 310
    Width = 89
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'Add this server'
    Enabled = False
    TabOrder = 6
    OnClick = btnAddServerClick
  end
  object etNickname: TEdit
    Left = 109
    Top = 12
    Width = 212
    Height = 21
    Margins.Left = 8
    HideSelection = False
    TabOrder = 0
    TextHint = 'Enter an unique name for this server.'
    OnChange = etNicknameChange
  end
  object etIPv6: TEdit
    Left = 109
    Top = 109
    Width = 124
    Height = 21
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Consolas'
    Font.Style = []
    ParentFont = False
    ParentShowHint = False
    ShowHint = True
    TabOrder = 3
    TextHint = 'Enter IPv6 here.'
  end
  object etOS: TEdit
    Left = 109
    Top = 141
    Width = 164
    Height = 21
    ParentShowHint = False
    ShowHint = True
    TabOrder = 4
    TextHint = 'This server'#39's operating system.'
  end
  object etComment: TRichEdit
    Left = 109
    Top = 173
    Width = 220
    Height = 124
    Font.Charset = ANSI_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    ParentShowHint = False
    ScrollBars = ssBoth
    ShowHint = True
    TabOrder = 5
    Zoom = 100
  end
  object etIPv4: TEdit
    Left = 109
    Top = 77
    Width = 124
    Height = 21
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Consolas'
    Font.Style = []
    ParentFont = False
    ParentShowHint = False
    ShowHint = True
    TabOrder = 2
    TextHint = 'Enter IPv4 here.'
  end
  object etDomain: TEdit
    Left = 109
    Top = 44
    Width = 164
    Height = 21
    ParentShowHint = False
    ShowHint = True
    TabOrder = 1
    TextHint = 'This server'#39's primary domain.'
  end
  object FDQuery1: TFDQuery
    Connection = FDConnection1
    Left = 44
    Top = 192
  end
  object DataSource1: TDataSource
    DataSet = FDQuery1
    Left = 68
    Top = 248
  end
  object FDConnection1: TFDConnection
    Params.Strings = (
      'Database=.\TinyServerInventory.db'
      'OpenMode=ReadWrite'
      'DriverID=SQLite')
    Left = 12
    Top = 256
  end
end

Added AddNewServerForm.pas.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
unit AddNewServerForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, System.UITypes,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Mask, Vcl.ComCtrls,
  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,
  FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,
  FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf, FireDAC.Stan.Def,
  FireDAC.Stan.Pool, FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef,
  FireDAC.Stan.ExprFuncs, FireDAC.VCLUI.Wait, Data.DB, FireDAC.Comp.Client,
  FireDAC.Comp.DataSet;

type
  TAddServerForm = class(TForm)
    btnAddServer: TButton;
    Label1: TLabel;
    etNickname: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    etIPv6: TEdit;
    Label6: TLabel;
    etOS: TEdit;
    Label7: TLabel;
    Label8: TLabel;
    etComment: TRichEdit;
    FDQuery1: TFDQuery;
    DataSource1: TDataSource;
    FDConnection1: TFDConnection;
    etIPv4: TEdit;
    Label9: TLabel;
    etDomain: TEdit;
    Label10: TLabel;
    procedure etNicknameChange(Sender: TObject);
    procedure btnAddServerClick(Sender: TObject);
  end;

var
  AddServerForm: TAddServerForm;

const
  WM_TSIMessage = WM_USER + 1;

implementation

{$R *.dfm}

procedure TAddServerForm.btnAddServerClick(Sender: TObject);
var
  ExistingID: Integer;
begin
  // Eindeutigkeit des Anzeigenamens prüfen:
  ExistingID := FDConnection1.ExecSQLScalar
    ('SELECT id FROM servers WHERE Nickname = :name', [etNickname.Text]);
  if ExistingID > 0 then
  begin
    // Server existiert schon.
    MessageDlg('Server nicknames have to be unique (for now) - sorry!',
      mtInformation, [mbOK], 0);
  end
  else
  begin
    // Server hinzufügen:
    FDConnection1.ExecSQL
      ('INSERT INTO servers (Nickname, PrimaryDomain, IPv4, IPv6, OperatingSystem, Comment) VALUES (:nickname, :domain, :ipv4, :ipv6, :os, :comment)',
      [etNickname.Text, etDomain.Text, etIPv4.Text, etIPv6.Text, etOS.Text, etComment.Text]);

    // MainForm benachrichtigen (für UI-Updates):
    PostMessage(Application.MainForm.Handle, WM_TSIMessage, 0,
      DWORD(PChar('updatetree')));

    // Dialog schließen:
    Close;
  end;
end;

procedure TAddServerForm.etNicknameChange(Sender: TObject);
begin
  if Trim(etNickname.Text) = '' then
    btnAddServer.Enabled := false
  else
    btnAddServer.Enabled := true;
end;

end.

Added MainForm.dfm.









































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
object TSIForm: TTSIForm
  Left = 0
  Top = 0
  Caption = 'Tiny Server Inventory'
  ClientHeight = 446
  ClientWidth = 673
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  OnCreate = FormCreate
  DesignSize = (
    673
    446)
  PixelsPerInch = 96
  TextHeight = 13
  object lblNoServers: TLabel
    Left = 191
    Top = 8
    Width = 437
    Height = 270
    Anchors = [akLeft, akTop, akRight, akBottom]
    Caption = 'Please add a server to continue. :-)'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -75
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    WordWrap = True
  end
  object grpDetails: TGroupBox
    Left = 191
    Top = 8
    Width = 474
    Height = 407
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 3
    Visible = False
    StyleElements = [seFont, seClient]
    DesignSize = (
      474
      407)
    object Label1: TLabel
      Left = 10
      Top = 16
      Width = 79
      Height = 13
      Caption = 'Displayed name:'
    end
    object Label2: TLabel
      Left = 10
      Top = 82
      Width = 68
      Height = 13
      Caption = 'IPv4 Address:'
    end
    object Label3: TLabel
      Left = 10
      Top = 112
      Width = 68
      Height = 13
      Caption = 'IPv6 Address:'
    end
    object Label4: TLabel
      Left = 10
      Top = 179
      Width = 49
      Height = 13
      Caption = 'Comment:'
    end
    object Label8: TLabel
      Left = 10
      Top = 253
      Width = 113
      Height = 13
      Caption = 'Services on this server:'
    end
    object Label5: TLabel
      Left = 10
      Top = 144
      Width = 90
      Height = 13
      Caption = 'Operating System:'
    end
    object Label6: TLabel
      Left = 335
      Top = 82
      Width = 107
      Height = 13
      Caption = '(opens a cmd window)'
    end
    object Label7: TLabel
      Left = 335
      Top = 112
      Width = 107
      Height = 13
      Caption = '(opens a cmd window)'
    end
    object Label9: TLabel
      Left = 10
      Top = 48
      Width = 78
      Height = 13
      Caption = 'Primary Domain:'
    end
    object btnSaveChanges: TButton
      Left = 371
      Top = 379
      Width = 101
      Height = 25
      Anchors = [akRight, akBottom]
      Caption = 'save changes'
      Enabled = False
      TabOrder = 8
      OnClick = btnSaveChangesClick
    end
    object etNickname: TEdit
      Left = 135
      Top = 13
      Width = 330
      Height = 21
      Anchors = [akLeft, akTop, akRight]
      TabOrder = 0
      OnChange = etNicknameChange
    end
    object etIPv6: TEdit
      Left = 135
      Top = 110
      Width = 139
      Height = 21
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Consolas'
      Font.Style = []
      ParentFont = False
      ParentShowHint = False
      ShowHint = True
      TabOrder = 3
      OnChange = etIPv6Change
    end
    object etComment: TRichEdit
      Left = 135
      Top = 176
      Width = 329
      Height = 68
      Anchors = [akLeft, akTop, akRight]
      Font.Charset = ANSI_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      ParentFont = False
      TabOrder = 5
      Zoom = 100
      OnChange = etCommentChange
    end
    object btnAddService: TButton
      Left = 10
      Top = 272
      Width = 113
      Height = 25
      Caption = 'add a service'
      TabOrder = 7
      OnClick = btnAddServiceClick
    end
    object etOS: TEdit
      Left = 135
      Top = 142
      Width = 330
      Height = 21
      Anchors = [akLeft, akTop, akRight]
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Consolas'
      Font.Style = []
      ParentFont = False
      ParentShowHint = False
      ShowHint = True
      TabOrder = 4
      OnChange = etIPv6Change
    end
    object etIPv4: TEdit
      Left = 135
      Top = 80
      Width = 139
      Height = 21
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Consolas'
      Font.Style = []
      ParentFont = False
      ParentShowHint = False
      ShowHint = False
      TabOrder = 2
      OnChange = etIPv4Change
    end
    object btnPingIPv4: TButton
      Left = 280
      Top = 77
      Width = 49
      Height = 25
      Caption = 'Ping'
      Enabled = False
      TabOrder = 9
      OnClick = btnPingIPv4Click
    end
    object btnPingIPv6: TButton
      Left = 280
      Top = 107
      Width = 49
      Height = 25
      Caption = 'Ping'
      Enabled = False
      TabOrder = 10
      OnClick = btnPingIPv6Click
    end
    object vleServices: TStringGrid
      Left = 135
      Top = 253
      Width = 343
      Height = 120
      ColCount = 3
      FixedCols = 0
      RowCount = 2
      Options = [goVertLine, goHorzLine, goRangeSelect, goColSizing, goEditing, goTabs]
      TabOrder = 6
      ColWidths = (
        64
        64
        64)
      RowHeights = (
        24
        24)
    end
    object etDomain: TEdit
      Left = 135
      Top = 46
      Width = 164
      Height = 21
      Anchors = [akLeft, akTop, akRight]
      TabOrder = 1
      OnChange = etDomainChange
    end
    object btnPingDomain: TButton
      Left = 305
      Top = 42
      Width = 49
      Height = 25
      Anchors = [akTop, akRight]
      Caption = 'Ping'
      Enabled = False
      TabOrder = 11
      OnClick = btnPingDomainClick
    end
    object btnOpenInWeb: TButton
      Left = 360
      Top = 42
      Width = 106
      Height = 25
      Anchors = [akTop, akRight]
      Caption = 'Open as Website'
      Enabled = False
      TabOrder = 12
      OnClick = btnOpenInWebClick
    end
  end
  object TreeView1: TTreeView
    Left = 8
    Top = 8
    Width = 177
    Height = 373
    Anchors = [akLeft, akTop, akBottom]
    Indent = 19
    TabOrder = 0
    StyleElements = [seFont, seClient]
  end
  object btnAddConn: TButton
    Left = 8
    Top = 387
    Width = 81
    Height = 25
    Anchors = [akLeft, akBottom]
    Caption = 'add'
    TabOrder = 1
    OnClick = btnAddConnClick
  end
  object btnRemoveConn: TButton
    Left = 103
    Top = 388
    Width = 82
    Height = 25
    Anchors = [akLeft, akBottom]
    Caption = 'remove'
    Enabled = False
    TabOrder = 2
    OnClick = btnRemoveConnClick
  end
  object btnExit: TButton
    Left = 590
    Top = 421
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'exit'
    TabOrder = 4
    OnClick = btnExitClick
  end
  object btnExportList: TButton
    Left = 8
    Top = 421
    Width = 177
    Height = 25
    Anchors = [akLeft, akBottom]
    Caption = 'export server list as ASCII text'
    TabOrder = 5
    OnClick = btnExportListClick
  end
  object MainMenu1: TMainMenu
    Left = 16
    Top = 24
    object N1: TMenuItem
      Caption = '?'
      object mnuNANY: TMenuItem
        Caption = 'N.A.N.Y. 2017'
        OnClick = mnuNANYClick
      end
      object N2: TMenuItem
        Caption = '-'
      end
      object mnuLicense: TMenuItem
        Caption = 'License'
        OnClick = mnuLicenseClick
      end
      object mnuAbout: TMenuItem
        Caption = 'About'
        OnClick = mnuAboutClick
      end
    end
  end
  object FDConnection1: TFDConnection
    Params.Strings = (
      'Database=.\TinyServerInventory.db'
      'OpenMode=ReadWrite'
      'DriverID=SQLite')
    Left = 64
    Top = 104
  end
  object FDQuery1: TFDQuery
    Connection = FDConnection1
    Left = 16
    Top = 80
  end
  object DataSource1: TDataSource
    DataSet = FDQuery1
    Left = 72
    Top = 32
  end
  object IdHTTP1: TIdHTTP
    AllowCookies = True
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.ContentLength = -1
    Request.ContentRangeEnd = -1
    Request.ContentRangeStart = -1
    Request.ContentRangeInstanceLength = -1
    Request.Accept = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
    Request.BasicAuthentication = False
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
    Request.Ranges.Units = 'bytes'
    Request.Ranges = <>
    HTTPOptions = [hoForceEncodeParams]
    Left = 56
    Top = 192
  end
  object FDQuery2: TFDQuery
    Connection = FDConnection1
    Left = 24
    Top = 88
  end
end

Added MainForm.pas.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.UITypes,
  System.Variants, System.Classes, Vcl.Graphics, Generics.Collections,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ComCtrls,
  FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLiteDef, FireDAC.Stan.Intf,
  FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Stan.Option, FireDAC.Stan.Error,
  FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Stan.Async, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet,
  FireDAC.Comp.Client, Vcl.StdCtrls, ShellApi, IdHttp, Vcl.ExtCtrls, Vcl.Mask,
  Vcl.Grids, Vcl.ValEdit, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient,
  // Eigene Klassen:
  AddNewServerForm, MsgHelpers;

const
  TSIVersion = '1612.2';
  TSIDatabaseFile = 'TinyServerInventory.db';
  TSISchema = 1;
  ExportFileName = 'Serverlist.txt';
  WM_TSIMessage = WM_USER + 1;

type
  TTSIForm = class(TForm)
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    mnuAbout: TMenuItem;
    TreeView1: TTreeView;
    FDConnection1: TFDConnection;
    FDQuery1: TFDQuery;
    DataSource1: TDataSource;
    btnAddConn: TButton;
    btnRemoveConn: TButton;
    N2: TMenuItem;
    mnuNANY: TMenuItem;
    grpDetails: TGroupBox;
    Label1: TLabel;
    btnSaveChanges: TButton;
    etNickname: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    etIPv6: TEdit;
    Label4: TLabel;
    etComment: TRichEdit;
    Label8: TLabel;
    btnAddService: TButton;
    Label5: TLabel;
    etOS: TEdit;
    mnuLicense: TMenuItem;
    IdHTTP1: TIdHTTP;
    btnExit: TButton;
    etIPv4: TEdit;
    btnPingIPv4: TButton;
    btnPingIPv6: TButton;
    Label6: TLabel;
    Label7: TLabel;
    vleServices: TStringGrid;
    Label9: TLabel;
    etDomain: TEdit;
    btnPingDomain: TButton;
    btnOpenInWeb: TButton;
    btnExportList: TButton;
    FDQuery2: TFDQuery;
    lblNoServers: TLabel;
    procedure mnuAboutClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnAddConnClick(Sender: TObject);
    procedure btnRemoveConnClick(Sender: TObject);
    procedure mnuNANYClick(Sender: TObject);
    procedure btnAddServiceClick(Sender: TObject);
    procedure etNicknameChange(Sender: TObject);
    procedure etIPv4Change(Sender: TObject);
    procedure etIPv6Change(Sender: TObject);
    procedure etCommentChange(Sender: TObject);
    procedure vleServicesSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: string);
    procedure btnSaveChangesClick(Sender: TObject);
    procedure mnuLicenseClick(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure btnPingIPv4Click(Sender: TObject);
    procedure btnPingIPv6Click(Sender: TObject);
    procedure btnPingDomainClick(Sender: TObject);
    procedure btnOpenInWebClick(Sender: TObject);
    procedure etDomainChange(Sender: TObject);
    procedure btnExportListClick(Sender: TObject);
  private
    procedure TreeView1Click(Sender: TObject);
    procedure receiveMessage(var msg: TMessage); message WM_TSIMessage;
  end;

var
  AboutText: string;
  ServerList: TDictionary<Integer, string>;
  ActiveSelection: TPair<Integer, string>;

  LicenseText: string;
  IdHttp: TIdHTTP;

  TSIForm: TTSIForm;
  AddServerForm: TAddServerForm;
  RootNode: TTreeNode;

implementation

{$R *.dfm}

procedure CheckDatabase();
var
  TempSchema: Integer;
begin
  // Datenbank auf Vorhandensein prüfen
  if not fileexists(TSIDatabaseFile) then
  begin
    MessageDlgWithTitle('They took our database!', 'The database file ' +
      TSIDatabaseFile + ' seems to be missing.' + sLineBreak +
      'Sorry, I cannot continue.', mtError, [mbOK], 0);
    Application.Terminate;
  end;

  // DB-Schema abgleichen
  TempSchema := TSIForm.FDConnection1.ExecSQLScalar
    ('SELECT schema_ver FROM meta');
  if TempSchema <> TSISchema then
  begin
    MessageDlgWithTitle('Wrong schema version!',
      'The database schema version is incorrect. Sorry, I cannot continue.',
      mtError, [mbOK], 0);
    Application.Terminate;
  end;
end;

function DBResultOrNotSet(query: TFDQuery; Param: string): string;
begin
  // Abkürzung: Hole Queryparameter - wenn leer oder NULL, gib "(not set)" zurück.
  if (query[Param] = NULL) or (query[Param] = '') then
    Result := '(not set)'
  else
    Result := query[Param];
end;

procedure PopulateTreeBar();
begin
  // DB initialisieren
  TSIForm.FDQuery1.SQL.Text :=
    'SELECT id, Nickname FROM servers ORDER BY Nickname ASC';
  TSIForm.FDQuery1.Open;

  ServerList := TDictionary<Integer, string>.Create(); // init.

  TSIForm.TreeView1.Items.Clear;

  RootNode := TSIForm.TreeView1.Items.Add(nil, 'My Servers');

  while (not TSIForm.FDQuery1.Eof) do
  begin
    // über die Ergebnisse iterieren
    ServerList.Add(strtoint(TSIForm.FDQuery1['id']),
      TSIForm.FDQuery1['Nickname']);
    TSIForm.TreeView1.Items.AddChild(RootNode, TSIForm.FDQuery1['Nickname']);
    TSIForm.FDQuery1.Next;
  end;

  // Gibt es keine Server, dann sollte ein Infotext angezeigt und
  // der Export verunmöglicht werden.
  if TSIForm.FDQuery1.RowsAffected > 0 then
  begin
    TSIForm.lblNoServers.Visible := false;
    TSIForm.btnExportList.Enabled := true;
  end
  else
  begin
    TSIForm.lblNoServers.Visible := true;
    TSIForm.btnExportList.Enabled := false;
  end;

  TSIForm.FDQuery1.Close;

  TSIForm.TreeView1.FullExpand; // alles ausklappen
  TSIForm.TreeView1.OnClick := TSIForm.TreeView1Click; // On-Click-Handler
end;

function GetNodeByCaption(NodeCaption: string): TTreeNode;
var
  i: Integer;
begin
  // Gibt den TreeNode mit der übergebenen Beschriftung zurück.
  Result := nil;
  for i := 0 to TSIForm.TreeView1.Items.Count - 1 do
  begin
    if (TSIForm.TreeView1.Items[i].Text = NodeCaption) then
      Result := TSIForm.TreeView1.Items[i];
    Break;
  end;
end;

procedure DeleteServerItem(id: Integer);
begin
  TSIForm.FDConnection1.ExecSQL('DELETE FROM servers WHERE id = :id',
    [id.ToString]);

  PopulateTreeBar;
end;

procedure TTSIForm.receiveMessage(var msg: TMessage);
var
  txt: PChar;
begin
  txt := PChar(msg.lParam);
  msg.Result := 1;
  if txt = 'updatetree' then
    PopulateTreeBar;
end;

procedure TTSIForm.btnAddConnClick(Sender: TObject);
begin
  AddServerForm := TAddServerForm.Create(nil);
  try
    AddServerForm.ShowModal;
  finally
    AddServerForm.Free;
  end;
end;

procedure TTSIForm.btnAddServiceClick(Sender: TObject);
begin
  vleServices.RowCount := vleServices.RowCount + 1;
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;
end;

procedure TTSIForm.btnExitClick(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TTSIForm.btnExportListClick(Sender: TObject);
var
  OutputString: string;
  OutputFile: TextFile;
  IndentationOuter, IndentationInner: string;
  i, j: Integer;
begin
  // Export als Textdatei
  OutputString := 'Servers' + sLineBreak;

  FDQuery1.SQL.Text :=
    'SELECT id, Nickname, PrimaryDomain, IPv4, IPv6, OperatingSystem, Comment FROM servers ORDER BY Nickname ASC';
  FDQuery1.Open;

  i := FDQuery1.RowsAffected - 1; // wird bis 0 runtergezählt

  while not FDQuery1.Eof do
  begin
    if i > 0 then
      // Es gibt ein nächstes Ergebnis. Zeichne Baum.
      IndentationOuter := ' |'
    else
      IndentationOuter := '  ';

    OutputString := OutputString + ' ├── ' + FDQuery1['Nickname'] + sLineBreak;
    OutputString := OutputString + IndentationOuter +
      '    ├── Primary Domain:   ';
    OutputString := OutputString + DBResultOrNotSet(FDQuery1, 'PrimaryDomain');
    OutputString := OutputString + sLineBreak;

    OutputString := OutputString + IndentationOuter +
      '    ├── IPv4 Address:     ';
    OutputString := OutputString + DBResultOrNotSet(FDQuery1, 'IPv4');
    OutputString := OutputString + sLineBreak;

    OutputString := OutputString + IndentationOuter +
      '    ├── IPv6 Address:     ';
    OutputString := OutputString + DBResultOrNotSet(FDQuery1, 'IPv6');
    OutputString := OutputString + sLineBreak;

    OutputString := OutputString + IndentationOuter +
      '    ├── Operating System: ';
    OutputString := OutputString + DBResultOrNotSet(FDQuery1,
      'OperatingSystem');
    OutputString := OutputString + sLineBreak;

    OutputString := OutputString + IndentationOuter +
      '    ├── Comment:          ';
    OutputString := OutputString + DBResultOrNotSet(FDQuery1, 'Comment');
    OutputString := OutputString + sLineBreak;

    OutputString := OutputString + IndentationOuter + '    └── Services';

    FDQuery2.SQL.Text :=
      'SELECT Name, Port, Comment FROM services WHERE Server=:id ORDER BY Name ASC';
    FDQuery2.ParamByName('id').Value := FDQuery1['id'];
    FDQuery2.Open;

    if FDQuery2.RowsAffected = 0 then
      OutputString := OutputString + ':         (not set)' + sLineBreak
    else
    begin
      OutputString := OutputString + sLineBreak;

      j := FDQuery2.RowsAffected - 1; // wird bis 0 runtergezählt

      while not FDQuery2.Eof do
      begin
        if j > 0 then
          // Es gibt ein nächstes Ergebnis. Zeichne Baum.
          IndentationInner := '        |'
        else
          IndentationInner := '         ';

        OutputString := OutputString + '        ├── Name: ' + FDQuery2['Name'] +
          sLineBreak;

        OutputString := OutputString + IndentationInner + '    ├── Port:      ';
        OutputString := OutputString + DBResultOrNotSet(FDQuery2, 'Port');
        OutputString := OutputString + sLineBreak;

        OutputString := OutputString + IndentationInner + '    └── Comment:   ';
        OutputString := OutputString + DBResultOrNotSet(FDQuery2, 'Comment');
        OutputString := OutputString + sLineBreak;

        // Abstand zwischen zwei Services
        OutputString := OutputString + IndentationInner + sLineBreak;

        j := j - 1;

        FDQuery2.Next;
      end;
    end;

    FDQuery2.Close;

    // Abstand zwischen zwei Servern
    OutputString := OutputString + IndentationOuter + sLineBreak;

    i := i - 1;

    FDQuery1.Next;
  end;
  FDQuery1.Close;

  AssignFile(OutputFile, ExportFileName);
  ReWrite(OutputFile);
  WriteLn(OutputFile, OutputString);
  CloseFile(OutputFile);

  MessageDlgWithTitle('Complete!',
    'A list of your servers has been exported as ' + ExportFileName + '.' +
    sLineBreak +
    'The file will be opened in your default text editor for your convenience.',
    mtInformation, [mbOK], 0);
  ShellExecute(Handle, 'open', PChar(ExportFileName), nil, nil, SW_SHOW);
end;

procedure TTSIForm.btnOpenInWebClick(Sender: TObject);
var
  URL: String;
begin
  URL := etDomain.Text;
  if not LowerCase(URL).StartsWith('http') then
    URL := 'http://' + URL;

  ShellExecute(Handle, 'open', PChar(URL), nil, nil, SW_SHOW);
end;

procedure TTSIForm.btnPingDomainClick(Sender: TObject);
begin
  ShellExecute(Handle, nil, PChar('cmd.exe'),
    PChar('/C ping -t -4 ' + etDomain.Text), nil, SW_SHOW);
end;

procedure TTSIForm.btnPingIPv4Click(Sender: TObject);
begin
  ShellExecute(Handle, nil, PChar('cmd.exe'),
    PChar('/C ping -t -4 ' + etIPv4.Text), nil, SW_SHOW);
end;

procedure TTSIForm.btnPingIPv6Click(Sender: TObject);
begin
  ShellExecute(Handle, nil, PChar('cmd.exe'),
    PChar('/C ping -t -4 ' + etIPv6.Text), nil, SW_SHOW);
end;

procedure TTSIForm.btnRemoveConnClick(Sender: TObject);
var
  buttonSelected: Integer;
begin
  buttonSelected := MessageDlgWithTitle('Confirmation',
    'Do you really intend to delete the server named "' +
    TreeView1.Selected.Text + '" from your database?', mtConfirmation,
    [mbYes, mbNo], 0);

  if buttonSelected = mrYes then
  begin
    DeleteServerItem(ActiveSelection.Key);

    // Durch das Löschen ist kein Eintrag mehr ausgewählt. UI anpassen.
    btnRemoveConn.Enabled := false;
    grpDetails.Visible := false;
  end;
end;

procedure TTSIForm.btnSaveChangesClick(Sender: TObject);
var
  i: Integer;
begin
  // Aktuellen Server wegspeichern :-)
  // 1. Metadaten:
  FDConnection1.ExecSQL
    ('UPDATE servers SET Nickname=:nick, PrimaryDomain=:domain, IPv4=:ipv4, IPv6=:ipv6, OperatingSystem=:os, Comment=:comment WHERE id = :id',
    [etNickname.Text, etDomain.Text, etIPv4.Text, etIPv6.Text, etOS.Text,
    etComment.Text, ActiveSelection.Key]);

  // 2. Services:
  FDConnection1.ExecSQL('DELETE FROM services WHERE Server=:id',
    [ActiveSelection.Key]);
  for i := 1 to vleServices.RowCount - 1 do
  begin
    // Jede Zeile als Service hinzufügen, sofern ein Name gesetzt ist.
    if vleServices.Rows[i].Strings[0] <> '' then
    begin
      FDQuery1.SQL.Text :=
        'INSERT INTO services (Name, Port, Comment, Server) VALUES (:name, :port, :comment, :server)';
      FDQuery1.ParamByName('name').Value := vleServices.Rows[i].Strings[0];
      FDQuery1.ParamByName('port').Value := vleServices.Rows[i].Strings[1];
      FDQuery1.ParamByName('comment').Value := vleServices.Rows[i].Strings[2];
      FDQuery1.ParamByName('server').Value := ActiveSelection.Key;
      FDQuery1.ExecSQL;
    end;
  end;

  // Liste aktualisieren:
  PopulateTreeBar;

  // Element im Baum neu fokussieren:
  TreeView1.Selected := GetNodeByCaption(etNickname.Text);
end;

procedure TTSIForm.etCommentChange(Sender: TObject);
begin
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;
end;

procedure TTSIForm.etDomainChange(Sender: TObject);
begin
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;

  if Trim(etDomain.Text) <> '' then
  begin
    btnPingDomain.Enabled := true;
    btnOpenInWeb.Enabled := true;
  end
  else
  begin
    btnPingDomain.Enabled := false;
    btnOpenInWeb.Enabled := false;
  end;
end;

procedure TTSIForm.etIPv4Change(Sender: TObject);
begin
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;

  if Trim(etIPv4.Text) <> '' then
    btnPingIPv4.Enabled := true
  else
    btnPingIPv4.Enabled := false;
end;

procedure TTSIForm.etIPv6Change(Sender: TObject);
begin
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;

  if Trim(etIPv6.Text) <> '' then
    btnPingIPv6.Enabled := true
  else
    btnPingIPv6.Enabled := false;
end;

procedure TTSIForm.etNicknameChange(Sender: TObject);
begin
  if Trim(etNickname.Text) = '' then
    btnSaveChanges.Enabled := false
  else
    btnSaveChanges.Enabled := true;
end;

procedure TTSIForm.FormCreate(Sender: TObject);
begin
  CheckDatabase;
  PopulateTreeBar;

  vleServices.Cells[0, 0] := 'Name';
  vleServices.Cells[1, 0] := 'Port';
  vleServices.Cells[2, 0] := 'Comment';

  vleServices.Options := vleServices.Options + [goAlwaysShowEditor];
  vleServices.ColWidths[0] := 135;
  vleServices.ColWidths[2] := 120;
end;

procedure TTSIForm.mnuAboutClick(Sender: TObject);
begin
  // About
  AboutText := 'This is the Tiny Server Inventory application.' + sLineBreak +
    'Version: ' + TSIVersion + sLineBreak + sLineBreak +
    'Licensed under the terms of the WTFPLv2.' + sLineBreak +
    'http://wtfpl.net/txt/copying/' + sLineBreak + sLineBreak +
    'NANY 2017 build for DonationCoder.com.';
  if Random(100) > 85 then
    AboutText := AboutText + sLineBreak + sLineBreak + 'Linux sucks.';

  MessageDlgWithTitle('Ohai!', AboutText, mtInformation, [mbOK], 0);
end;

procedure TTSIForm.mnuLicenseClick(Sender: TObject);
begin
  IdHttp := TIdHTTP.Create(nil);
  try
    LicenseText := IdHttp.Get('http://www.wtfpl.net/txt/copying/');
    MessageDlgWithTitle('WTFPL license', LicenseText, mtInformation, [mbOK], 0);
  finally
    IdHttp.Free;
  end;
end;

procedure TTSIForm.mnuNANYClick(Sender: TObject);
begin
  ShellExecute(Handle, 'open',
    'http://www.donationcoder.com/forum/index.php?topic=43325.0', nil,
    nil, SW_SHOW);
end;

procedure TTSIForm.TreeView1Click(Sender: TObject);
var
  TempPair: TPair<Integer, string>;
begin
  // Klick auf einen Eintrag im Baum. Oder den Baum selbst.
  if (TreeView1.Selected.AbsoluteIndex = 0) or (TreeView1.Selected = nil) then
  begin
    // Es wurde der Ursprungsknoten ausgewählt.
    btnRemoveConn.Enabled := false;
    grpDetails.Visible := false;
  end
  else
  begin
    // Es wurde ein Kindknoten ausgewählt.
    // ActiveSelection zuweisen:
    ActiveSelection.Value := TreeView1.Selected.Text;
    // ID suchen:
    for TempPair in ServerList do
      if TempPair.Value = ActiveSelection.Value then
      begin
        // Nicknamen sind einheitlich, aktuelle ID also = End-ID.
        ActiveSelection.Key := TempPair.Key;
        Break;
      end;

    // Editfelder befüllen:
    FDQuery1.SQL.Text :=
      'SELECT Nickname, PrimaryDomain, IPv4, IPv6, OperatingSystem, Comment FROM servers WHERE id=:id';
    FDQuery1.ParamByName('id').Value := ActiveSelection.Key;
    FDQuery1.Open;

    if FDQuery1['Nickname'] <> NULL then
      etNickname.Text := FDQuery1['Nickname'];

    if FDQuery1['PrimaryDomain'] <> NULL then
      etDomain.Text := FDQuery1['PrimaryDomain'];

    if FDQuery1['IPv4'] <> NULL then
      etIPv4.Text := FDQuery1['IPv4'];

    if FDQuery1['IPv6'] <> NULL then
      etIPv6.Text := FDQuery1['IPv6'];

    if FDQuery1['OperatingSystem'] <> NULL then
      etOS.Text := FDQuery1['OperatingSystem'];

    if FDQuery1['Comment'] <> NULL then
      etComment.Text := FDQuery1['Comment'];

    if Trim(etIPv4.Text) <> '' then
      btnPingIPv4.Enabled := true
    else
      btnPingIPv4.Enabled := false;

    if Trim(etIPv6.Text) <> '' then
      btnPingIPv6.Enabled := true
    else
      btnPingIPv6.Enabled := false;

    if Trim(etDomain.Text) <> '' then
    begin
      btnPingDomain.Enabled := true;
      btnOpenInWeb.Enabled := true;
    end
    else
    begin
      btnPingDomain.Enabled := false;
      btnOpenInWeb.Enabled := false;
    end;

    FDQuery1.Close;

    // Serviceliste laden:
    FDQuery1.SQL.Text :=
      'SELECT Name, Port, Comment FROM services WHERE Server=:id ORDER BY Name ASC';
    FDQuery1.ParamByName('id').Value := ActiveSelection.Key;
    FDQuery1.Open;

    vleServices.RowCount := 1;
    if FDQuery1.RowsAffected = 0 then
    // Dieser Server hat keine Services.
    begin
      vleServices.Cells[0, 1] := '';
      vleServices.Cells[1, 1] := '';
      vleServices.Cells[2, 1] := '';
    end
    else
    begin
      while not FDQuery1.Eof do
      begin
        // StringGrid füllen:
        vleServices.RowCount := vleServices.RowCount + 1;
        if FDQuery1['Name'] <> NULL then
          vleServices.Cells[0, vleServices.RowCount - 1] := FDQuery1['Name'];
        if FDQuery1['Port'] <> NULL then
          vleServices.Cells[1, vleServices.RowCount - 1] := FDQuery1['Port'];
        if FDQuery1['Comment'] <> NULL then
          vleServices.Cells[2, vleServices.RowCount - 1] := FDQuery1['Comment'];
        FDQuery1.Next;
      end;
    end;
    FDQuery1.Close;

    if vleServices.RowCount = 1 then
      vleServices.RowCount := 2;
    vleServices.FixedRows := 1;

    // Entfernen-Button aktivieren:
    btnRemoveConn.Enabled := true;
    grpDetails.Visible := true;
  end;
end;

procedure TTSIForm.vleServicesSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: string);
begin
  if Trim(etNickname.Text) <> '' then
    btnSaveChanges.Enabled := true;
end;

end.

Added MsgHelpers.pas.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
unit MsgHelpers;

interface

uses Vcl.Dialogs, Vcl.Forms;

// Als public im Interface definieren:
function MessageDlgWithTitle(const Title: String; const Msg: string;
  DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;

implementation

function MessageDlgWithTitle(const Title: String; const Msg: string;
  DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
begin
  // Zentrierter MessageDlg mit einstellbarem Titel
  with CreateMessageDialog(Msg, DlgType, Buttons) do
    try
      Caption := Title;
      HelpContext := HelpCtx;
      HelpFile := '';
      Position := poMainFormCenter;
      result := ShowModal;
    finally
      Free;
    end;

end;

end.

Added README.md.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
# Tiny Server Inventory

A Delphi application to keep track of your servers and services.

## Made for NANY 2017.

See [http://www.donationcoder.com/forum/index.php?topic=43325.0](DonationCoder.com) for information.

## Downloads

See the *Versions* folder for .rar archives.

Added TinyServerInventory.db.

cannot compute difference between binary files

Added TinyServerInventory.dpr.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
program TinyServerInventory;

uses
  Vcl.Forms,
  Vcl.Themes,
  Vcl.Styles,
  MainForm in 'MainForm.pas' {TSIForm},
  AddNewServerForm in 'AddNewServerForm.pas' {AddServerForm},
  MsgHelpers in 'MsgHelpers.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TTSIForm, TSIForm);
  Application.CreateForm(TAddServerForm, AddServerForm);
  TStyleManager.TrySetStyle('Obsidian');
  Application.Run;
end.

Added TinyServerInventory.dproj.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>{BF942DBC-5725-4C3C-907E-0097EEA175DF}</ProjectGuid>
        <ProjectVersion>18.1</ProjectVersion>
        <FrameworkType>VCL</FrameworkType>
        <MainSource>TinyServerInventory.dpr</MainSource>
        <Base>True</Base>
        <Config Condition="'$(Config)'==''">Release</Config>
        <Platform Condition="'$(Platform)'==''">Win64</Platform>
        <TargetedPlatforms>2</TargetedPlatforms>
        <AppType>Application</AppType>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
        <Base_Win32>true</Base_Win32>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
        <Base_Win64>true</Base_Win64>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
        <Cfg_1>true</Cfg_1>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
        <Cfg_1_Win32>true</Cfg_1_Win32>
        <CfgParent>Cfg_1</CfgParent>
        <Cfg_1>true</Cfg_1>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
        <Cfg_1_Win64>true</Cfg_1_Win64>
        <CfgParent>Cfg_1</CfgParent>
        <Cfg_1>true</Cfg_1>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
        <Cfg_2>true</Cfg_2>
        <CfgParent>Base</CfgParent>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
        <Cfg_2_Win32>true</Cfg_2_Win32>
        <CfgParent>Cfg_2</CfgParent>
        <Cfg_2>true</Cfg_2>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
        <Cfg_2_Win64>true</Cfg_2_Win64>
        <CfgParent>Cfg_2</CfgParent>
        <Cfg_2>true</Cfg_2>
        <Base>true</Base>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base)'!=''">
        <Custom_Styles>Obsidian|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Obsidian.vsf</Custom_Styles>
        <Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
        <SanitizedProjectName>TinyServerInventory</SanitizedProjectName>
        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
        <DCC_E>false</DCC_E>
        <DCC_N>false</DCC_N>
        <DCC_S>false</DCC_S>
        <DCC_F>false</DCC_F>
        <DCC_K>false</DCC_K>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win32)'!=''">
        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;JvGlobus;FireDACADSDriver;JvPluginSystem;DBXMSSQLDriver;JvMM;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;JvBands;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;JvJans;JvNet;inetdb;JvAppFrm;FmxTeeUI;emsedge;JvDotNetCtrls;FireDACIBDriver;fmx;fmxdae;vclib;JvWizards;FireDACDBXDriver;dbexpress;IndyCore;vclx;JvPageComps;dsnap;DataSnapCommon;emsclient;FireDACCommon;JvDB;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;JclDeveloperTools;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;JvCmp;JvHMI;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;JvCustom;vcl;DBXSybaseASEDriver;IndyIPServer;JvXPCtrls;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;Jcl;JvCore;emshosting;JvCrypt;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;JvDlgs;JvRuntimeDesign;ibxpress;Tee;JvManagedThreads;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;JvTimeFramework;DBXSybaseASADriver;CustomIPTransport;vcldsnap;JvSystem;JvStdCtrls;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;JvDocking;dbxcds;VclSmp;JvPascalInterpreter;adortl;FireDACODBCDriver;JclVcl;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;JvControls;JvPrintPreview;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
        <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
        <VerInfo_Locale>1033</VerInfo_Locale>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Base_Win64)'!=''">
        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
        <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1)'!=''">
        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
        <DCC_DebugDCUs>true</DCC_DebugDCUs>
        <DCC_Optimize>false</DCC_Optimize>
        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
        <DCC_RemoteDebug>true</DCC_RemoteDebug>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
        <AppEnableHighDPI>true</AppEnableHighDPI>
        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
        <DCC_RemoteDebug>false</DCC_RemoteDebug>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
        <AppEnableHighDPI>true</AppEnableHighDPI>
        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2)'!=''">
        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
        <DCC_DebugInformation>0</DCC_DebugInformation>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
        <AppEnableHighDPI>true</AppEnableHighDPI>
        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
        <Icon_MainIcon>icon.ico</Icon_MainIcon>
        <DCC_ExeOutput>.</DCC_ExeOutput>
        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
        <AppEnableHighDPI>true</AppEnableHighDPI>
        <VerInfo_Locale>1033</VerInfo_Locale>
        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
    </PropertyGroup>
    <ItemGroup>
        <DelphiCompile Include="$(MainSource)">
            <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="MainForm.pas">
            <Form>TSIForm</Form>
            <FormType>dfm</FormType>
        </DCCReference>
        <DCCReference Include="AddNewServerForm.pas">
            <Form>AddServerForm</Form>
            <FormType>dfm</FormType>
        </DCCReference>
        <DCCReference Include="MsgHelpers.pas"/>
        <BuildConfiguration Include="Release">
            <Key>Cfg_2</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
        <BuildConfiguration Include="Base">
            <Key>Base</Key>
        </BuildConfiguration>
        <BuildConfiguration Include="Debug">
            <Key>Cfg_1</Key>
            <CfgParent>Base</CfgParent>
        </BuildConfiguration>
    </ItemGroup>
    <ProjectExtensions>
        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
        <Borland.ProjectType>Application</Borland.ProjectType>
        <BorlandProject>
            <Delphi.Personality>
                <Source>
                    <Source Name="MainSource">TinyServerInventory.dpr</Source>
                </Source>
                <Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dcloffice2k240.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
                    <Excluded_Packages Name="$(BDSBIN)\dclofficexp240.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
                </Excluded_Packages>
            </Delphi.Personality>
            <Deployment Version="3">
                <DeployFile LocalName="TinyServerInventory.exe" Configuration="Release" Class="ProjectOutput">
                    <Platform Name="Win64">
                        <RemoteName>TinyServerInventory.exe</RemoteName>
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="Win32\Debug\TinyServerInventory.exe" Configuration="Debug" Class="ProjectOutput">
                    <Platform Name="Win32">
                        <RemoteName>TinyServerInventory.exe</RemoteName>
                        <Overwrite>true</Overwrite>
                    </Platform>
                </DeployFile>
                <DeployClass Name="DependencyModule">
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                        <Extensions>.dll;.bpl</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXResource">
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\Resources</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidClassesDexFile">
                    <Platform Name="Android">
                        <RemoteDir>classes</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AdditionalDebugSymbols">
                    <Platform Name="Win32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch768">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon144">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidLibnativeMipsFile">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\mips</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Required="true" Name="ProjectOutput">
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="Linux64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="DependencyFramework">
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.framework</Extensions>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch640">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch1024">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSDeviceDebug">
                    <Platform Name="iOSDevice64">
                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch320">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSInfoPList">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidLibnativeArmeabiFile">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="DebugSymbols">
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch1536">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage470">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-normal</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon96">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage640">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-large</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPhone_Launch640x1136">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSEntitlements">
                    <Platform Name="iOSDevice64">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon72">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-hdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidGDBServer">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXInfoPList">
                    <Platform Name="OSX32">
                        <RemoteDir>Contents</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectOSXEntitlements">
                    <Platform Name="OSX32">
                        <RemoteDir>..\</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="iPad_Launch2048">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidSplashStyles">
                    <Platform Name="Android">
                        <RemoteDir>res\values</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage426">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-small</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidSplashImageDef">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSResource">
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectAndroidManifest">
                    <Platform Name="Android">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_DefaultAppIcon">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="File">
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="Android">
                        <Operation>0</Operation>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>0</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="AndroidServiceOutput">
                    <Platform Name="Android">
                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Required="true" Name="DependencyPackage">
                    <Platform Name="Win32">
                        <Operation>0</Operation>
                        <Extensions>.bpl</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="OSX32">
                        <RemoteDir>Contents\MacOS</RemoteDir>
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <Operation>1</Operation>
                        <Extensions>.dylib</Extensions>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon48">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-mdpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_SplashImage960">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-xlarge</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="Android_LauncherIcon36">
                    <Platform Name="Android">
                        <RemoteDir>res\drawable-ldpi</RemoteDir>
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <DeployClass Name="ProjectiOSDeviceResourceRules">
                    <Platform Name="iOSDevice64">
                        <Operation>1</Operation>
                    </Platform>
                    <Platform Name="iOSDevice32">
                        <Operation>1</Operation>
                    </Platform>
                </DeployClass>
                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
            </Deployment>
            <Platforms>
                <Platform value="Win32">False</Platform>
                <Platform value="Win64">True</Platform>
            </Platforms>
        </BorlandProject>
        <ProjectFileVersion>12</ProjectFileVersion>
    </ProjectExtensions>
    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

Added TinyServerInventory.res.

cannot compute difference between binary files

Added icon.ico.

cannot compute difference between binary files