RunAProgram: Difference between revisions
m Created AccuTermFileTransfer page and added link here |
m link fix |
||
Line 1: | Line 1: | ||
HomePage>>HowTos>>RunAProgram | HomePage>>HowTos>>[[RunAProgram]] | ||
The problem: you want a program to run on a windows PC as a result of something that happens on your Windows or Unix-based server. | The problem: you want a program to run on a windows PC as a result of something that happens on your Windows or Unix-based server. | ||
Line 6: | Line 6: | ||
For this to work "something", some program, has to be running on the PC. | For this to work "something", some program, has to be running on the PC. | ||
==== 0) TerminalEmulators ==== | ==== 0) [[TerminalEmulators]] ==== | ||
The most common "something" is a terminal emulator and they pretty much all allow you to send an escape sequence and fire off a program. If you want the program to run in response to something the user did on the server, this is the most straightforward way to do it. Also, if you have a serial connection, this is probably the only option. | The most common "something" is a terminal emulator and they pretty much all allow you to send an escape sequence and fire off a program. If you want the program to run in response to something the user did on the server, this is the most straightforward way to do it. Also, if you have a serial connection, this is probably the only option. | ||
Line 16: | Line 16: | ||
* Accuterm: | * Accuterm: | ||
To execute a command and return to PICK/BASIC immediately: | To execute a command and return to PICK[[/BASIC]] immediately: | ||
<PRE> | <PRE> | ||
PRINT CHAR(27):CHAR(2):"<":command:CHAR(13) | PRINT CHAR(27):CHAR(2):"<":command:CHAR(13) | ||
</PRE> | </PRE> | ||
To execute a command and wait for the command to terminate before returning to PICK/BASIC: | To execute a command and wait for the command to terminate before returning to PICK[[/BASIC]]: | ||
<PRE> | <PRE> | ||
PRINT CHAR(27):CHAR(2):">":command:CHAR(13) | PRINT CHAR(27):CHAR(2):">":command:CHAR(13) | ||
Line 27: | Line 27: | ||
See <nowiki>AccuTerm</nowiki> help for details: From the Help Introduction, see <nowiki>AccuTerm</nowiki> Programming. Also see Help on Object Bridge. | See <nowiki>AccuTerm</nowiki> help for details: From the Help Introduction, see <nowiki>AccuTerm</nowiki> Programming. Also see Help on Object Bridge. | ||
More examples are at AccuTermFileTransfer. | More examples are at [[AccuTermFileTransfer]]. | ||
* ViaDuct: | * [[ViaDuct]]: | ||
<PRE> | <PRE> | ||
? | ? | ||
Line 77: | Line 77: | ||
==== 3) Install or turn on a telnet server ==== | ==== 3) Install or turn on a telnet server ==== | ||
W2K/XP come with a telnet server, or you can purchase one. Then use http://expect.nist.gov to script the login/command process. | [[W2K/XP]] come with a telnet server, or you can purchase one. Then use http://expect.nist.gov to script the login/command process. | ||
<PRE> | <PRE> | ||
Line 95: | Line 95: | ||
Have the program listen on a predefined port. There are obvious security issues here, but with a little handwaving we can move past them :-) | Have the program listen on a predefined port. There are obvious security issues here, but with a little handwaving we can move past them :-) | ||
Recent U2 products can create socket connections from basic and connect to the server. Sample code for this is at BasicSocketClient. | Recent U2 products can create socket connections from basic and connect to the server. Sample code for this is at [[BasicSocketClient]]. | ||
Here's a stripped down example of a server in <a href="http://www.python.org">Python</a>: | Here's a stripped down example of a server in <a href="http://www.python.org">Python</a>: | ||
Line 101: | Line 101: | ||
urlserver.py | urlserver.py | ||
<PRE> | <PRE> | ||
import SocketServer | import [[SocketServer]] | ||
import os | import os | ||
class UrlHandler(SocketServer.StreamRequestHandler): | class [[UrlHandler]]([[SocketServer]].[[StreamRequestHandler]]): | ||
def handle(self): | def handle(self): | ||
url=self.rfile.readline(512) | url=self.rfile.readline(512) | ||
Line 110: | Line 110: | ||
os.system("start "+url) | os.system("start "+url) | ||
server=SocketServer.TCPServer( ('', 79), UrlHandler) | server=[[SocketServer]].TCPServer( ('', 79), [[UrlHandler]]) | ||
server.serve_forever() | server.serve_forever() | ||
</PRE> | </PRE> | ||
Line 128: | Line 128: | ||
On Error Resume Next | On Error Resume Next | ||
Err.Number=0 | Err.Number=0 | ||
Set oSck=WScript.CreateObject("MSWinsock.Winsock","s_") | Set oSck=WScript.[[CreateObject]]("MSWinsock.Winsock","s_") | ||
Select Case Err.Number | Select Case Err.Number | ||
Case 0 | Case 0 | ||
Line 134: | Line 134: | ||
echo "No licence found. Install Visual Studio" | echo "No licence found. Install Visual Studio" | ||
case &H80020009 | case &H80020009 | ||
echo "ActiveX Winsock not in the registry, check if installed or use regsvr32" | echo "[[ActiveX]] Winsock not in the registry, check if installed or use regsvr32" | ||
Case else | Case else | ||
echo "Error " & Err.Number & " - &H" & Hex(Err.Number) & " - " & Err.Description | echo "Error " & Err.Number & " - &H" & Hex(Err.Number) & " - " & Err.Description | ||
Line 140: | Line 140: | ||
On Error Goto 0 | On Error Goto 0 | ||
oSck.LocalPort=79 | oSck.[[LocalPort]]=79 | ||
oSck.Listen | oSck.Listen | ||
echo "Listening on port " & oSck.LocalPort | echo "Listening on port " & oSck.[[LocalPort]] | ||
Do | Do | ||
' Sleep for 2 seconds | ' Sleep for 2 seconds | ||
Line 152: | Line 152: | ||
End Sub | End Sub | ||
Sub | Sub s_[[ConnectionRequest]](Byval requestID) | ||
oSck.Close | oSck.Close | ||
echo oSck.RemoteHostIP & " - Connection request:" & requestID | echo oSck.[[RemoteHostIP]] & " - Connection request:" & requestID | ||
oSck.Accept requestID | oSck.Accept requestID | ||
End Sub | End Sub | ||
Line 164: | Line 164: | ||
End Sub | End Sub | ||
Sub | Sub s_[[SendComplete]] | ||
oSck.close | oSck.close | ||
oSck.Listen | oSck.Listen | ||
End Sub | End Sub | ||
Sub s_Error(ByVal N, D, ByVal C, ByVal S, ByVal F, ByVal H, Y) | Sub s_Error([[ByVal]] N, D, [[ByVal]] C, [[ByVal]] S, [[ByVal]] F, [[ByVal]] H, Y) | ||
echo "Error" & N & " - " & D | echo "Error" & N & " - " & D | ||
oSck.Close | oSck.Close | ||
Line 175: | Line 175: | ||
End Sub | End Sub | ||
Sub | Sub s_[[DataArrival]](Byval b) | ||
Dim S,sh | Dim S,sh | ||
S="" | S="" | ||
oSck.GetData S | oSck.[[GetData]] S | ||
S=left(S,len(S)-2) | S=left(S,len(S)-2) | ||
S=left(S,512) | S=left(S,512) | ||
Line 201: | Line 201: | ||
<PRE> | <PRE> | ||
Private Sub Form_Load() | Private Sub [[Form_Load]]() | ||
txt[[ScheduleNum]].Enabled = False | |||
cboCategory.Enabled = False | cboCategory.Enabled = False | ||
cmdOK.Enabled = False | cmdOK.Enabled = False | ||
Line 211: | Line 211: | ||
Me.Show | Me.Show | ||
' Start the poll right away | ' Start the poll right away | ||
Timer1_Timer | [[Timer1_Timer]] | ||
End Sub | End Sub | ||
Private Sub Timer1_Timer() | Private Sub [[Timer1_Timer]]() | ||
TxtLog.ForeColor = vbBlack | [[TxtLog]].[[ForeColor]] = vbBlack | ||
LogMsg "Checking c:\batch" | [[LogMsg]] "Checking c:\batch" | ||
Set fso = CreateObject("Scripting.FileSystemObject") | Set fso = [[CreateObject]]("Scripting.[[FileSystemObject]]") | ||
Set dir = fso.GetFolder("C:\BATCH") | Set dir = fso.[[GetFolder]]("C:\BATCH") | ||
For Each file In dir.Files | For Each file In dir.Files | ||
If LCase(Right(file.Name, 3)) = "pdf" Then | If LCase(Right(file.Name, 3)) = "pdf" Then | ||
Timer1.Enabled = False | Timer1.Enabled = False | ||
TxtLog.Enabled = False | [[TxtLog]].Enabled = False | ||
fstr = file.Name | fstr = file.Name | ||
hpsname = Left(fstr, Len(fstr) - 3) & "hps" | hpsname = Left(fstr, Len(fstr) - 3) & "hps" | ||
justname = Left(fstr, Len(fstr) - 3) | justname = Left(fstr, Len(fstr) - 3) | ||
LogMsg fstr | [[LogMsg]] fstr | ||
Label1.Enabled = True | Label1.Enabled = True | ||
Label3.Enabled = True | Label3.Enabled = True | ||
Line 234: | Line 234: | ||
cmdPreview.Enabled = True | cmdPreview.Enabled = True | ||
' Enable some controls and do something with the file | ' Enable some controls and do something with the file | ||
txt[[ScheduleNum]].[[SetFocus]] | |||
Exit For | Exit For | ||
End If | End If | ||
Line 244: | Line 244: | ||
(Ad) | (Ad) | ||
The following link goes to the Nebula R&D forum where an offering is discussed and a link is provided to a blog entry for more information. As of the time of this writing the software is fully usable but is not being offered as a product simply for lack of demand. That situation can change with a compelling business case. http://nebula-rnd.com/forum/index.php/topic,51.0.html | The following link goes to the Nebula R&D forum where an offering is discussed and a link is provided to a blog entry for more information. As of the time of this writing the software is fully usable but is not being offered as a product simply for lack of demand. That situation can change with a compelling business case. http://nebula-rnd.com/forum/index.php/topic,51.0.html | ||
(/Ad) | ([[/Ad]]) | ||
A general description of this approach, not specific to the Nebula solution, would be to write a PC program in your favourite language (.Net, Java, Flex for example), that runs on the PC and makes periodic calls to a Pick program using whatever technology makes sense for your Pick variety. In the U2 world, this would be UniObjects, though a web services call that hides the connection details from the client, and be much more likely to work through firewalls, would make more sense. | A general description of this approach, not specific to the Nebula solution, would be to write a PC program in your favourite language (.Net, Java, Flex for example), that runs on the PC and makes periodic calls to a Pick program using whatever technology makes sense for your Pick variety. In the U2 world, this would be [[UniObjects]], though a web services call that hides the connection details from the client, and be much more likely to work through firewalls, would make more sense. | ||
Note: this is not exactly the problem we are trying to solve on this page. The problem is "how do I run a program on the client side, on demand from a Pick program?" The polling solutions presented suffer from a lag between something happening on the server and a program running on the client. | Note: this is not exactly the problem we are trying to solve on this page. The problem is "how do I run a program on the client side, on demand from a Pick program?" The polling solutions presented suffer from a lag between something happening on the server and a program running on the client. |
Revision as of 23:48, 26 February 2015
HomePage>>HowTos>>RunAProgram
The problem: you want a program to run on a windows PC as a result of something that happens on your Windows or Unix-based server. It's usually less of an issue to have a Unix server run something on a Unix client, or Windows server to Windows client - there's plenty of built in ways for that to work. So we'll just consider a Windows PC with a network connection (LAN,WAN or VPN) to a Unix server.
For this to work "something", some program, has to be running on the PC.
0) TerminalEmulators
The most common "something" is a terminal emulator and they pretty much all allow you to send an escape sequence and fire off a program. If you want the program to run in response to something the user did on the server, this is the most straightforward way to do it. Also, if you have a serial connection, this is probably the only option.
- wIntegrate:
Use the WIN.PCRUN command installed on the server, CALL WIN.PCRUN(COMMAND,ARGS)
- Accuterm:
To execute a command and return to PICK/BASIC immediately:
PRINT CHAR(27):CHAR(2):"<":command:CHAR(13)
To execute a command and wait for the command to terminate before returning to PICK/BASIC:
PRINT CHAR(27):CHAR(2):">":command:CHAR(13)
See AccuTerm help for details: From the Help Introduction, see AccuTerm Programming. Also see Help on Object Bridge.
More examples are at AccuTermFileTransfer.
?
- Powerterm:
PRINT CHAR(27):"$tS":COMMAND:CHAR(27):"\"
- Netterm:
Start/run the program specified by COMMAND.
CRT CHAR(27):"[]":COMMAND:CHAR(27):"[1*
Send the URL to the client's WWW browser for processing.
CRT CHAR(27):'[]':URL:CHAR(27):'[0*'
Start/run the program specified by COMMAND and wait till it terminates. COMMAND can contain both the program to run and command line arguments.
CRT CHAR(27):"[]":COMMAND:CHAR(27):"[9*"
Start the program associated with the extension contained within FILENAME.
CRT CHAR(27):"[]":FILENAME:CHAR(27):"[12*
1) Doit
Doit is a small utility program that installs a tray applet on the client. The server sends it the path of a file to open.
http://www.chiark.greenend.org.uk/~sgtatham/doit/
2) Install rcmd
Either from the windows resource kit, or purchase it from mks. You can then issue an rcmd from the unix side.
http://www.dynawell.com/support/ResKit/winnt.asp http://www.mkssoftware.com/support/kb/faqs.asp?product=Toolkit&type=tech#art140
3) Install or turn on a telnet server
W2K/XP come with a telnet server, or you can purchase one. Then use http://expect.nist.gov to script the login/command process.
http://www.goodtechsys.com/
4) Install an ssh server
Just like telnet, only secure!
http://tech.erdelynet.com/cygwin-sshd.html
5a) Write a small server program
Have the program listen on a predefined port. There are obvious security issues here, but with a little handwaving we can move past them :-)
Recent U2 products can create socket connections from basic and connect to the server. Sample code for this is at BasicSocketClient.
Here's a stripped down example of a server in <a href="http://www.python.org">Python</a>:
urlserver.py
import [[SocketServer]] import os class [[UrlHandler]]([[SocketServer]].[[StreamRequestHandler]]): def handle(self): url=self.rfile.readline(512) print "opening "+url os.system("start "+url) server=[[SocketServer]].TCPServer( ('', 79), [[UrlHandler]]) server.serve_forever()
On the pc, type "python urlserver.py" to start the server up, then from another machine, "telnet pc-address 79" and then type the url to go to - the client will open up a browser and go to that address.
5b) ...and here's another in vbscript
urlserver.vbs
Option Explicit ' Heavily cribbed from the amazing 4K webserver at: ' http://www.interclasse.com/scripts/4KWebServer.php Dim oSck On Error Resume Next Err.Number=0 Set oSck=WScript.[[CreateObject]]("MSWinsock.Winsock","s_") Select Case Err.Number Case 0 case &H80040112 echo "No licence found. Install Visual Studio" case &H80020009 echo "[[ActiveX]] Winsock not in the registry, check if installed or use regsvr32" Case else echo "Error " & Err.Number & " - &H" & Hex(Err.Number) & " - " & Err.Description End Select On Error Goto 0 oSck.[[LocalPort]]=79 oSck.Listen echo "Listening on port " & oSck.[[LocalPort]] Do ' Sleep for 2 seconds WScript.sleep 2000 Loop Sub echo(S) WScript.Echo Now & " " & S End Sub Sub s_[[ConnectionRequest]](Byval requestID) oSck.Close echo oSck.[[RemoteHostIP]] & " - Connection request:" & requestID oSck.Accept requestID End Sub Sub s_Close oSck.Close echo "closed - re-listening" oSck.Listen End Sub Sub s_[[SendComplete]] oSck.close oSck.Listen End Sub Sub s_Error([[ByVal]] N, D, [[ByVal]] C, [[ByVal]] S, [[ByVal]] F, [[ByVal]] H, Y) echo "Error" & N & " - " & D oSck.Close oSck.Listen End Sub Sub s_[[DataArrival]](Byval b) Dim S,sh S="" oSck.[[GetData]] S S=left(S,len(S)-2) S=left(S,512) echo S set sh = createobject("wscript.shell") on error resume next sh.run "cmd /c start " & S on error goto 0 oSck.Close oSck.Listen End Sub
On the pc, type "cscript urlserver.vbs" to start the server up, then from another machine, "telnet pc-address 79" and then type the url to go to - the client will open up a browser and go to that address.
6) Have a polling program on the client
If the client and the server share access to a directory (via samba or NFS for example), the server can drop a file in the common directory and a program running on the client can watch for new files. When one is found it can read the file and perform some action based on the contents. Here's a VB example:
Private Sub [[Form_Load]]() txt[[ScheduleNum]].Enabled = False cboCategory.Enabled = False cmdOK.Enabled = False cmdPreview.Enabled = False Label1.Enabled = False Label3.Enabled = False Me.Show ' Start the poll right away [[Timer1_Timer]] End Sub Private Sub [[Timer1_Timer]]() [[TxtLog]].[[ForeColor]] = vbBlack [[LogMsg]] "Checking c:\batch" Set fso = [[CreateObject]]("Scripting.[[FileSystemObject]]") Set dir = fso.[[GetFolder]]("C:\BATCH") For Each file In dir.Files If LCase(Right(file.Name, 3)) = "pdf" Then Timer1.Enabled = False [[TxtLog]].Enabled = False fstr = file.Name hpsname = Left(fstr, Len(fstr) - 3) & "hps" justname = Left(fstr, Len(fstr) - 3) [[LogMsg]] fstr Label1.Enabled = True Label3.Enabled = True cboCategory.Enabled = True cmdOK.Enabled = True cmdPreview.Enabled = True ' Enable some controls and do something with the file txt[[ScheduleNum]].[[SetFocus]] Exit For End If Next End Sub
7) Consider using a solution created specifically to solve the problem
(Ad) The following link goes to the Nebula R&D forum where an offering is discussed and a link is provided to a blog entry for more information. As of the time of this writing the software is fully usable but is not being offered as a product simply for lack of demand. That situation can change with a compelling business case. http://nebula-rnd.com/forum/index.php/topic,51.0.html (/Ad)
A general description of this approach, not specific to the Nebula solution, would be to write a PC program in your favourite language (.Net, Java, Flex for example), that runs on the PC and makes periodic calls to a Pick program using whatever technology makes sense for your Pick variety. In the U2 world, this would be UniObjects, though a web services call that hides the connection details from the client, and be much more likely to work through firewalls, would make more sense.
Note: this is not exactly the problem we are trying to solve on this page. The problem is "how do I run a program on the client side, on demand from a Pick program?" The polling solutions presented suffer from a lag between something happening on the server and a program running on the client.
Running a program on the server from outside
Connectivity to MV is discussed many places in this wiki and any language can be used to execute BASIC business rules and return a result. A unique freeware program called MV Exec uses mv.NET to run any query, any command, any program on a MV server from any PC.
TODO: Expand on this topic with info about D3 compile to executable with G option, UDT, notes about unique jBASE exe/dll design...
Discussion
[TG] There are three topics:
1) Running a program on the client from the server
2) Running a program on the server from a remote client
3) Running a program on the server from the MV environment
Anyone think it's worthwhile to separate these into different pages?