使用 CreateProcess 从 Win32 C++ 应用程序启动 Java 应用程序时出错

Posted

技术标签:

【中文标题】使用 CreateProcess 从 Win32 C++ 应用程序启动 Java 应用程序时出错【英文标题】:Error launching a Java app from a Win32 C++ app using CreateProcess 【发布时间】:2010-02-26 04:10:48 【问题描述】:

我正在尝试使用以下代码从 C++ 应用程序启动 Java 应用程序:

#include <windows.h>
#include <memory.h>
#include <tchar.h>

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) 
    STARTUPINFOW        siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;

    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 

    if (CreateProcess(TEXT("c:\\java\\jre\\bin\\java.exe"), TEXT("-jar testapp.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) 
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    

    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);

    return 0;

当我构建并运行程序时,我收到以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError: testapp/jar
Caused by: java.lang.ClassNotFoundException: testapp.jar
        at: java.net.URLClassLoader$1.run(Uknown Source)
        at: java.security.AccessController.doPrivileged(Native Method)
        at: java.net.URLClassLoader.findClass(Uknown Source)
        at: java.lang.ClassLoader.loadClass(Uknown Source)
        at: sun.misc.Launcher$AppClassLoader.loadClass(Uknown Source)
        at: java.lang.ClassLoader.loadClass(Uknown Source)
Could not find the main class: testapp.jar. Program will exit.

testapp.jar 文件是从 Eclipse 项目中导出的可运行 JAR 文件,其中包含一个类:

public class Test 
    public static void main(String[] args) 
        System.out.println("test");
    

EXE 和 JAR 文件位于完全相同的文件夹中,我正在从命令行运行 EXE。如果我通过将c:\java\jre\bin\java.exe -jar testapp.jar 放入命令提示符直接运行 JAR,一切都会按预期工作。

有人知道这里发生了什么吗?

编辑:谢谢大家的帮助,但看起来我现在可以正常工作了。

【问题讨论】:

【参考方案1】:

解决了。我用过:

if (CreateProcess(TEXT("C:\\Program Files\\Java\\jre6\\bin\\java.exe"), TEXT(" -jar test.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) 
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    

而你曾经使用过:

if (CreateProcess(TEXT("C:\\Program Files\\Java\\jre6\\bin\\java.exe"), TEXT("-jar test.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) 
        MessageBox(NULL, L"Could not load app", L"Error", 0);
    

当我使用它时,它会复制您的错误。区别在于-jar 开关前面有一个空格,为什么会这样,我不知道,我无意中弄错了它!

【讨论】:

老实说,为什么我现在一直在躲避我。如果我发现了,我会更新答案。 @gf 我知道。通过编辑错误发现,所以我真的不值得 +1 或答案,但无论如何我已经达到了代表限制。关于为什么会这样的任何想法? @Ninefingers:快速测试表明 Win32 API 非常聪明,如果您使用前导空格,它会将空条目作为 argv 的第一个条目传递... @gf。哦。有趣...我确实尝试将参数字符串作为 java.exe -jar ...按原样使用程序字符串,但这又产生了错误。嗯。【参考方案2】:

我只需要改变调用 CreateProcess 的方式:

wchar_t *command = (wchar_t*)calloc(512, sizeof(wchar_t));

wsprintf(command, TEXT("c:\\java\\jre\\bin\\java.exe -jar testapp.jar"));

if (CreateProcess(NULL, command, NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo) == false) 

【讨论】:

这个允许你在命令中只使用“java.exe -jar testapp.jar”与“c:\\java\\jre\\bin\\java.exe -jar testapp” 。罐”。 support.microsoft.com/en-us/kb/175986【参考方案3】:

CreateProcess() 的文档指定了参数lpCurrentDirectory

进程当前目录的完整路径。该字符串还可以指定 UNC 路径。 如果此参数为NULL,则新进程将与调用进程具有相同的当前驱动器和目录。

您的摘录缺少path 的定义,但很可能设置不正确。

【讨论】:

抱歉,我粘贴的代码有错误。该行应该是: CreateProcess(TEXT("c:\\java\\jre\\bin\\java.exe"), TEXT("-jar testapp.jar"), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &siStartupInfo, &piProcessInfo)【参考方案4】:

尝试在-jar 之后指定JAR 的目录。它可能与您当前的工作目录有关...

【讨论】:

以上是关于使用 CreateProcess 从 Win32 C++ 应用程序启动 Java 应用程序时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ProcMon 检查 Win32 CreateProcess() 失败的原因。排除 GetLastError()

Win32 API 类似于 CreateProcess,但适用于 bat/cmd/等。 (即使用 PATHEXT)

为啥 CreateProcess 给出错误 193(%1 不是有效的 Win32 应用程序)

WIN32创建进程CreateProcess

CreateProcess失败;代码193.%/不是有效的win32应用程序

DBeaver执行sql脚本报错:CreateProcess error=193, %1 不是有效的 Win32 应用程序。