MT4通过DLL调用Java程序闪退问题求助
MT4调用DLL启动Java Jar文件失败,进程一闪而过
我使用Windows 11 Home系统,希望通过标准输入输出管道实现MetaTrader4(MT4)与自研Java应用的通信,当前尝试通过MT4调用DLL来启动.jar文件。但启动MQL脚本并成功导入DLL后,仅出现一闪而过的控制台窗口,任务管理器中也找不到对应线程。
我的代码
Java代码
import javax.swing.*; public class SystemOutTest { public static void main(String[] args) throws InterruptedException { JFrame frame = new JFrame("Text Window"); JLabel label = new JLabel("Hello, World!"); frame.add(label); frame.setSize(200, 100); frame.setVisible(true); Thread.sleep(9000); } }
Delphi/Pascal DLL代码
library JarLauncher; uses Windows, ShellAPI; function LaunchJar(const AFileName: string; const AArguments: string): Integer; stdcall; var JavaPath: string; begin JavaPath := 'C:\Program Files (x86)\Java\jre1.8.0_361\bin\java.exe'; Result := ShellExecute( 0, nil, 'java.exe', '-Xmx1024M -Xms1024M -jar testpilot.jar', nil, SW_SHOW ); end; exports LaunchJar; begin end.
MQL代码
#import "JarLauncher.dll" int LaunchJar(string AFileName, string AArguments); #import void OnInit() { // string jarFile = "C:\\path\\to\\testpilot.jar"; string jarFile = "testpilot.jar"; string arguments = ""; int result = LaunchJar(jarFile, arguments); if (result <= 0) { Print("Failed to launch JAR file!"); } else { Print(result); } Sleep(9000); }
已知信息
- MT4为32位程序,已将Lazarus、Eclipse及JRE均调整为32位版本,无报错(曾解决ERR 126文件未找到问题,确认MQL可正常找到并执行DLL)
- MT4控制台输出:
2023.04.15 20:43:28.558 maybeload [DJI30],H1: 42 2023.04.15 20:43:26.064 Expert maybeload [DJI30],H1: loaded successfully
- 推测42是进程句柄而非错误码
- 已尝试调整ShellExecute参数:使用java.exe全路径、javaw.exe、修改显示参数(SW_SHOWNORMAL、SW_SHOWDEFAULT等),均无改善
- 手动通过CMD或双击可正常启动.jar文件并显示窗口,怀疑是MQL线程处理问题
解决方案
问题根源
- ShellExecute参数未正确使用:DLL中定义了Java全路径但未实际调用,而是直接传
java.exe,MT4的工作目录不是Java安装目录,导致系统找不到可执行文件,进程启动后立即退出。 - 工作目录不匹配:MT4启动DLL时的工作目录是自身安装/数据目录,若Jar文件不在该目录下,Java无法找到目标文件。
- 字符串编码冲突:MQL字符串为ANSI编码,Delphi默认字符串为Unicode,参数传递时可能出现乱码,导致命令解析失败。
具体修复步骤
1. 修正DLL代码(兼容ANSI编码+明确路径)
library JarLauncher; uses Windows, ShellAPI, SysUtils; function LaunchJar(const AFileName: PAnsiChar; const AArguments: PAnsiChar): Integer; stdcall; var JavaPath: AnsiString; CmdLine: AnsiString; WorkDir: AnsiString; begin // 使用32位Java全路径 JavaPath := 'C:\Program Files (x86)\Java\jre1.8.0_361\bin\java.exe'; // 拼接命令行:传入Jar绝对路径 CmdLine := '-Xmx1024M -Xms1024M -jar ' + AFileName; if AArguments <> '' then CmdLine := CmdLine + ' ' + AArguments; // 提取Jar文件所在目录作为工作目录 WorkDir := ExtractFilePath(AFileName); // 使用ShellExecuteA确保ANSI编码兼容MQL Result := ShellExecuteA( 0, nil, PAnsiChar(JavaPath), PAnsiChar(CmdLine), PAnsiChar(WorkDir), SW_SHOWNORMAL ); end; exports LaunchJar; begin end.
2. 修正MQL代码(传入Jar绝对路径)
#import "JarLauncher.dll" int LaunchJar(string AFileName, string AArguments); #import void OnInit() { // 替换为你的Jar文件绝对路径 string jarFile = "C:\\path\\to\\testpilot.jar"; string arguments = ""; int result = LaunchJar(jarFile, arguments); // ShellExecute返回值<=32表示错误 if (result <= 32) { Print("Failed to launch JAR file! Error code: ", result); } else { Print("Launch succeeded, handle: ", result); } Sleep(9000); }
3. 备选方案:改用CreateProcess直接启动进程
若ShellExecute仍有问题,使用CreateProcessA跳过Shell解析,更稳定:
library JarLauncher; uses Windows, SysUtils; function LaunchJar(const AFileName: PAnsiChar; const AArguments: PAnsiChar): Integer; stdcall; var JavaPath: AnsiString; CmdLine: AnsiString; StartupInfo: TStartupInfoA; ProcessInfo: TProcessInformation; WorkDir: AnsiString; begin Result := 0; JavaPath := 'C:\Program Files (x86)\Java\jre1.8.0_361\bin\java.exe'; // 给路径加双引号,避免空格解析错误 CmdLine := '"' + JavaPath + '" -Xmx1024M -Xms1024M -jar "' + AFileName + '"'; if AArguments <> '' then CmdLine := CmdLine + ' ' + AArguments; WorkDir := ExtractFilePath(AFileName); ZeroMemory(@StartupInfo, SizeOf(StartupInfo)); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_SHOWNORMAL; if CreateProcessA( nil, PAnsiChar(CmdLine), nil, nil, False, 0, nil, PAnsiChar(WorkDir), StartupInfo, ProcessInfo ) then begin Result := Integer(ProcessInfo.hProcess); // 关闭多余句柄,避免资源泄漏 CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); end else begin Result := GetLastError(); end; end; exports LaunchJar; begin end.
验证步骤
- 重新编译DLL和Java Jar文件
- 确保Jar文件位于MQL代码指定的绝对路径下
- 启动MT4加载脚本,查看控制台输出及Java窗口是否正常弹出
内容的提问来源于stack exchange,提问作者Duke
相关产品推荐
相关产品推荐

