代码之家  ›  专栏  ›  技术社区  ›  Jonik

从Java调用Windows内核函数最简单的方法是什么?

  •  7
  • Jonik  · 技术社区  · 16 年前

    在寻找如何做到这一点的过程中,我发现了一些关于不同选项的模糊讨论,比如JNI和JNA,但没有太多具体的例子。

    上下文:如果Java File.renameTo() 不能做它的工作(无论什么原因; it is a little problematic )我想回到直接使用这个本机windows函数,它在kernel32.dll中定义。( from this answer ):

    BOOL WINAPI MoveFile(
      __in  LPCTSTR lpExistingFileName,
      __in  LPCTSTR lpNewFileName
    );
    

    因此,使用任何方法,您将如何从Java代码中调用该函数?我在寻找最简单的方法,用最少的非Java代码或额外的步骤(例如编译或部署)。

    3 回复  |  直到 16 年前
        1
  •  7
  •   McDowell rahul gupta    16 年前

    如果您使用JNA,请考虑调用 MoveFileW 直接-它省去了在Unicode和ANSI调用之间进行选择时必须提供配置信息的麻烦。

    import java.io.*;
    import com.sun.jna.*;
    
    public class Ren {
    
      static interface Kernel32 extends Library {
        public static Kernel32 INSTANCE = (Kernel32) Native
            .loadLibrary("Kernel32", Kernel32.class);
    
        public static int FORMAT_MESSAGE_FROM_SYSTEM = 4096;
        public static int FORMAT_MESSAGE_IGNORE_INSERTS = 512;
    
        public boolean MoveFileW(WString lpExistingFileName,
            WString lpNewFileName);
    
        public int GetLastError();
    
        public int FormatMessageW(int dwFlags,
            Pointer lpSource, int dwMessageId,
            int dwLanguageId, char[] lpBuffer, int nSize,
            Pointer Arguments);
      }
    
      public static String getLastError() {
        int dwMessageId = Kernel32.INSTANCE.GetLastError();
        char[] lpBuffer = new char[1024];
        int lenW = Kernel32.INSTANCE.FormatMessageW(
            Kernel32.FORMAT_MESSAGE_FROM_SYSTEM
                | Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS, null,
            dwMessageId, 0, lpBuffer, lpBuffer.length, null);
        return new String(lpBuffer, 0, lenW);
      }
    
      public static void main(String[] args) throws IOException {
        String from = ".\\from.txt";
        String to = ".\\to.txt";
        new FileOutputStream(from).close();
        if (!Kernel32.INSTANCE.MoveFileW(new WString(from),
            new WString(to))) {
          throw new IOException(getLastError());
        }
      }
    }
    

    编辑:我在检查代码后编辑了我的答案-我错认为在签名中使用char[]-最好使用 WString .

        2
  •  1
  •   Matthew Flaschen    16 年前

    如果这真的是必要的(Renameto不起作用,你肯定movefile会的),我会用 JNA . 看起来大部分工作已经在com.muommander.file.util中完成了。 Kernel32.java / Kernel32API.java .

        3
  •  1
  •   jitter    16 年前

    基于 NativeCall library 我做了以下的 POC Application .

    它使用 MoveFileA 函数从 KNEL32.DLL

    它是完整的工作样本,有run.bat和所有jar和dll。

    它将包含的test.txt移动到test2.txt


    如果你不喜欢NativeCall库版本,我做了另一个 POC Application 基于/继续于 Java Native Access (JNA) 图书馆。这一次 莫菲里亚 MoveFileW 实施和演示。