├── .gitignore
├── LICENSE
├── README.md
├── SCPDemo.dpr
├── SCPDemo.dproj
├── SCPDemo.res
├── SSHCommand.pas
├── SSHCommandDemo.dpr
├── SSHCommandDemo.dproj
├── SSHCommandDemo.res
├── TSSHCommand.groupproj
├── Test
├── Test.dpr
├── Test.dproj
├── Test.res
└── uTest.pas
└── Thorsten Maxeiner Vortrag ssh Forentage 2019.pdf
/.gitignore:
--------------------------------------------------------------------------------
1 | # Uncomment these types if you want even more clean repository. But be careful.
2 | # It can make harm to an existing project source. Read explanations below.
3 | #
4 | # Resource files are binaries containing manifest, project icon and version info.
5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
6 | #*.res
7 | #
8 | # Type library file (binary). In old Delphi versions it should be stored.
9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
10 | #*.tlb
11 | #
12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
13 | # Uncomment this if you are not using diagrams or use newer Delphi version.
14 | #*.ddp
15 | #
16 | # Visual LiveBindings file. Added in Delphi XE2.
17 | # Uncomment this if you are not using LiveBindings Designer.
18 | #*.vlb
19 | #
20 | # Deployment Manager configuration file for your project. Added in Delphi XE2.
21 | # Uncomment this if it is not mobile development and you do not use remote debug feature.
22 | #*.deployproj
23 | #
24 | # C++ object files produced when C/C++ Output file generation is configured.
25 | # Uncomment this if you are not using external objects (zlib library for example).
26 | #*.obj
27 | #
28 |
29 | # Delphi compiler-generated binaries (safe to delete)
30 | *.exe
31 | *.dll
32 | *.bpl
33 | *.bpi
34 | *.dcp
35 | *.so
36 | *.apk
37 | *.drc
38 | *.map
39 | *.dres
40 | *.rsm
41 | *.tds
42 | *.dcu
43 | *.lib
44 | *.a
45 | *.o
46 | *.ocx
47 |
48 | # Delphi autogenerated files (duplicated info)
49 | *.cfg
50 | *.hpp
51 | *Resource.rc
52 |
53 | # Delphi local files (user-specific info)
54 | *.local
55 | *.identcache
56 | *.projdata
57 | *.tvsconfig
58 | *.dsk
59 |
60 | # Delphi history and backups
61 | __history/
62 | __recovery/
63 | *.~*
64 |
65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi)
66 | *.stat
67 |
68 | # Output directory
69 | Win32/
70 |
71 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Thorsten Maxeiner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TSSHCommand
2 | Send commands over ssh with Delphi. This is no implementation of ssh protocol in Delphi but a Wrapper to use ssh in a Delphi way. Since Openssh is a part of Windows 10, usage is easy without installing putty or something else.
3 | ---
4 |
5 | # Description
6 | TSSHCommand is a wrapper for Delphi to use built in openssh in Windows 10 to:
7 | - send commands to a remote ssh server
8 | - send files with scp to a remote server
9 | - receive files with scp from a remote server
10 |
11 | # Advantage
12 | Openssh is available in windows 10 since 1803 and I think standard install since 1809.
13 | Using ssh with Delphi gives out of the box encryption and authentication mechanism.
14 | Openssh in Windows is key compatible with openssh key in Linux.
15 | Command line options are compatible in Windows and Linux.
16 |
17 | # Prerequisites
18 | This wrapper uses shellexecute to start ssh.exe. Normally ssh is located in c:\windows\system32\Openssh\.
19 | I don't know why but shellexecute can't open the Openssh folder. If you start cmd.exe and navigate to c:\windows\system32\, you see no folder Openssh. If you use powershell, you see the folder and can enter it.
20 | So my detour is to copy ssh.exe from Openssh folder to my application folder or to a other folder e.g. c:\tools\
21 | To use the scp function, same is for scp.exe.
22 |
23 | # Repo Contens
24 | Included is the wrapper as Delphi record (file SSHCommand.pas), demo application and test.
25 |
26 | # Usage
27 | Evertything is visible in the demo application.
28 | After entering basic settings like:
29 | - hostname
30 | - port (if set other than 22)
31 | - username
32 | - keyfile
33 | you can perform as many commands and scp copy action with one line of code each.
34 |
35 | Attention: Before connecting with this wrapper, first make manuell connection e.g. with powershell to have a host entry in known_hosts!
36 |
37 |
38 | ''''
39 |
--------------------------------------------------------------------------------
/SCPDemo.dpr:
--------------------------------------------------------------------------------
1 | program SCPDemo;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | SSHCommand;
10 |
11 | var
12 | MySSHCommander : TSSHCommand;
13 | MyResult : integer;
14 | begin
15 | try
16 | MySSHCommander.HostName := 'www.example.com';
17 | MySSHCommander.PortNum := 12322;
18 | MySSHCommander.UserName := 'myuser';
19 | MySSHCommander.KeyFile := '~/.ssh/myuserkey';
20 |
21 | MyResult := MySSHCommander.SCPFromRemote( '/home/bill/list*.*', 'c:\tools\' );
22 | if MyResult > 32 then Writeln('Copy from remote OK')
23 | else Writeln('Error Nr.: ' + MyResult.ToString);
24 |
25 | MyResult := MySSHCommander.SCPToRemote( 'c:\tools\liste2.txt' , '/home/bill/' );
26 | if MyResult > 32 then Writeln('Copy to remote OK')
27 | else Writeln('Error Nr.: ' + MyResult.ToString);
28 |
29 | Writeln('Press Enter...');
30 | Readln;
31 | except
32 | on E: Exception do
33 | Writeln(E.ClassName, ': ', E.Message);
34 | end;
35 | end.
36 |
--------------------------------------------------------------------------------
/SCPDemo.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {F113DDEA-B2F9-4677-B7EE-B36965605396}
4 | 18.3
5 | None
6 | SCPDemo.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Console
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | .\$(Platform)\$(Config)
44 | .\$(Platform)\$(Config)
45 | false
46 | false
47 | false
48 | false
49 | false
50 | RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;aurelius;$(DCC_UsePackage)
51 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
52 | SCPDemo
53 |
54 |
55 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;svnui;FireDACADSDriver;frxe25;vacommpkgdXE11;FireDACMSSQLDriver;hotxls250;vcltouch;tmsxlsdXE11;vcldb;bindcompfmx;svn;Intraweb;inetdb;TMSCryptoPkgDXE11;RaizeComponentsVcl;vcwdedXE11;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;frxDB25;tmsdXE11;RadiantShapesFmx;frxTee25;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;fsTee25;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;fs25;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;advchartdedxe11;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;inetwinsockets;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;fsADO25;TeeDB;vacommpkgdedXE11;emshosting;FireDACPgDriver;FireDACASADriver;frxADO25;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;frx25;fmxobj;vclwinx;FireDACDSDriver;rtl;DelphiModbus102Tokyo;DbxClientDriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;fsDB25;bindcomp;appanalytics;tmswizdXE11;IndyIPClient;frxDBX25;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;TMSCryptoPkgDEDXE11;fmxase;$(DCC_UsePackage)
56 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
57 | Debug
58 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
59 | 1033
60 | true
61 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
62 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
63 |
64 |
65 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;FireDACADSDriver;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;inetdb;RaizeComponentsVcl;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;tmsdXE11;RadiantShapesFmx;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;fmxase;$(DCC_UsePackage)
66 | true
67 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
68 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
69 |
70 |
71 | DEBUG;$(DCC_Define)
72 | true
73 | false
74 | true
75 | true
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 | RELEASE;$(DCC_Define)
84 | 0
85 | 0
86 |
87 |
88 |
89 | MainSource
90 |
91 |
92 | Cfg_2
93 | Base
94 |
95 |
96 | Base
97 |
98 |
99 | Cfg_1
100 | Base
101 |
102 |
103 |
104 | Delphi.Personality.12
105 | Application
106 |
107 |
108 |
109 | SCPDemo.dpr
110 |
111 |
112 |
113 |
114 |
115 | true
116 |
117 |
118 |
119 |
120 | true
121 |
122 |
123 |
124 |
125 | true
126 |
127 |
128 |
129 |
130 | true
131 |
132 |
133 |
134 |
135 | SCPDemo.exe
136 | true
137 |
138 |
139 |
140 |
141 | 1
142 |
143 |
144 | Contents\MacOS
145 | 1
146 |
147 |
148 | Contents\MacOS
149 | 0
150 |
151 |
152 |
153 |
154 | classes
155 | 1
156 |
157 |
158 |
159 |
160 | library\lib\armeabi-v7a
161 | 1
162 |
163 |
164 |
165 |
166 | library\lib\armeabi
167 | 1
168 |
169 |
170 |
171 |
172 | library\lib\mips
173 | 1
174 |
175 |
176 |
177 |
178 | library\lib\armeabi-v7a
179 | 1
180 |
181 |
182 |
183 |
184 | res\drawable
185 | 1
186 |
187 |
188 |
189 |
190 | res\values
191 | 1
192 |
193 |
194 |
195 |
196 | res\drawable
197 | 1
198 |
199 |
200 |
201 |
202 | res\drawable-xxhdpi
203 | 1
204 |
205 |
206 |
207 |
208 | res\drawable-ldpi
209 | 1
210 |
211 |
212 |
213 |
214 | res\drawable-mdpi
215 | 1
216 |
217 |
218 |
219 |
220 | res\drawable-hdpi
221 | 1
222 |
223 |
224 |
225 |
226 | res\drawable-xhdpi
227 | 1
228 |
229 |
230 |
231 |
232 | res\drawable-small
233 | 1
234 |
235 |
236 |
237 |
238 | res\drawable-normal
239 | 1
240 |
241 |
242 |
243 |
244 | res\drawable-large
245 | 1
246 |
247 |
248 |
249 |
250 | res\drawable-xlarge
251 | 1
252 |
253 |
254 |
255 |
256 | 1
257 |
258 |
259 | Contents\MacOS
260 | 1
261 |
262 |
263 | 0
264 |
265 |
266 |
267 |
268 | Contents\MacOS
269 | 1
270 | .framework
271 |
272 |
273 | 0
274 |
275 |
276 |
277 |
278 | 1
279 | .dylib
280 |
281 |
282 | 1
283 | .dylib
284 |
285 |
286 | 1
287 | .dylib
288 |
289 |
290 | Contents\MacOS
291 | 1
292 | .dylib
293 |
294 |
295 | 0
296 | .dll;.bpl
297 |
298 |
299 |
300 |
301 | 1
302 | .dylib
303 |
304 |
305 | 1
306 | .dylib
307 |
308 |
309 | 1
310 | .dylib
311 |
312 |
313 | Contents\MacOS
314 | 1
315 | .dylib
316 |
317 |
318 | 0
319 | .bpl
320 |
321 |
322 |
323 |
324 | 0
325 |
326 |
327 | 0
328 |
329 |
330 | 0
331 |
332 |
333 | 0
334 |
335 |
336 | Contents\Resources\StartUp\
337 | 0
338 |
339 |
340 | 0
341 |
342 |
343 |
344 |
345 | 1
346 |
347 |
348 | 1
349 |
350 |
351 | 1
352 |
353 |
354 |
355 |
356 | 1
357 |
358 |
359 | 1
360 |
361 |
362 | 1
363 |
364 |
365 |
366 |
367 | 1
368 |
369 |
370 | 1
371 |
372 |
373 | 1
374 |
375 |
376 |
377 |
378 | 1
379 |
380 |
381 | 1
382 |
383 |
384 | 1
385 |
386 |
387 |
388 |
389 | 1
390 |
391 |
392 | 1
393 |
394 |
395 | 1
396 |
397 |
398 |
399 |
400 | 1
401 |
402 |
403 | 1
404 |
405 |
406 | 1
407 |
408 |
409 |
410 |
411 | 1
412 |
413 |
414 | 1
415 |
416 |
417 | 1
418 |
419 |
420 |
421 |
422 | 1
423 |
424 |
425 |
426 |
427 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
428 | 1
429 |
430 |
431 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
432 | 1
433 |
434 |
435 |
436 |
437 | 1
438 |
439 |
440 | 1
441 |
442 |
443 |
444 |
445 | ..\
446 | 1
447 |
448 |
449 | ..\
450 | 1
451 |
452 |
453 |
454 |
455 | 1
456 |
457 |
458 | 1
459 |
460 |
461 | 1
462 |
463 |
464 |
465 |
466 | 1
467 |
468 |
469 | 1
470 |
471 |
472 | 1
473 |
474 |
475 |
476 |
477 | ..\
478 | 1
479 |
480 |
481 |
482 |
483 | Contents
484 | 1
485 |
486 |
487 |
488 |
489 | Contents\Resources
490 | 1
491 |
492 |
493 |
494 |
495 | library\lib\armeabi-v7a
496 | 1
497 |
498 |
499 | 1
500 |
501 |
502 | 1
503 |
504 |
505 | 1
506 |
507 |
508 | 1
509 |
510 |
511 | Contents\MacOS
512 | 1
513 |
514 |
515 | 0
516 |
517 |
518 |
519 |
520 | 1
521 |
522 |
523 | 1
524 |
525 |
526 |
527 |
528 | Assets
529 | 1
530 |
531 |
532 | Assets
533 | 1
534 |
535 |
536 |
537 |
538 | Assets
539 | 1
540 |
541 |
542 | Assets
543 | 1
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 | True
557 | False
558 |
559 |
560 | 12
561 |
562 |
563 |
564 |
565 |
566 |
--------------------------------------------------------------------------------
/SCPDemo.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmaxeiner/TSSHCommand/fc24b7ca6844f0f1dcbe2258c3879675f6175c57/SCPDemo.res
--------------------------------------------------------------------------------
/SSHCommand.pas:
--------------------------------------------------------------------------------
1 | unit SSHCommand;
2 | {
3 | unit : SSHCommand.pas
4 | Author : tmaxeiner
5 | License : MIT, see License file
6 | Version : 0.1
7 | }
8 |
9 | interface
10 |
11 |
12 | uses
13 | System.SysUtils,
14 | shellapi,
15 | Winapi.Windows;
16 |
17 | type
18 | TSSHCommand = record
19 | strict private
20 | FSSHClient : string;
21 | FHostName : string;
22 | FPortNum : integer;
23 | FUserName : string;
24 | FKeyFile : string;
25 | FCommand : string;
26 | FCommandParameter : string;
27 | FSource : string;
28 | FDestination : string;
29 | FSCPParameterLine : string;
30 | function GetPortNum : integer;
31 | procedure SetHostName( const Value : string );
32 | procedure SetKeyFile( const Value : string );
33 | procedure SetPortNum( const Value : integer );
34 | procedure SetSSHClient( const Value : string );
35 | procedure SetUserName( const Value : string );
36 | private
37 | procedure SetCommand(const Value: string);
38 | procedure SetCommandParameter(const Value: string);
39 | procedure SetDestination(const Value: string);
40 | procedure SetSource(const Value: string);
41 | public
42 | ///
43 | /// Set a ssh client exe. Can be in application directory.
44 | /// Don't use original path in windows wich is
45 | /// c:\windows\system32\Openssh because it won't work with this wrapper!
46 | /// Leave blank if ssh.exe is in your application directory or in other searchpath.
47 | ///
48 | property SSHClient : string read FSSHClient write SetSSHClient;
49 | ///
50 | /// Hostname like www.excample.com or IP address.
51 | ///
52 | property HostName : string read FHostName write SetHostName;
53 | ///
54 | /// Leave blank if you use standard port 22.
55 | ///
56 | property PortNum : integer read GetPortNum write SetPortNum;
57 | ///
58 | /// Username on remote host. Needs login access rights.
59 | ///
60 | property UserName : string read FUserName write SetUserName;
61 | ///
62 | /// Full path of your private key file.
63 | ///
64 | property KeyFile : string read FKeyFile write SetKeyFile;
65 | ///
66 | /// Command to be run on remote host.
67 | ///
68 | property Command : string read FCommand write SetCommand;
69 | ///
70 | /// Command line parameter fpr the command to be run on remote host.
71 | ///
72 | property CommandParameter : string read FCommandParameter write SetCommandParameter;
73 | ///
74 | /// Destination for scp.
75 | /// This property is there for testing purpose.
76 | ///
77 | property Source : string read FSource write SetSource;
78 | ///
79 | /// Destination for scp.
80 | /// This property is there for testing purpose.
81 | ///
82 | property Destination : string read FDestination write SetDestination;
83 | ///
84 | /// Gives the parameter line for command execution.
85 | /// Can be used for testing.
86 | /// Set properties Source and Destionation first.
87 | ///
88 | function GetCommandParameterLine : string;
89 | ///
90 | /// Gives the parameter line for copy from remote action.
91 | /// Set properties Source and Destionation first.
92 | /// Can be used for testing.
93 | ///
94 | function GetSCPToRemoteParameterLine : string;
95 | ///
96 | /// Gives the parameter line for copy to remote action.
97 | /// Set properties Source and Destionation first.
98 | /// Can be used for testing.
99 | ///
100 | function GetSCPFromRemoteParameterLine : string;
101 | ///
102 | /// Send ACommand with AParameter to the remote host.
103 | /// All remote settings need to be set first.
104 | ///
105 | function SendCommand( const ACommand : string; const AParameter : string) : integer;
106 | ///
107 | /// Copy a local ASource to the remote host to ADestination.
108 | /// Uses scp. All remote settings need to be set first.
109 | /// If ADestination has trailing / then last part is a directory und filename of sourceparameter will copy into it.
110 | /// If ADestination has no trailing / then last part will be the new filename as copy destination.
111 | /// ASource can contain wildcards. Then give a trailing / as ADestination.
112 | ///
113 | function SCPToRemote( const ASource : string; const ADestination : string) : integer;
114 | ///
115 | /// Copy from ASource at remote host to a local ADestination
116 | /// All remote settings need to be set first.
117 | /// If ADestination has trailing / then last part is a directory und filename of sourceparameter will copy into it.
118 | /// If ADestination has no trailing / then last part will be the new filename as copy destination.
119 | /// ASource can contain wildcards. Then give a trailing / as ADestination.
120 | ///
121 | function SCPFromRemote( const ASource : string; const ADestination : string) : integer;
122 | end;
123 |
124 |
125 |
126 | implementation
127 |
128 | { TSSHCommand }
129 |
130 | {################################################################################################}
131 |
132 | function TSSHCommand.GetPortNum : integer;
133 | begin
134 | result := FPortNum;
135 | end;
136 |
137 | {################################################################################################}
138 |
139 | function TSSHCommand.GetSCPFromRemoteParameterLine: string;
140 | begin
141 | if FPortNum = 0 then FPortNum := 22;
142 | // scp -P 12322 -i keyfile user@remotehost:/home/user/file1.csv c:\tools\
143 | result := '-P ' +
144 | FPortNum.ToString +
145 | ' -i ' +
146 | FKeyFile +
147 | ' ' +
148 | FUserName +
149 | '@' +
150 | FHostName +
151 | ':' +
152 | FSource +
153 | ' ' +
154 | FDestination;
155 | end;
156 |
157 | {################################################################################################}
158 |
159 | function TSSHCommand.GetSCPToRemoteParameterLine: string;
160 | begin
161 | if FPortNum = 0 then FPortNum := 22;
162 | // scp -P 12322 -i keyfile ASource user@remotehost:ADestination
163 | result := '-P ' +
164 | FPortNum.ToString +
165 | ' -i ' +
166 | FKeyFile +
167 | ' ' +
168 | FSource +
169 | ' ' +
170 | FUserName +
171 | '@' +
172 | FHostName +
173 | ':' +
174 | FDestination;
175 | end;
176 |
177 | {################################################################################################}
178 |
179 | function TSSHCommand.GetCommandParameterLine : string;
180 | begin
181 | if FPortNum = 0 then FPortNum := 22;
182 | // ssh remotehost -p 12322 -i keyfile -l user -t "command commandparameter"
183 | result := FHostName +
184 | ' -p ' +
185 | FPortNum.ToString +
186 | ' -i ' +
187 | FKeyFile +
188 | ' -l ' +
189 | FUserName +
190 | ' -t "' +
191 | FCommand +
192 | ' ' +
193 | FCommandParameter + '"';
194 | end;
195 |
196 | {################################################################################################}
197 |
198 | function TSSHCommand.SCPFromRemote(const ASource, ADestination: string): integer;
199 | var
200 | LSCPParameterLine : string;
201 | begin
202 | if FSSHClient.IsEmpty then FSSHClient := 'scp.exe';
203 | FSource := ASource;
204 | FDestination := ADestination;
205 | LSCPParameterLine := GetSCPFromRemoteParameterLine;
206 | result := ShellExecute( 0, 'open', PCHar( FSSHClient ), PCHar( LSCPParameterLine ), nil, SW_HIDE );
207 | end;
208 |
209 | {################################################################################################}
210 |
211 | function TSSHCommand.SCPToRemote(const ASource, ADestination: string): integer;
212 | var
213 | LSCPParameterLine : string;
214 | begin
215 | if FSSHClient.IsEmpty then FSSHClient := 'scp.exe';
216 | FSource := ASource;
217 | FDestination := ADestination;
218 | LSCPParameterLine := GetSCPToRemoteParameterLine;
219 | result := ShellExecute( 0, 'open', PCHar( FSSHClient ), PCHar( LSCPParameterLine ), nil, SW_HIDE );
220 | end;
221 |
222 | {################################################################################################}
223 |
224 | function TSSHCommand.SendCommand ( const ACommand : string; const AParameter : string) : integer;
225 | var
226 | LCommandWithParameter : string;
227 | begin
228 | if FSSHClient.IsEmpty then FSSHClient := 'ssh.exe';
229 | FCommand := ACommand;
230 | FCommandParameter := AParameter;
231 | LCommandWithParameter := GetCommandParameterLine;
232 | result := ShellExecute( 0, 'open', PCHar( FSSHClient ), PCHar( LCommandWithParameter ), nil, SW_HIDE );
233 | end;
234 |
235 | {################################################################################################}
236 |
237 | procedure TSSHCommand.SetCommand(const Value: string);
238 | begin
239 | FCommand := Value;
240 | end;
241 |
242 | {################################################################################################}
243 |
244 | procedure TSSHCommand.SetCommandParameter(const Value: string);
245 | begin
246 | FCommandParameter := Value;
247 | end;
248 |
249 | {################################################################################################}
250 |
251 | procedure TSSHCommand.SetDestination(const Value: string);
252 | begin
253 | FDestination := Value;
254 | end;
255 |
256 | {################################################################################################}
257 |
258 | procedure TSSHCommand.SetHostName( const Value : string );
259 | begin
260 | FHostName := Value;
261 | end;
262 |
263 | {################################################################################################}
264 |
265 | procedure TSSHCommand.SetKeyFile( const Value : string );
266 | begin
267 | FKeyFile := Value;
268 | end;
269 |
270 | {################################################################################################}
271 |
272 | procedure TSSHCommand.SetPortNum( const Value : integer );
273 | begin
274 | FPortNum := Value;
275 | end;
276 |
277 | {################################################################################################}
278 |
279 | procedure TSSHCommand.SetSource(const Value: string);
280 | begin
281 | FSource := Value;
282 | end;
283 |
284 | procedure TSSHCommand.SetSSHClient( const Value : string );
285 | begin
286 | FSSHClient := Value;
287 | end;
288 |
289 | {################################################################################################}
290 |
291 | procedure TSSHCommand.SetUserName( const Value : string );
292 | begin
293 | FUserName := Value;
294 | end;
295 |
296 |
297 | end.
298 |
--------------------------------------------------------------------------------
/SSHCommandDemo.dpr:
--------------------------------------------------------------------------------
1 | program SSHCommandDemo;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | System.SysUtils,
9 | SSHCommand;
10 |
11 | var
12 | MySSHCommander : TSSHCommand;
13 | MyResult : integer;
14 | begin
15 | try
16 | MySSHCommander.HostName := 'www.example.com';
17 | MySSHCommander.PortNum := 12322;
18 | MySSHCommander.UserName := 'myuser';
19 | MySSHCommander.KeyFile := '~/.ssh/myuserkey';
20 |
21 | MyResult := MySSHCommander.SendCommand( '~/testcommand.sh', 'newline123' );
22 | if MyResult > 32 then Writeln('Command OK')
23 | else Writeln('Error Nr.: ' + MyResult.ToString);
24 | Writeln('Press Enter...');
25 | Readln;
26 | except
27 | on E: Exception do
28 | Writeln(E.ClassName, ': ', E.Message);
29 | end;
30 | end.
31 |
--------------------------------------------------------------------------------
/SSHCommandDemo.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {202634ED-F5FB-42B2-B949-79FE6D0F3FFB}
4 | 18.3
5 | None
6 | SSHCommandDemo.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Console
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | .\$(Platform)\$(Config)
44 | .\$(Platform)\$(Config)
45 | false
46 | false
47 | false
48 | false
49 | false
50 | RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;aurelius;$(DCC_UsePackage)
51 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
52 | SSHCommandDemo
53 |
54 |
55 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;svnui;FireDACADSDriver;frxe25;vacommpkgdXE11;FireDACMSSQLDriver;hotxls250;vcltouch;tmsxlsdXE11;vcldb;bindcompfmx;svn;Intraweb;inetdb;TMSCryptoPkgDXE11;RaizeComponentsVcl;vcwdedXE11;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;frxDB25;tmsdXE11;RadiantShapesFmx;frxTee25;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;fsTee25;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;fs25;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;advchartdedxe11;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;inetwinsockets;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;fsADO25;TeeDB;vacommpkgdedXE11;emshosting;FireDACPgDriver;FireDACASADriver;frxADO25;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;frx25;fmxobj;vclwinx;FireDACDSDriver;rtl;DelphiModbus102Tokyo;DbxClientDriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;fsDB25;bindcomp;appanalytics;tmswizdXE11;IndyIPClient;frxDBX25;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;TMSCryptoPkgDEDXE11;fmxase;$(DCC_UsePackage)
56 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
57 | Debug
58 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
59 | 1033
60 | true
61 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
62 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
63 |
64 |
65 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;FireDACADSDriver;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;inetdb;RaizeComponentsVcl;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;tmsdXE11;RadiantShapesFmx;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;fmxase;$(DCC_UsePackage)
66 | true
67 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
68 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
69 |
70 |
71 | DEBUG;$(DCC_Define)
72 | true
73 | false
74 | true
75 | true
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 | RELEASE;$(DCC_Define)
84 | 0
85 | 0
86 |
87 |
88 |
89 | MainSource
90 |
91 |
92 | Cfg_2
93 | Base
94 |
95 |
96 | Base
97 |
98 |
99 | Cfg_1
100 | Base
101 |
102 |
103 |
104 | Delphi.Personality.12
105 | Application
106 |
107 |
108 |
109 | SSHCommandDemo.dpr
110 |
111 |
112 |
113 |
114 |
115 | true
116 |
117 |
118 |
119 |
120 | true
121 |
122 |
123 |
124 |
125 | true
126 |
127 |
128 |
129 |
130 | true
131 |
132 |
133 |
134 |
135 | SSHCommandDemo.exe
136 | true
137 |
138 |
139 |
140 |
141 | 1
142 |
143 |
144 | Contents\MacOS
145 | 1
146 |
147 |
148 | Contents\MacOS
149 | 0
150 |
151 |
152 |
153 |
154 | classes
155 | 1
156 |
157 |
158 |
159 |
160 | library\lib\armeabi-v7a
161 | 1
162 |
163 |
164 |
165 |
166 | library\lib\armeabi
167 | 1
168 |
169 |
170 |
171 |
172 | library\lib\mips
173 | 1
174 |
175 |
176 |
177 |
178 | library\lib\armeabi-v7a
179 | 1
180 |
181 |
182 |
183 |
184 | res\drawable
185 | 1
186 |
187 |
188 |
189 |
190 | res\values
191 | 1
192 |
193 |
194 |
195 |
196 | res\drawable
197 | 1
198 |
199 |
200 |
201 |
202 | res\drawable-xxhdpi
203 | 1
204 |
205 |
206 |
207 |
208 | res\drawable-ldpi
209 | 1
210 |
211 |
212 |
213 |
214 | res\drawable-mdpi
215 | 1
216 |
217 |
218 |
219 |
220 | res\drawable-hdpi
221 | 1
222 |
223 |
224 |
225 |
226 | res\drawable-xhdpi
227 | 1
228 |
229 |
230 |
231 |
232 | res\drawable-small
233 | 1
234 |
235 |
236 |
237 |
238 | res\drawable-normal
239 | 1
240 |
241 |
242 |
243 |
244 | res\drawable-large
245 | 1
246 |
247 |
248 |
249 |
250 | res\drawable-xlarge
251 | 1
252 |
253 |
254 |
255 |
256 | 1
257 |
258 |
259 | Contents\MacOS
260 | 1
261 |
262 |
263 | 0
264 |
265 |
266 |
267 |
268 | Contents\MacOS
269 | 1
270 | .framework
271 |
272 |
273 | 0
274 |
275 |
276 |
277 |
278 | 1
279 | .dylib
280 |
281 |
282 | 1
283 | .dylib
284 |
285 |
286 | 1
287 | .dylib
288 |
289 |
290 | Contents\MacOS
291 | 1
292 | .dylib
293 |
294 |
295 | 0
296 | .dll;.bpl
297 |
298 |
299 |
300 |
301 | 1
302 | .dylib
303 |
304 |
305 | 1
306 | .dylib
307 |
308 |
309 | 1
310 | .dylib
311 |
312 |
313 | Contents\MacOS
314 | 1
315 | .dylib
316 |
317 |
318 | 0
319 | .bpl
320 |
321 |
322 |
323 |
324 | 0
325 |
326 |
327 | 0
328 |
329 |
330 | 0
331 |
332 |
333 | 0
334 |
335 |
336 | Contents\Resources\StartUp\
337 | 0
338 |
339 |
340 | 0
341 |
342 |
343 |
344 |
345 | 1
346 |
347 |
348 | 1
349 |
350 |
351 | 1
352 |
353 |
354 |
355 |
356 | 1
357 |
358 |
359 | 1
360 |
361 |
362 | 1
363 |
364 |
365 |
366 |
367 | 1
368 |
369 |
370 | 1
371 |
372 |
373 | 1
374 |
375 |
376 |
377 |
378 | 1
379 |
380 |
381 | 1
382 |
383 |
384 | 1
385 |
386 |
387 |
388 |
389 | 1
390 |
391 |
392 | 1
393 |
394 |
395 | 1
396 |
397 |
398 |
399 |
400 | 1
401 |
402 |
403 | 1
404 |
405 |
406 | 1
407 |
408 |
409 |
410 |
411 | 1
412 |
413 |
414 | 1
415 |
416 |
417 | 1
418 |
419 |
420 |
421 |
422 | 1
423 |
424 |
425 |
426 |
427 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
428 | 1
429 |
430 |
431 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
432 | 1
433 |
434 |
435 |
436 |
437 | 1
438 |
439 |
440 | 1
441 |
442 |
443 |
444 |
445 | ..\
446 | 1
447 |
448 |
449 | ..\
450 | 1
451 |
452 |
453 |
454 |
455 | 1
456 |
457 |
458 | 1
459 |
460 |
461 | 1
462 |
463 |
464 |
465 |
466 | 1
467 |
468 |
469 | 1
470 |
471 |
472 | 1
473 |
474 |
475 |
476 |
477 | ..\
478 | 1
479 |
480 |
481 |
482 |
483 | Contents
484 | 1
485 |
486 |
487 |
488 |
489 | Contents\Resources
490 | 1
491 |
492 |
493 |
494 |
495 | library\lib\armeabi-v7a
496 | 1
497 |
498 |
499 | 1
500 |
501 |
502 | 1
503 |
504 |
505 | 1
506 |
507 |
508 | 1
509 |
510 |
511 | Contents\MacOS
512 | 1
513 |
514 |
515 | 0
516 |
517 |
518 |
519 |
520 | 1
521 |
522 |
523 | 1
524 |
525 |
526 |
527 |
528 | Assets
529 | 1
530 |
531 |
532 | Assets
533 | 1
534 |
535 |
536 |
537 |
538 | Assets
539 | 1
540 |
541 |
542 | Assets
543 | 1
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 | True
557 | False
558 |
559 |
560 | 12
561 |
562 |
563 |
564 |
565 |
566 |
--------------------------------------------------------------------------------
/SSHCommandDemo.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmaxeiner/TSSHCommand/fc24b7ca6844f0f1dcbe2258c3879675f6175c57/SSHCommandDemo.res
--------------------------------------------------------------------------------
/TSSHCommand.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {7B23765E-BF50-4CDF-B0CC-E011FA0BB03D}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Default.Personality.12
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 |
--------------------------------------------------------------------------------
/Test/Test.dpr:
--------------------------------------------------------------------------------
1 | program Test;
2 |
3 | {$IFNDEF TESTINSIGHT}
4 | {$APPTYPE CONSOLE}
5 | {$ENDIF}{$STRONGLINKTYPES ON}
6 | uses
7 | System.SysUtils,
8 | {$IFDEF TESTINSIGHT}
9 | TestInsight.DUnitX,
10 | {$ENDIF }
11 | DUnitX.Loggers.Console,
12 | DUnitX.Loggers.Xml.NUnit,
13 | DUnitX.TestFramework,
14 | uTest in 'uTest.pas',
15 | SSHCommand in '..\SSHCommand.pas';
16 |
17 | var
18 | runner : ITestRunner;
19 | results : IRunResults;
20 | logger : ITestLogger;
21 | nunitLogger : ITestLogger;
22 | begin
23 | {$IFDEF TESTINSIGHT}
24 | TestInsight.DUnitX.RunRegisteredTests;
25 | exit;
26 | {$ENDIF}
27 | try
28 | //Check command line options, will exit if invalid
29 | TDUnitX.CheckCommandLine;
30 | //Create the test runner
31 | runner := TDUnitX.CreateRunner;
32 | //Tell the runner to use RTTI to find Fixtures
33 | runner.UseRTTI := True;
34 | //tell the runner how we will log things
35 | //Log to the console window
36 | logger := TDUnitXConsoleLogger.Create(true);
37 | runner.AddLogger(logger);
38 | //Generate an NUnit compatible XML File
39 | nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile);
40 | runner.AddLogger(nunitLogger);
41 | runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests;
42 |
43 | //Run tests
44 | results := runner.Execute;
45 | if not results.AllPassed then
46 | System.ExitCode := EXIT_ERRORS;
47 |
48 | {$IFNDEF CI}
49 | //We don't want this happening when running under CI.
50 | if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then
51 | begin
52 | System.Write('Done.. press key to quit.');
53 | System.Readln;
54 | end;
55 | {$ENDIF}
56 | except
57 | on E: Exception do
58 | System.Writeln(E.ClassName, ': ', E.Message);
59 | end;
60 | end.
61 |
--------------------------------------------------------------------------------
/Test/Test.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {54792C7C-9F68-46A3-902F-B76AD9F2D1C4}
4 | 18.3
5 | None
6 | Test.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Console
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | .\$(Platform)\$(Config)
44 | .\$(Platform)\$(Config)
45 | false
46 | false
47 | false
48 | false
49 | false
50 | RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;aurelius;$(DCC_UsePackage)
51 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
52 | true
53 | $(BDS)\bin\delphi_PROJECTICON.ico
54 | $(BDS)\bin\delphi_PROJECTICNS.icns
55 | $(DUnitX);$(DCC_UnitSearchPath)
56 | Test
57 |
58 |
59 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;svnui;FireDACADSDriver;frxe25;vacommpkgdXE11;FireDACMSSQLDriver;hotxls250;vcltouch;tmsxlsdXE11;vcldb;bindcompfmx;svn;Intraweb;inetdb;TMSCryptoPkgDXE11;RaizeComponentsVcl;vcwdedXE11;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;frxDB25;tmsdXE11;RadiantShapesFmx;frxTee25;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;fsTee25;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;fs25;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;advchartdedxe11;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;inetwinsockets;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;fsADO25;TeeDB;vacommpkgdedXE11;emshosting;FireDACPgDriver;FireDACASADriver;frxADO25;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;frx25;fmxobj;vclwinx;FireDACDSDriver;rtl;DelphiModbus102Tokyo;DbxClientDriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;fsDB25;bindcomp;appanalytics;tmswizdXE11;IndyIPClient;frxDBX25;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;TMSCryptoPkgDEDXE11;fmxase;$(DCC_UsePackage)
60 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
61 | Debug
62 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
63 | 1033
64 |
65 |
66 | DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;AbkStdRAD10_2;tethering;FireDACADSDriver;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;inetdb;RaizeComponentsVcl;vcwdXE11;FmxTeeUI;emsedge;RaizeComponentsVclDb;fmx;fmxdae;tmsdXE11;RadiantShapesFmx;tmsexdXE11;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;IcsVclD102Run;VCLRESTComponents;IcsFmxD102Run;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;AbkDBStdRAD10_2;vcl;IndyIPServer;IndySystem;FireDACDb2Driver;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;AsyncProDR;Tee;xmlrtl;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;dsnapxml;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;IcsCommonD102Run;fmxase;$(DCC_UsePackage)
67 |
68 |
69 | DEBUG;$(DCC_Define)
70 | true
71 | false
72 | true
73 | true
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | false
81 | RELEASE;$(DCC_Define)
82 | 0
83 | 0
84 |
85 |
86 |
87 | MainSource
88 |
89 |
90 |
91 |
92 | Cfg_2
93 | Base
94 |
95 |
96 | Base
97 |
98 |
99 | Cfg_1
100 | Base
101 |
102 |
103 |
104 | Delphi.Personality.12
105 | Console
106 |
107 |
108 |
109 | Test.dpr
110 |
111 |
112 |
113 |
114 |
115 | true
116 |
117 |
118 |
119 |
120 | true
121 |
122 |
123 |
124 |
125 | true
126 |
127 |
128 |
129 |
130 | true
131 |
132 |
133 |
134 |
135 | Test.exe
136 | true
137 |
138 |
139 |
140 |
141 | 1
142 |
143 |
144 | Contents\MacOS
145 | 0
146 |
147 |
148 |
149 |
150 | classes
151 | 1
152 |
153 |
154 |
155 |
156 | library\lib\armeabi-v7a
157 | 1
158 |
159 |
160 |
161 |
162 | library\lib\armeabi
163 | 1
164 |
165 |
166 |
167 |
168 | library\lib\mips
169 | 1
170 |
171 |
172 |
173 |
174 | library\lib\armeabi-v7a
175 | 1
176 |
177 |
178 |
179 |
180 | res\drawable
181 | 1
182 |
183 |
184 |
185 |
186 | res\values
187 | 1
188 |
189 |
190 |
191 |
192 | res\drawable
193 | 1
194 |
195 |
196 |
197 |
198 | res\drawable-xxhdpi
199 | 1
200 |
201 |
202 |
203 |
204 | res\drawable-ldpi
205 | 1
206 |
207 |
208 |
209 |
210 | res\drawable-mdpi
211 | 1
212 |
213 |
214 |
215 |
216 | res\drawable-hdpi
217 | 1
218 |
219 |
220 |
221 |
222 | res\drawable-xhdpi
223 | 1
224 |
225 |
226 |
227 |
228 | res\drawable-small
229 | 1
230 |
231 |
232 |
233 |
234 | res\drawable-normal
235 | 1
236 |
237 |
238 |
239 |
240 | res\drawable-large
241 | 1
242 |
243 |
244 |
245 |
246 | res\drawable-xlarge
247 | 1
248 |
249 |
250 |
251 |
252 | 1
253 |
254 |
255 | 1
256 |
257 |
258 | 0
259 |
260 |
261 |
262 |
263 | 1
264 | .framework
265 |
266 |
267 | 0
268 |
269 |
270 |
271 |
272 | 1
273 | .dylib
274 |
275 |
276 | 0
277 | .dll;.bpl
278 |
279 |
280 |
281 |
282 | 1
283 | .dylib
284 |
285 |
286 | 1
287 | .dylib
288 |
289 |
290 | 1
291 | .dylib
292 |
293 |
294 | 1
295 | .dylib
296 |
297 |
298 | 0
299 | .bpl
300 |
301 |
302 |
303 |
304 | 0
305 |
306 |
307 | 0
308 |
309 |
310 | 0
311 |
312 |
313 | 0
314 |
315 |
316 | 0
317 |
318 |
319 | 0
320 |
321 |
322 |
323 |
324 | 1
325 |
326 |
327 | 1
328 |
329 |
330 | 1
331 |
332 |
333 |
334 |
335 | 1
336 |
337 |
338 | 1
339 |
340 |
341 | 1
342 |
343 |
344 |
345 |
346 | 1
347 |
348 |
349 | 1
350 |
351 |
352 | 1
353 |
354 |
355 |
356 |
357 | 1
358 |
359 |
360 | 1
361 |
362 |
363 | 1
364 |
365 |
366 |
367 |
368 | 1
369 |
370 |
371 | 1
372 |
373 |
374 | 1
375 |
376 |
377 |
378 |
379 | 1
380 |
381 |
382 | 1
383 |
384 |
385 | 1
386 |
387 |
388 |
389 |
390 | 1
391 |
392 |
393 | 1
394 |
395 |
396 | 1
397 |
398 |
399 |
400 |
401 | 1
402 |
403 |
404 |
405 |
406 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
407 | 1
408 |
409 |
410 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
411 | 1
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 | 1
420 |
421 |
422 | 1
423 |
424 |
425 | 1
426 |
427 |
428 |
429 |
430 |
431 |
432 | Contents\Resources
433 | 1
434 |
435 |
436 |
437 |
438 | library\lib\armeabi-v7a
439 | 1
440 |
441 |
442 | 1
443 |
444 |
445 | 1
446 |
447 |
448 | 1
449 |
450 |
451 | 1
452 |
453 |
454 | 1
455 |
456 |
457 | 0
458 |
459 |
460 |
461 |
462 | 1
463 |
464 |
465 | 1
466 |
467 |
468 |
469 |
470 | Assets
471 | 1
472 |
473 |
474 | Assets
475 | 1
476 |
477 |
478 |
479 |
480 | Assets
481 | 1
482 |
483 |
484 | Assets
485 | 1
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 | True
499 | False
500 |
501 |
502 | 12
503 |
504 |
505 |
506 |
507 |
508 |
--------------------------------------------------------------------------------
/Test/Test.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmaxeiner/TSSHCommand/fc24b7ca6844f0f1dcbe2258c3879675f6175c57/Test/Test.res
--------------------------------------------------------------------------------
/Test/uTest.pas:
--------------------------------------------------------------------------------
1 | unit uTest;
2 |
3 | interface
4 | uses
5 | DUnitX.TestFramework,
6 | SSHCommand;
7 |
8 | type
9 |
10 | [TestFixture]
11 | TMyTestObject = class(TObject)
12 | public
13 | [Setup]
14 | procedure Setup;
15 | [TearDown]
16 | procedure TearDown;
17 | [TEST]
18 | procedure TestParameterLineCommandStandardPort;
19 | [TEST]
20 | procedure TestParameterLineCommandOtherPort;
21 | [TEST]
22 | procedure TestParameterLineSCPToRemoteStandardPort;
23 | [TEST]
24 | procedure TestParameterLineSCPFromRemoteStandardPort;
25 | end;
26 |
27 | implementation
28 |
29 | procedure TMyTestObject.Setup;
30 | begin
31 | end;
32 |
33 | procedure TMyTestObject.TearDown;
34 | begin
35 | end;
36 |
37 | procedure TMyTestObject.TestParameterLineSCPFromRemoteStandardPort;
38 | var
39 | LSSHCommander : TSSHCommand;
40 | LGoodLine : string;
41 | begin
42 | LSSHCommander.HostName := 'example.com';
43 | LSSHCommander.UserName := 'myuser';
44 | LSSHCommander.KeyFile := '~/.ssh/mykey';
45 | LSSHCommander.Source := '/home/myuser/list1.txt';
46 | LSSHCommander.Destination := 'c:\Users\bill\';
47 | // scp -P 22 -i keyfile user@remotehost:/home/myuser/file1.csv c:\tools\
48 | LGoodLine := '-P 22 -i ~/.ssh/mykey myuser@example.com:/home/myuser/list1.txt c:\Users\bill\';
49 | Assert.AreEqual(LGoodLine, LSSHCommander.GetSCPFromRemoteParameterLine, 'Parameterlist scp from remote standardport incorrect');
50 | end;
51 |
52 | procedure TMyTestObject.TestParameterLineSCPToRemoteStandardPort;
53 | var
54 | LSSHCommander : TSSHCommand;
55 | LGoodLine : string;
56 | begin
57 | LSSHCommander.HostName := 'example.com';
58 | LSSHCommander.UserName := 'myuser';
59 | LSSHCommander.KeyFile := '~/.ssh/mykey';
60 | LSSHCommander.Source := 'c:\Users\bill\list1.txt';
61 | LSSHCommander.Destination := '/home/myuser/list2.txt';
62 | // scp -P 22 -i keyfile c:\Users\bill\list1.txt user@remotehost:/home/myuser/file1.csv
63 | LGoodLine := '-P 22 -i ~/.ssh/mykey c:\Users\bill\list1.txt myuser@example.com:/home/myuser/list2.txt';
64 | Assert.AreEqual(LGoodLine, LSSHCommander.GetSCPToRemoteParameterLine, 'Parameterlist scp to remote standardport incorrect');
65 | end;
66 |
67 | procedure TMyTestObject.TestParameterLineCommandOtherPort;
68 | var
69 | LSSHCommander : TSSHCommand;
70 | LGoodLine : string;
71 | begin
72 | LSSHCommander.HostName := 'example.com';
73 | LSSHCommander.UserName := 'myuser';
74 | LSSHCommander.PortNum := 12322;
75 | LSSHCommander.KeyFile := '~/.ssh/mykey';
76 | LSSHCommander.Command := 'MyCommand';
77 | LSSHCommander.CommandParameter := 'DoNothing';
78 | // ssh remotehost -p 12322 -i keyfile -l user -t "command commandparameter"
79 | LGoodline := 'example.com -p 12322 -i ~/.ssh/mykey -l myuser -t "MyCommand DoNothing"';
80 | Assert.AreEqual(LGoodLine, LSSHCommander.GetCommandParameterLine, 'Parameterlist Command other port incorrect');
81 | end;
82 |
83 | procedure TMyTestObject.TestParameterLineCommandStandardPort;
84 | var
85 | LSSHCommander : TSSHCommand;
86 | LGoodLine : string;
87 | begin
88 | LSSHCommander.HostName := 'example.com';
89 | LSSHCommander.UserName := 'myuser';
90 | LSSHCommander.KeyFile := '~/.ssh/mykey';
91 | LSSHCommander.Command := 'MyCommand';
92 | LSSHCommander.CommandParameter := 'DoNothing';
93 | // ssh remotehost -p 22 -i keyfile -l user -t "command commandparameter"
94 | LGoodline := 'example.com -p 22 -i ~/.ssh/mykey -l myuser -t "MyCommand DoNothing"';
95 | Assert.AreEqual(LGoodLine, LSSHCommander.GetCommandParameterLine, 'Parameterlist Command standardport incorrect');
96 | end;
97 |
98 | initialization
99 | TDUnitX.RegisterTestFixture(TMyTestObject);
100 | end.
101 |
--------------------------------------------------------------------------------
/Thorsten Maxeiner Vortrag ssh Forentage 2019.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmaxeiner/TSSHCommand/fc24b7ca6844f0f1dcbe2258c3879675f6175c57/Thorsten Maxeiner Vortrag ssh Forentage 2019.pdf
--------------------------------------------------------------------------------