diff --git a/resources/IBC.jar b/resources/IBC.jar index 0904b56..c3d106e 100644 Binary files a/resources/IBC.jar and b/resources/IBC.jar differ diff --git a/resources/StartGateway.bat b/resources/StartGateway.bat index ea7c683..9b2cdac 100644 --- a/resources/StartGateway.bat +++ b/resources/StartGateway.bat @@ -35,7 +35,7 @@ set TWS_MAJOR_VRSN=978 set CONFIG=%USERPROFILE%\Documents\IBC\config.ini set TRADING_MODE= set TWOFA_TIMEOUT_ACTION=exit -set IBC_PATH=%SYSTEMDRIVE%\IBC +set IBC_PATH=%~dp0. set TWS_PATH=%SYSTEMDRIVE%\Jts set TWS_SETTINGS_PATH= set LOG_PATH=%IBC_PATH%\Logs @@ -45,6 +45,7 @@ set FIXUSERID= set FIXPASSWORD= set JAVA_PATH= set HIDE= +set PRESS_ANY_KEY_ON_ERROR=1 :: PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE !! @@ -72,9 +73,9 @@ set HIDE= :: This file should be in a folder in your personal filestore, so that :: other users of your computer can't access it. This folder and its :: contents should also be encrypted so that even users with administrator -:: privileges can't see the contents. Note that you can use the HOMEDRIVE and -:: HOMEPATH environment variables to address the root of your personal -:: filestore (they are set automatically by Windows). +:: privileges can't see the contents. Note that you can use the USERPROFILE +:: environment variable to address the root of your personal filestore +:: (they are set automatically by Windows). :: TRADING_MODE @@ -179,6 +180,15 @@ set HIDE= :: this setting has no effect.) +:: PRESS_ANY_KEY_ON_ERROR +:: +:: If set to 1, the diagnostic window will remain open and prompt user for +:: pressing any key in order to let them read error message. This behaviour +:: however is not desirable when the script runs in non-interactive mode +:: (e.g. when it is started by task scheduler). In such case please +:: set it to 0 or make it empty. + + :: End of Notes: ::============================================================================== diff --git a/resources/StartTWS.bat b/resources/StartTWS.bat index 66d3992..0b3d64d 100644 --- a/resources/StartTWS.bat +++ b/resources/StartTWS.bat @@ -25,7 +25,7 @@ set TWS_MAJOR_VRSN=978 set CONFIG=%USERPROFILE%\Documents\IBC\config.ini set TRADING_MODE= set TWOFA_TIMEOUT_ACTION=exit -set IBC_PATH=%SYSTEMDRIVE%\IBC +set IBC_PATH=%~dp0. set TWS_PATH=%SYSTEMDRIVE%\Jts set TWS_SETTINGS_PATH= set LOG_PATH=%IBC_PATH%\Logs @@ -33,6 +33,7 @@ set TWSUSERID= set TWSPASSWORD= set JAVA_PATH= set HIDE= +set PRESS_ANY_KEY_ON_ERROR=1 :: PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE !! @@ -60,9 +61,9 @@ set HIDE= :: This file should be in a folder in your personal filestore, so that :: other users of your computer can't access it. This folder and its :: contents should also be encrypted so that even users with administrator -:: privileges can't see the contents. Note that you can use the HOMEDRIVE and -:: HOMEPATH environment variables to address the root of your personal -:: filestore (they are set automatically by Windows). +:: privileges can't see the contents. Note that you can use the USERPROFILE +:: environment variable to address the root of your personal filestore +:: (they are set automatically by Windows). :: TRADING_MODE @@ -157,6 +158,15 @@ set HIDE= :: this setting has no effect.) +:: PRESS_ANY_KEY_ON_ERROR +:: +:: If set to 1, the diagnostic window will remain open and prompt user for +:: pressing any key in order to let them read error message. This behaviour +:: however is not desirable when the script runs in non-interactive mode +:: (e.g. when it is started by task scheduler). In such case please +:: set it to 0 or make it empty. + + :: End of Notes: ::============================================================================== diff --git a/resources/Stop.bat b/resources/Stop.bat index 698ce63..74cae7e 100644 --- a/resources/Stop.bat +++ b/resources/Stop.bat @@ -1,51 +1,146 @@ -@echo off - -:: Sends a STOP command to the specified instance of IBC to cause it to -:: initiate a tidy closedown of TWS or Gateway. - - -:: You may need to change this line. Set it to the name or IP address of the -:: computer that is running IBC. Note that you can use the local loopback -:: address (127.0.0.1) if IBC is running on the current machine. - -set ServerAddress=127.0.0.1 - - -:: You may need to change this line. Make sure it's set to the value of the -:: CommandServerPort setting in config.ini: - -set CommandServerPort=7462 - - -:: You may need to change this line. Make sure it's set to the location of the -:: IBC files: - -set IBC_PATH=%SYSTEMDRIVE%\IBC - - -:: IMPORTANT NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -:: ============== -:: -:: The following uses the telnet utility, which is not enabled in -:: Windows 'out of the box'. To enable it, run the 'Programs and Features' applet in -:: Control Panel. Click the 'Turn Windows features on or off' link in the left hand -:: panel. Then locate the 'Telnet client' entry in the list of Windows features and -:: ensure the checkbox in the entry is ticked. Click 'OK' and Windows will -:: enable it. This command file should then run successfully. - - -:: You shouldn't need to change anything below this line. -::============================================================================== - - -:: open a telnet window with a session to IBC -set TITLE=Stop TWS or Gateway %RANDOM%%RANDOM%%RANDOM% -start "%TITLE%" telnet %ServerAddress% %CommandServerPort% - -:: send the required command to IBC -cscript %IBC_PATH%\Scripts\SendStopCommand.vbs "%TITLE%" - - -:: Acknowledgement: many thanks for the help contained in Mukul Goel's answer to this question at: -:: http://stackoverflow.com/questions/13197376/is-it-possible-to-use-a-batch-file-to-establish-a-telnet-session-send-a-command - +@echo off +setlocal enableextensions enabledelayedexpansion + + +::=============================================================================+ +:: + +:: Stops Interactive Brokers' IB Gateway or Trader Workstation (TWS). + +:: + +::=============================================================================+ + + +set TWS_MAJOR_VRSN=978 +set CONFIG=%USERPROFILE%\Documents\IBC\config.ini +set TRADING_MODE= +set TWOFA_TIMEOUT_ACTION=exit +set IBC_PATH=%~dp0. +set TWS_PATH=%SYSTEMDRIVE%\Jts +set TWS_SETTINGS_PATH= +set LOG_PATH=%IBC_PATH%\Logs +set TWSUSERID= +set TWSPASSWORD= +set FIXUSERID= +set FIXPASSWORD= +set JAVA_PATH= +set HIDE= +set PRESS_ANY_KEY_ON_ERROR=1 + + +:: PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE !! +::============================================================================== + +:: Notes: +:: + +:: TWS_MAJOR_VRSN +:: +:: Specifies the major version number of Gateway to be run. If you are +:: unsure of which version number to use, run the Gateway manually from the +:: icon on the desktop, then click Help > About IB Gateway. In the +:: displayed information you'll see a line similar to this: +:: +:: Build 954.2a, Oct 30, 2015 4:07:54 PM +:: +:: Here the major version number is 954. Do not include the rest of the +:: version number in this setting. + + +:: CONFIG +:: +:: This is the location and filename of the IBC configuration file. +:: This file should be in a folder in your personal filestore, so that +:: other users of your computer can't access it. This folder and its +:: contents should also be encrypted so that even users with administrator +:: privileges can't see the contents. Note that you can use the USERPROFILE +:: environment variable to address the root of your personal filestore +:: (they are set automatically by Windows). + + +:: IBC_PATH +:: +:: The folder containing the IBC files. + + +:: TWS_PATH +:: +:: The folder where TWS is installed. The TWS installer always installs to +:: C:\Jts. Note that even if you have installed from a Gateway download +:: rather than a TWS download, you should still use this default setting. +:: It is possible to move the TWS installation to a different folder, but +:: there are virtually no good reasons for doing so. + + +:: TWS_SETTINGS_PATH +:: +:: The folder where TWS is to store its settings. This setting is ignored +:: if the IbDir setting in the configuration file is specified. If no value +:: is specified in either place, the settings are stored in the TWS_PATH +:: folder. + + +:: LOG_PATH +:: +:: Specifies the folder where diagnostic information is to be logged while +:: this command file is running. This information is very valuable when +:: troubleshooting problems, so it is advisable to always have this set to +:: a valid location, especially when setting up IBC. You must +:: have write access to the specified folder. +:: +:: Once everything runs properly, you can prevent further logging by +:: removing the value as show below (but this is not recommended): +:: +:: set LOG_PATH= + + +:: JAVA_PATH +:: +:: IB's installer for TWS/Gateway includes a hidden version of Java which +:: IB have used to develop and test that particular version. This means that +:: it is not necessary to separately install Java. If there is a separate +:: Java installation, that does not matter: it won't be used by IBC +:: or TWS/Gateway unless you set the path to it here. You should not do this +:: without a very good reason. + + +:: HIDE +:: +:: If set to YES or TRUE, the diagnostic window that contains information +:: about the running TWS, and where to find the log file, will be minimized +:: to the taskbar. If not set, or set to any other value, the window will be +:: displayed. Values are not case-sensitive so for example yEs and yes will +:: be interpeted as YES. (Note that when the /INLINE argument is supplied, +:: this setting has no effect.) + + +:: PRESS_ANY_KEY_ON_ERROR +:: +:: If set to 1, the diagnostic window will remain open and prompt user for +:: pressing any key in order to let them read error message. This behaviour +:: however is not desirable when the script runs in non-interactive mode +:: (e.g. when it is started by task scheduler). In such case please +:: set it to 0 or make it empty. + + +:: End of Notes: +::============================================================================== + +set APP=STOP +set TITLE=IBC (%APP% %TWS_MAJOR_VRSN%) +if /I "%HIDE%" == "YES" ( + set MIN=/Min +) else if /I "%HIDE%" == "TRUE" ( + set MIN=/Min +) else ( + set MIN= +) + +id / + +if /I "%~1" == "/INLINE" ( + set INLINE=1 + "%IBC_PATH%\scripts\DisplayBannerAndLaunch.bat" %~2 +) else ( + set INLINE=0 + start "%TITLE%" %MIN% "%IBC_PATH%\scripts\DisplayBannerAndLaunch.bat" %~1 +) +exit /B diff --git a/resources/scripts/DisplayBannerAndLaunch.bat b/resources/scripts/DisplayBannerAndLaunch.bat index 4af936d..1d7be53 100644 --- a/resources/scripts/DisplayBannerAndLaunch.bat +++ b/resources/scripts/DisplayBannerAndLaunch.bat @@ -76,6 +76,7 @@ echo + set GW_FLAG= if /I "%APP%" == "GATEWAY" set GW_FLAG=/G +if /I "%APP%" == "STOP" set GW_FLAG=/STOP set PHASE=Running StartIBC.bat set ERROR_MESSAGE= @@ -147,8 +148,10 @@ if defined LOG_FILE ( echo + echo +============================================================================== echo + -echo + Press any key to close this window -pause > NUL +if "%PRESS_ANY_KEY_ON_ERROR%" == "1" ( + echo + Press any key to close this window + pause > NUL +) echo + if "%INLINE%" == "1" exit /B exit diff --git a/resources/scripts/SendStopCommand.vbs b/resources/scripts/SendStopCommand.vbs deleted file mode 100644 index ec8602d..0000000 --- a/resources/scripts/SendStopCommand.vbs +++ /dev/null @@ -1,20 +0,0 @@ -' allow time for telnet session to start and connect -WScript.sleep 200 - -set OBJECT=WScript.CreateObject("WScript.Shell") - -OBJECT.AppActivate WScript.Arguments(0) - -' STOP IBC -OBJECT.SendKeys "STOP{ENTER}" - -' Do not send an EXIT command because IBC always -' closes the connection after receiving a STOP -' command -'OBJECT.SendKeys "EXIT{ENTER}" - -WScript.sleep 200 - -' close telnet window -OBJECT.SendKeys "q{ENTER}" - diff --git a/resources/scripts/StartIBC.bat b/resources/scripts/StartIBC.bat index 63ca404..a223af8 100644 --- a/resources/scripts/StartIBC.bat +++ b/resources/scripts/StartIBC.bat @@ -25,7 +25,7 @@ echo Runs IBC, thus loading TWS or the IB Gateway echo. echo Usage: echo. -echo StartIBC twsVersion [/G ^| /Gateway] [/TwsPath:twsPath] +echo StartIBC twsVersion [/G ^| /Gateway] [/Stop] [/TwsPath:twsPath] echo [/TwsSettingsPath:twsSettingsPath] [/IbcPath:ibcPath] echo [/Config:configfile] [/JavaPath:javaPath] echo [/User:userId] [/PW:password] @@ -38,6 +38,8 @@ echo. echo /G or /Gateway Indicates that the IB Gateway is to be loaded rather echo than TWS echo. +echo /Stop Indicates that the IB Gateway or TWS is to be stopped +echo. echo twsPath Path to the TWS installation folder. Defaults to echo C:\Jts echo. @@ -49,7 +51,7 @@ echo Defaults to C:\IBC echo. echo configfile The location and filename of the IBC echo configuration file. Defaults to -echo ^%%HOMEPATH^%%\Documents\IBC\config.ini +echo ^%%USERPROFILE^%%\Documents\IBC\config.ini echo. echo javaPath Path to the folder containing the java.exe to be used echo to run IBC. Defaults to the java.exe included @@ -104,6 +106,7 @@ set E_LOGIN_DIALOG_DISPLAY_TIMEOUT=1112 set ENTRY_POINT_TWS=ibcalpha.ibc.IbcTws set ENTRY_POINT_GATEWAY=ibcalpha.ibc.IbcGateway +set ENTRY_POINT_STOP=ibcalpha.ibc.IbcStop :: Variables to be derived from arguments set TWS_VERSION= @@ -134,6 +137,8 @@ if /I "%ARG%" == "/G" ( set ENTRY_POINT=%ENTRY_POINT_GATEWAY% ) else if /I "%ARG%" == "/GATEWAY" ( set ENTRY_POINT=%ENTRY_POINT_GATEWAY% +) else if /I "%ARG%" == "/STOP" ( + set ENTRY_POINT=%ENTRY_POINT_STOP% ) else if /I "%ARG:~0,9%" == "/TWSPATH:" ( set TWS_PATH=%ARG:~9% ) else if /I "%ARG:~0,17%" == "/TWSSETTINGSPATH:" ( @@ -258,7 +263,7 @@ if not defined TWS_VERSION ( if not defined TWS_PATH set TWS_PATH=C:\Jts if not defined TWS_SETTINGS_PATH set TWS_SETTINGS_PATH=%TWS_PATH% if not defined IBC_PATH set IBC_PATH=C:\IBC -if not defined CONFIG set CONFIG=%HOMEPATH%\Documents\IBC\config.ini +if not defined CONFIG set CONFIG=%USERPROFILE%\Documents\IBC\config.ini :: In the following we try to use the correct .vmoptions file for the chosen entrypoint :: Note that uninstalling TWS or Gateway leaves the relevant .vmoption file in place, so @@ -293,6 +298,21 @@ if /I "%ENTRY_POINT%" == "%ENTRY_POINT_GATEWAY%" ( set INSTALL4J=%TWS_PATH%\%TWS_VERSION%\.install4j ) ) +if /I "%ENTRY_POINT%" == "%ENTRY_POINT_STOP%" ( + if exist "%TWS_PATH%\%TWS_VERSION%\tws.vmoptions" ( + set TWS_VMOPTS=%TWS_PATH%\%TWS_VERSION%\tws.vmoptions + ) else if exist "%TWS_PATH%\ibgateway\%TWS_VERSION%\ibgateway.vmoptions" ( + set TWS_VMOPTS=%TWS_PATH%\ibgateway\%TWS_VERSION%\ibgateway.vmoptions + ) + + if exist "%TWS_PATH%\%TWS_VERSION%\jars" ( + set TWS_JARS=%TWS_PATH%\%TWS_VERSION%\jars + set INSTALL4J=%TWS_PATH%\%TWS_VERSION%\.install4j + ) else ( + set TWS_JARS=%TWS_PATH%\ibgateway\%TWS_VERSION%\jars + set INSTALL4J=%TWS_PATH%\ibgateway\%TWS_VERSION%\.install4j + ) +) if not exist "%TWS_JARS%" ( set ERROR_MESSAGE=Offline TWS/Gateway version %TWS_VERSION% is not installed: can't find jars folder diff --git a/src/ibcalpha/ibc/DefaultSettings.java b/src/ibcalpha/ibc/DefaultSettings.java index ac62fe9..8924b82 100644 --- a/src/ibcalpha/ibc/DefaultSettings.java +++ b/src/ibcalpha/ibc/DefaultSettings.java @@ -82,8 +82,7 @@ private String getSettingSanitisedValue(String key) { static String generateDefaultIniPath() { if (System.getProperty("os.name").startsWith("Windows")) { - return System.getenv("HOMEDRIVE") + - System.getenv("HOMEPATH") + File.separator + + return System.getenv("USERPROFILE") + File.separator + "Documents" + File.separator + "IBC" + File.separator + "config.ini"; diff --git a/src/ibcalpha/ibc/IbcStop.java b/src/ibcalpha/ibc/IbcStop.java new file mode 100644 index 0000000..583cc84 --- /dev/null +++ b/src/ibcalpha/ibc/IbcStop.java @@ -0,0 +1,78 @@ +// This file is part of IBC. +// Copyright (C) 2004 Steven M. Kearns (skearns23@yahoo.com ) +// Copyright (C) 2004 - 2018 Richard L King (rlking@aultan.com) +// For conditions of distribution and use, see copyright notice in COPYING.txt + +// IBC is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// IBC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with IBC. If not, see . + +package ibcalpha.ibc; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; + +import static ibcalpha.ibc.IbcTws.checkArguments; + +public class IbcStop { + public static void main(String[] args) throws Exception { + if (Thread.getDefaultUncaughtExceptionHandler() == null) { + Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler()); + } + checkArguments(args); + setupDefaultEnvironment(args); + sendStopCommand(); + } + + static void setupDefaultEnvironment(final String[] args) { + IbcTws.printVersionInfo(); + Settings.initialise(new DefaultSettings(args)); + } + + static void sendStopCommand() throws IOException { + final int port = Settings.settings().getInt("CommandServerPort", 0); + if (port == 0) { + Utils.logError("CommandServer is not started because the port is not configured"); + return; + } + InetSocketAddress address = new InetSocketAddress(getInetAddress(Settings.settings().getString("BindAddress", "")), port); + Utils.logToConsole("Connecting to CommandServer: " + address); + try (Socket socket = new Socket()) { + socket.connect(address); + Utils.logToConsole("Connected to CommandServer: " + socket.getLocalSocketAddress() + "=>" + socket.getRemoteSocketAddress()); + try (OutputStream outputStream = socket.getOutputStream()) { + outputStream.write("STOP\n".getBytes(StandardCharsets.US_ASCII)); + } + } + Utils.logToConsole("STOP command is sent successfully"); + } + + static InetAddress getInetAddress(String bindaddr) { + InetAddress result = InetAddress.getLoopbackAddress(); + if (!bindaddr.isEmpty()) { + try { + InetAddress candidate = InetAddress.getByName(bindaddr); + if (!candidate.isAnyLocalAddress()) { + result = candidate; + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + return result; + } +}