使用java本机接口获取Windows当前用户

2024-02-21

我试图做一个概念证明,在 cpp 程序中我获取 Windows 用户名,然后使用 Java 本机接口(JNI)从 java 代码调用该程序。现在我到目前为止拥有的是一个示例 JNI hello world 程序,它能够编译和打印 Hello world 或我设置的任何参数。现在,在一个单独的 cpp 片段中,我可以获取当前用户名并且它也可以工作;看起来如下:

#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
    char acUserName[100];
    DWORD nUserName = sizeof(acUserName);
    if (GetUserName(acUserName, &nUserName)) {
        cout << "User name is " << acUserName << "." << endl;
        cin.get();
    }
    return 0;
}

当在命令提示符下使用我的 G++ 编译和执行时,它会正确打印当前用户名。

现在我只想结合这两个程序。当我这样做时如下

public class Sample1
 {
    public native String fetchCurrentUserName();
 
    public static void main(String[] args)
    {
     System.loadLibrary("Sample1");
     Sample1 sample = new Sample1();     
     String  userName   = sample.fetchCurrentUserName();       
     System.out.println("userName: " + userName);
     
    }
 }

这是java部分,cpp部分如下:

 #include "Sample1.h"
 #include <string.h>
 #include <iostream>
 #include <windows.h>
 using namespace std;


  JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName
   (JNIEnv *env, jobject obj) {

    char acUserName[100];
    DWORD nUserName = sizeof(acUserName);
    if (GetUserName(acUserName, &nUserName)) {
        cout << "User name is " << acUserName << "." << endl;
        cin.get();
    }

    const char* userName = acUserName;
    //const char* userName = "acUserName";
    return env->NewStringUTF(userName);
 }
 
 void main(){}

它说这不再编译

Sample1.obj : error LNK2019: unresolved external symbol __imp_GetUserNameA referenced in function Java_Sample1_fetchCurrentUserName
Sample1.dll : fatal error LNK1120: 1 unresolved externals

我使用以下命令来编译 JNI 代码。

cl -I"C:\Program Files\Java\jdk1.8.0_131\include" -I"C:\Program Files\Java\jdk1.8.0_131\include\win32" -LD Sample1.cpp -FeSample1.dll

根据教程https://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html https://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html。现在,从堆栈溢出中的其他几个问题来看,我的程序似乎无法以某种方式链接 Windows 库或领导者。但我不知道如何解决这个问题。有人有什么好主意吗?请让我开心!谢谢你的时间 :D 我调查过JNI中dll文件的链接 https://stackoverflow.com/questions/45904957/linking-of-dll-file-in-jni这与我的问题非常相关。但不确定这些解决方案是否适用于我。

Edit

错误:LNK1120:5 个未解析的外部 https://stackoverflow.com/questions/22757314/error-lnk1120-5-unresolved-externals这个问题有类似的问题,并且似乎有相同的解决方案,正如 Remy 建议的与 Advapi32.lib 链接。至少现在我学到了一些新东西,比如 #pragma 注释和 Advapi32 库的作用。非常感谢!


你的代码compiles美好的。你实际上得到的是linker错误,不是compiler error.

从错误消息中,您可以看到您的 C++ 代码正在尝试调用GetUserNameA()功能。GetUserName()是一个预处理器#define宏在winbase.h(包含在windows.h)决定GetUserNameA() when UNICODE没有定义:

WINADVAPI
BOOL
WINAPI
GetUserNameA (
    __out_ecount_part_opt(*pcbBuffer, *pcbBuffer) LPSTR lpBuffer,
    __inout LPDWORD pcbBuffer
    );
WINADVAPI
BOOL
WINAPI
GetUserNameW (
    __out_ecount_part_opt(*pcbBuffer, *pcbBuffer) LPWSTR lpBuffer,
    __inout LPDWORD pcbBuffer
    );
#ifdef UNICODE
#define GetUserName  GetUserNameW
#else
#define GetUserName  GetUserNameA // <-- HERE!
#endif // !UNICODE

