ما هي أسهل طريقة لاستدعاء دالة نواة ويندوز من جافا؟
-
05-07-2019 - |
سؤال
وحين تبحث عن كيفية القيام بذلك، لقد وجدت بعض المناقشات غامضة حول خيارات مختلفة، مثل JNI مقابل JNA، ولكن ليس الكثير في الطريق من أمثلة ملموسة.
والسياق: إذا File.renameTo()
جاوة لا تستطيع ان تفعل ذلك من وظيفة (لأي سبب كان، هو قليلا إشكالية )، أود أن يرتد إلى مباشرة باستخدام هذه الوظيفة الأم ويندوز، والذي يعرف في Kernel32.dll (<لأ href = "https://stackoverflow.com/questions/1000183/reliable- ملف renameto-بديل على اساس ويندوز / 1000308 # 1000308 "> من هذه الإجابة ):
BOOL WINAPI MoveFile(
__in LPCTSTR lpExistingFileName,
__in LPCTSTR lpNewFileName
);
وهكذا، باستخدام أي نهج، كيف بالضبط هل نسمي ذلك وظيفة من ضمن التعليمات البرمجية جافا؟ أنا أبحث عن أبسط طريقة، مع الحد الأدنى من غير جافا رمز أو إضافية الخطوات (على سبيل المثال في تجميع أو نشر).
المحلول
إذا كنت أذهب مع الجيش الشعبي اليوغوسلافي، والنظر في الاحتجاج MoveFileW و> مباشرة - أن يحفظ الحاجة إلى توفير معلومات التكوين للاختيار بين المكالمات يونيكود و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());
}
}
}
وتحرير: أنا قد قمت بتعديل جوابي بعد التحقق من كود - كنت مخطئا حول استخدام شار [] في التوقيع - أنه من الأفضل استخدام <لأ href = "https://jna.dev.java.net/ جافادوك / كوم / الشمس / الجيش الشعبي اليوغوسلافي / WString.html "يختلط =" noreferrer "> WString .
نصائح أخرى
إذا كان ذلك ضروريا حقا (renameTo لا يعمل وكنت على يقين سوف MoveFile)، وأود أن استخدام <لأ href = "https://github.com/twall/jna/" يختلط = "نوفولو noreferrer" > JNA . يبدو أن معظم العمل يتم بالفعل في com.mucommander.file.util. <وأ href = "http://trac.mucommander.com/browser/trunk/source/com/mucommander/file/util/Kernel32. جافا "يختلط =" نوفولو noreferrer "> Kernel32.java / <لأ href =" http://trac.mucommander.com/browser/trunk/source/com/mucommander/file/util/Kernel32API.java " يختلط = "نوفولو noreferrer"> Kernel32API.java .
واستنادا إلى مكتبة NativeCall فعلت ما يلي <لأ href = "HTTP: // www.file-upload.net/download-1706268/MoveFile.zip.html "يختلط =" نوفولو noreferrer "> POC تطبيق .
ويستخدم وظيفة MoveFileA
من KERNEL32.DLL م>
ويتعلق الأمر عينة العمل كما كاملة مع run.bat وكل جرة ودلس في المكان.
وهي تتحرك TEST.TXT شملت لtest2.txt
إذا كنت لا تحب إصدار مكتبة NativeCall فعلت آخر POC تطبيق استنادا / resuing على جافا الوصول الأصلي (الجيش الشعبي اليوغوسلافي) المكتبة. يتم تنفيذ هذا MoveFileA
الوقت وMoveFileW
وأظهر.