2

我需要为某个文件类型注册文件关联——事实上,我只需要启动一个带有某些参数和该文件名称的某个 Java 程序。

我得到了以下几点:

// in fff-assoc.cmd file:
assoc .fff=SomeFile
ftype SomeFile=java -jar some.jar <arguments1> "%%1" <arguments2>

它适用于 ASCII 文件名。但是当我尝试双击名称中包含非 ASCII 符号的文件时,传递的参数看起来像“????” (每个字符的 int 值 = 63)。

我该如何解决这些关联?

4

3 回答 3

2

如果 bobince 说的是准确的,并且您不能可靠地将数据直接传递给 java,则另一种解决方案是用另一种语言(例如 C、C++ 或 C#)编写一个小的“shim”程序。

这个想法是程序将输入获取为 UNICODE,对其进行编码,以便仅使用 ASCII 字符(例如,通过使用 base64,或者甚至像将每个字符编码为其数字等价物一样简单),然后将命令行参数组装为使用 CreateProcess 使用并启动 java 本身。

您的 Java 代码可以“撤消”编码,重构 UNICODE 名称并继续使用它。这是一种迂回的方式,需要为您的软件添加一个额外的组件,但它应该可以解决上面详述的限制,如果这确实是一个实际限制的话。

更新:这是 shim 程序的基本代码。它将输入编码为整数序列,用冒号分隔。它在错误检查方面没有多大作用,您可能希望稍微改进它,但它至少应该让您开始并朝着正确的方向前进。

您应该获取 Visual Studio Express(如果您还没有 Visual Studio)并创建一个新的 Visual C++ 项目,选择“Win32”并选择“Win32 项目”。选择“Win32 应用程序”。创建项目后,将显示的 .cpp 文件中的所有内容替换为以下代码:

#include "stdafx.h"
#include <string>

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR lpCmdLine, int)
{
    std::string filename;

    while((lpCmdLine != NULL) && (*lpCmdLine != 0))
    {
        if(filename.length() != 0)
            filename.append(":");

        char buf[32];

        sprintf(buf, "%u", (unsigned int)(*lpCmdLine++));

        filename.append(buf);   
    }

    if(filename.length() == 0)
        return 0;

    PROCESS_INFORMATION pi;
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));

    STARTUPINFOA si;
    memset(&si, 0, sizeof(STARTUPINFOA));
    si.cb = sizeof(STARTUPINFOA);

    char *buf = new char[filename.length() + 256]; // ensure that 256 is enough for your extra arguments!

    sprintf(buf, "java.exe -jar some.jar <arguments1> \"%s\" <arguments2>", filename.c_str());

    // CHECKME: You hard-coded the path for java.exe here. While that may work on your system
    // is it guaranteed that it will work on every system?

    if(CreateProcessA("C:\\Program Files\\Java\\jre7\\bin\\java.exe", buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
    {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }

    delete[] buf;

    return 0;
}

您应该能够相当容易地弄清楚如何编译等细节。

于 2012-11-24T10:29:27.453 回答
1

我只需要使用某些参数和该文件的名称启动某个 Java 程序。

不幸的是,由于 Java 用于接收参数输入(以及其他内容)的标准 C 库的 MS 实现,这种“公正”实际上是不可能的。除非您绕过标准 Java 或 C 接口直接使用本机 Win32 API,

有关背景,请参阅此问题

于 2012-11-22T15:31:57.777 回答
1

从命令行调用 java 时,可以指定参数的编码(将用于在 中创建字符串args[]):

java -jar -Dsun.jnu.encoding=cp1252 yourFileName

使用非 ASCII 字符时,指定的字符集会影响args[0]. 不确定这是否适用于文件关联。

注意:我不确定该参数还有什么其他用途 -这篇文章似乎没有说。

于 2012-11-24T09:57:26.090 回答