由于没有GetUserNameA()在 C++ 代码中实现的函数,但至少有一个可用的声明(来自winbase.h),编译器发出引用的机器代码GetUserNameA()外部(通过名为__imp_GetUserNameA)。当编译完成后调用链接器时,链接器输出“未解决”错误,因为它无法找到任何实现GetUserNameA函数来满足该参考。

GetUserNameA()是一个 Win32 API 函数,实现于Advapi32.dll。您需要链接到Advapi32.lib从编译器的 Windows SDK 中,以便链接器可以找到以下实现GetUserNameA().

一种方法是添加一个#pragma comment(lib)对 C++ 代码的声明,例如:

#include "Sample1.h"
#include <windows.h>
#include <iostream>

using namespace std;

#pragma comment(lib, "Advapi32.lib") // <-- add this!

JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName(JNIEnv *env, jobject obj) {
    char acUserName[100] = {};
    DWORD nUserName = sizeof(acUserName);
    if (GetUserNameA(acUserName, &nUserName)) {
        cout << "User name is " << acUserName << "." << endl;
    }
    else {
        DWORD dwErr = GetLastError();
        cout << "Unable to get User name, error " << dwErr << "." << endl;
    }

    return env->NewStringUTF(acUserName);
}

void main() {}

或者:

#include "Sample1.h"
#include <windows.h>
#include <iostream>
#include <vector>

using namespace std;

#pragma comment(lib, "Advapi32.lib")

JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName(JNIEnv *env, jobject obj) {
    DWORD nUserName = 100, dwErr;
    std::vector<char> acUserName(nUserName);
    do {
        if (GetUserNameA(&acUserName[0], &nUserName)) {
            cout << "User name is " << &acUserName[0] << "." << endl;
            break;
        }
        dwErr = GetLastError();
        if (dwErr != ERROR_INSUFFICIENT_BUFFER) {
            cout << "Unable to get the User name, error " << dwErr << "." << endl;
            break;
        }
        acUserName.resize(nUserName);
    }
    while (true);

    return env->NewStringUTF(&acUserName[0]);
}

void main() {}

话虽如此,NewStringUTF()需要输入字符串modified UTF-8 https://docs.oracle.com/javase/10/docs/api/java/io/DataInput.html#modified-utf-8格式。然而,GetUserNameA()输出 ANSI 格式(因此A其名称),而不是 UTF-8,更不用说modifiedUTF-8。 Windows没有这个概念modified完全是UTF-8。仅当用户名中不包含任何非 ASCII 字符时,您的代码才能正常工作。

你的 C++ 代码确实应该调用GetUserNameW()相反,它以 UTF-16 格式输出。然后你可以使用NewString()代替NewStringUTF()(Java 字符串无论如何都使用 UTF-16),例如:

#include "Sample1.h"
#include <windows.h>
#include <iostream>

using namespace std;

#pragma comment(lib, "Advapi32.lib")

JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName(JNIEnv *env, jobject obj) {
    WCHAR acUserName[100];
    DWORD nUserName = 100;
    if (GetUserNameW(acUserName, &nUserName)) {
        --nUserName; // ignore the null terminator
        wcout << L"User name is " << acUserName << L"." << endl;
    }
    else
    {
        nUserName = 0;
        DWORD dwErr = GetLastError();
        cout << "Unable to get the User name, error " << dwErr << "." << endl;
    }

    return env->NewString(reinterpret_cast<jchar*>(acUserName), nUserName);
}

void main() {}

或者:

#include "Sample1.h"
#include <windows.h>
#include <iostream>
#include <vector>

using namespace std;

#pragma comment(lib, "Advapi32.lib")

JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName(JNIEnv *env, jobject obj) {
    DWORD nUserName = 100, dwErr;
    std::vector<WCHAR> acUserName(nUserName);
    do {
        if (GetUserNameW(&acUserName[0], &nUserName)) {
            --nUserName; // ignore the null terminator
            wcout << L"User name is " << &acUserName[0] << L"." << endl;
            break;
        }
        dwErr = GetLastError();
        if (dwErr != ERROR_INSUFFICIENT_BUFFER) {
            nUserName = 0;
            cout << "Unable to get the User name, error " << dwErr << "." << endl;
            break;
        }
        acUserName.resize(nUserName);
    }
    while (true);

    return env->NewString(reinterpret_cast<jchar*>(&acUserName[0]), nUserName);
}

void main() {}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用java本机接口获取Windows当前用户 的相关文章

  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 警告:无法更改每个人的权限:

    当运行 Java 快速入门示例时https developers google com drive web quickstart java hl hu https developers google com drive web quicks
  • 公共方法与公共 API

    在干净的代码书中 有一个观点是 公共 API 中的 Javadocs 同样 Effective java 一书也有这样的内容 项目 56 为所有公开的 API 元素编写文档注释 所以这就是我的问题 所有公共方法都被视为公共 API 吗 它们
  • 如何用表达式语言获取布尔属性?

    如果我有一堂这样的课 class Person private int age public int getAge return age public boolean isAdult return age gt 19 我可以得到age像这样
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • Java:使用 Graph API 在线更新 Sharepoint 上的 docx 文件

    我在使用 Java 在线更新 Sharepoint 上的 docx 文件时遇到问题 首先 我检查了构建 PUT 请求的 URL 此处 并使用此请求 PUT drives drive id items item id content 我首先使
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • Java、Spring、Hibernate找不到org.springframework.orm.hibernate3.LocalSessionFactoryBean

    我正在尝试制作 spring hibernate ant 项目 目前我收到此错误 HTTP Status 500 type Exception report message description The server encountere
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐

  • 将图像上传到 Google 云端硬盘后清除表单字段

    几天来我一直在努力确保在向谷歌驱动器提交 jpg 后 它会清理表单字段并为下一次插入下一条记录做好准备 它复制文件但不重置该字段 我想要的是 一旦他上传文件 他就会重置表单字段 而无需重新加载它等待下一个上传 这个例子是我从互联网上获取的
  • 如何从 fstream 中准确读取 128 个字节到字符串对象中? [复制]

    这个问题在这里已经有答案了 如何从 fstream 中准确读取 128 个字节到字符串对象中 我编写了一些代码来读取文件的前 128 个字节并打印它 然后读取文件的最后 128 个字节并打印它 最后一部分有效 因为您可以轻松迭代到 EOF
  • 将屏幕坐标转换为 Metal 的标准化设备坐标

    我正在尝试使用用户触摸来渲染 2D 三角形 因此 我将让用户触摸屏幕上的三个点 这些点将用作三角形的顶点 您已经意识到您需要返回剪辑空间坐标 技术上未标准化的设备坐标 https stackoverflow com questions 21
  • iTunes Connect 中的应用内购买。如何使应用内购买“清仓出售”?

    我正在尝试将应用程序内购买添加到已在应用程序商店出售的应用程序中 以便下次更新 我以前从未添加过任何应用内购买 我正在使用 MKStoreKit 来处理应用内购买 因此我认为一切都应该在编码方面进行 当我的应用程序启动时 我查询可用的应用程
  • 我无法在window平台上使用pthread

    我的环境是 Windows 8 1 64 位 并使用 Visual Studio 2010 我确实将所有 dll 文件放在 system32 SYSWOW64 中 因为我使用 win8 64 位 并将 x64 系统的 lib 文件与 VC
  • Java 编译器抱怨未报告的 IOException

    我正在尝试编写一种列出目录中所有非隐藏文件的方法 但是 当我添加条件时 Files isHidden filePath 我的代码无法编译 编译器返回以下错误 java lang RuntimeException Uncompilable s
  • 范围 A 到 B,其中 F# 中 A > B

    我刚刚在 F 中发现了一些我称之为怪癖的东西 想知道它是设计使然还是错误 如果是设计使然 为什么会这样 如果编写任何第一项大于第二项的范围表达式 则返回的序列为空 看一下反射器表明这是设计使然 但我真的找不到为什么必须如此的原因 重现它的一
  • 使用 python fileinput 模块时跳过第一行的优雅方法?

    使用时是否有一种跳过文件第一行的优雅方法python文件输入模块 我有数据文件 其中数据格式良好 但第一行是标题 使用fileinput如果该行似乎不包含数据 我将必须包含检查和丢弃行 问题是它会对文件的其余部分应用相同的检查 和read
  • 时间轴视图、日视图、周视图、月视图并添加事件日历颤动库? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我在寻找Flutter 中的日历库它支持网络和移动设备 日历必须具有以下所有视图 时间表视图 日视图
  • 加载之前的Javascript?

    onLoad onPageShow 之前是否有任何事件处理程序 onLoad 的问题是 如果显示有任何变化 页面将原样显示 直到完全加载 然后脚本才会运行 确保它尽快运行的最佳方法是什么 如果你把 JavaScript声明 而不是函数定义
  • 如何使用 Carrierwave + FactoryGirl 测试上传

    我想为我的应用程序创建一些测试 但出现以下错误 1 User feeds ordering should order feeds by id desc Failure Error post 1 FactoryGirl create post
  • 使用Drools 6 Maven架构完全离线

    我正在使用 Drools 6 0 1 并利用新的基于 Maven 的架构来部署我的规则 该项目的 POM 如下所示 我用参数启动项目 Dkie maven settings custom X maven2 settings xml 为 Dr
  • Weblogic 12c:如何将“活动配置文件”传递给 Spring Boot 应用程序?

    我正在开发一个 Spring Boot 应用程序 并且我have让它在我们的Weblogic 12c服务器 如战争 我试图找到一种方法来传递默认值弹簧活动剖面 info here http docs spring io spring boo
  • javascript 中的对象变量是否按照添加顺序枚举? [复制]

    这个问题在这里已经有答案了 可能的重复 元素顺序 javascript 中的 for in 循环 https stackoverflow com questions 280713 elements order for in loop in
  • 如何替换 MPMoviePlayer 通知?

    在 iOS 9 中 MPMoviePlayer 及其所有组件均已弃用 我们使用 MPMoviePlayerController 通知 例如MPMoviePlayerLoadStateDidChangeNotification MPMovie
  • 如何限制用户只能使用 CakePHP 3 进行一次会话?

    我的授权工作正常 用户可以登录和退出 没有问题 问题是 如果用户共享登录信息 那么他们都可以与一个用户同时登录 不好 我需要让 CakePHP 知道用户何时登录 我认为这是一个使用以下命令启动的进程 Session gt defaults
  • 转义正则表达式中的变量[重复]

    这个问题在这里已经有答案了 我正在尝试获取输入文本字段的值并在正则表达式中使用它 这是我必须匹配行开头的内容 regex new RegExp inputValue i 它适用于以字母数字字符开头的常规字符串 但我也将其用于美元金额 当输入
  • `DList` 和 `[]` 与 Co密度的关系

    我一直在尝试Codensity最近这应该与DList with 除其他事项外 不管怎样 我从来没有找到说明这种关系的代码 经过一些实验我最终得到了这个 LANGUAGE RankNTypes module Codensity where n
  • GWT JPA - 响应无法反序列化

    我使用 GWT 和 JPA 来实现持久性 我创建了一个域 JPA 魔法类 DAO 和 RPC 用于它们之间的通信 一切正常 客户端通过 RPC 将对象发送到服务器 但无法得到响应 服务器无法以与客户端兼容的方式反序列化 所以我无法使用服务器
  • 使用java本机接口获取Windows当前用户

    我试图做一个概念证明 在 cpp 程序中我获取 Windows 用户名 然后使用 Java 本机接口 JNI 从 java 代码调用该程序 现在我到目前为止拥有的是一个示例 JNI hello world 程序 它能够编译和打印 Hello