• QT使用WindowsAPI NetUserAdd创建系统用户


    首先,放上NetUserAdd这个API的官方文档地址:NetUserAdd function (lmaccess.h) - Win32 apps | Microsoft Docs

    下面是微软官方给的C++示例代码(注意,示例代码里有错误!):

    1. #ifndef UNICODE
    2. #define UNICODE
    3. #endif
    4. #pragma comment(lib, "netapi32.lib")
    5. #include
    6. #include
    7. #include
    8. int wmain(int argc, wchar_t *argv[])
    9. {
    10. USER_INFO_1 ui;
    11. DWORD dwLevel = 1;
    12. DWORD dwError = 0;
    13. NET_API_STATUS nStatus;
    14. if (argc != 3)
    15. {
    16. fwprintf(stderr, L"Usage: %s \\\\ServerName UserName\n", argv[0]);
    17. exit(1);
    18. }
    19. //
    20. // Set up the USER_INFO_1 structure.
    21. // USER_PRIV_USER: name identifies a user,
    22. // rather than an administrator or a guest.
    23. // UF_SCRIPT: required
    24. //
    25. ui.usri1_name = argv[2];
    26. ui.usri1_password = argv[2];
    27. ui.usri1_priv = USER_PRIV_USER;
    28. ui.usri1_home_dir = NULL;
    29. ui.usri1_comment = NULL;
    30. ui.usri1_flags = UF_SCRIPT;
    31. ui.usri1_script_path = NULL;
    32. //
    33. // Call the NetUserAdd function, specifying level 1.
    34. //
    35. nStatus = NetUserAdd(argv[1],
    36. dwLevel,
    37. (LPBYTE)&ui,
    38. &dwError);
    39. //
    40. // If the call succeeds, inform the user.
    41. //
    42. if (nStatus == NERR_Success)
    43. fwprintf(stderr, L"User %s has been successfully added on %s\n",
    44. argv[2], argv[1]);
    45. //
    46. // Otherwise, print the system error.
    47. //
    48. else
    49. fprintf(stderr, "A system error has occurred: %d\n", nStatus);
    50. return 0;
    51. }

    再次提醒,上面的示例代码虽然是微软官方给的,但有错误且不完善,不要直接使用!

    QT虽然底层就是C++,而且也支持C++代码,但有些地方仍需要处理!比如QT默认的文本类型QString,C++是没有的,像示例代码中的wchar_t类型和QString就需要进行转换。。

    新建项目,选择构建套件(Kits)

    新建一个项目,这里项目取名叫:adduser

    开发Windows程序,QT常用的有MSVC和MinGW,推荐使用MinGW,如图:

     本文内容也是基于MinGW!

    .pro文件

    双击打开adduser.pro文件:

    在右侧窗口中,添加一行:

    LIBS += -lnetapi32

    如图: 

    注意,官方的示例代码:

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

    这是MSVC才支持的写法,MinGW不支持!

    .h头文件

    导入头文件:

    1. #include
    2. #include
    3. #include
    4. #include "QMessageBox"

    定义函数:

    1. wchar_t* QStringToWchar(QString qStr); //QString转换为wchar_t类型
    2. int adduser(wchar_t* Server, wchar_t * User,wchar_t * Password); //添加用户

    如图:

      .cpp文件

    cpp文件中的函数代码:

    1. wchar_t* MainWindow::QStringToWchar(QString qStr) //QString转换为wchar_t类型
    2. {
    3. return (wchar_t*)reinterpret_cast<const wchar_t *>(qStr.utf16());
    4. }
    5. int MainWindow::adduser(wchar_t * Server,wchar_t * User,wchar_t * Password)
    6. {
    7. USER_INFO_1 ui;
    8. DWORD dwLevel = 1;
    9. DWORD dwError = 0;
    10. NET_API_STATUS nStatus;
    11. ui.usri1_name = User;
    12. ui.usri1_password = Password;
    13. ui.usri1_priv = USER_PRIV_USER; //这里设置成其它无效,比如USER_PRIV_ADMIN
    14. ui.usri1_home_dir = NULL;
    15. ui.usri1_comment = NULL;
    16. ui.usri1_flags = UF_NORMAL_ACCOUNT | UF_SCRIPT | UF_DONT_EXPIRE_PASSWD; //密码永不过期
    17. ui.usri1_script_path = NULL;
    18. nStatus = NetUserAdd(Server, dwLevel, (LPBYTE)&ui, &dwError); //调用WindowsAPI添加用户
    19. switch (nStatus) { //判断返回值,给出相应的提示
    20. case NERR_Success: //0
    21. QMessageBox::information(NULL,"成功","用户:" + QString::fromStdWString(User) + " 添加成功!");
    22. break;
    23. case NERR_UserExists: //2224
    24. QMessageBox::warning(NULL,"失败","用户:" + QString::fromStdWString(User) + " 已存在!");
    25. return 1;
    26. case ERROR_ACCESS_DENIED: //5
    27. QMessageBox::warning(NULL,"失败","没有访问权限!");
    28. return 1;
    29. case NERR_InvalidComputer: //2351
    30. QMessageBox::warning(NULL,"失败","计算机名或IP无效!");
    31. return 1;
    32. case NERR_NotPrimary: //2226
    33. QMessageBox::warning(NULL,"失败","该操作只允许在域的主域控制器上进行!");
    34. return 1;
    35. case NERR_GroupExists: //2223
    36. QMessageBox::warning(NULL,"失败","用户组已存在!");
    37. return 1;
    38. case NERR_PasswordTooShort: //2245
    39. QMessageBox::warning(NULL,"失败","密码不符合规范!");
    40. return 1;
    41. default:
    42. QMessageBox::warning(NULL,"失败","未知错误!");
    43. return 1;
    44. }
    45. //给刚才添加用户,设置权限组
    46. _LOCALGROUP_MEMBERS_INFO_3 gi;
    47. gi.lgrmi3_domainandname = ui.usri1_name;
    48. nStatus = NetLocalGroupAddMembers(NULL, L"Users", 3, (LPBYTE)&gi, 1); //调用WindowsAPI将刚才添加的用户,设置成“Users”权限
    49. switch (nStatus) {
    50. case NERR_Success:
    51. fwprintf(stderr, L"设置用户组成功!\n",User); //权限组设置成功就不弹出对话框提示了,太烦
    52. break;
    53. case NERR_GroupNotFound: //2220
    54. QMessageBox::warning(NULL,"失败","指定的用户组不存在!");
    55. return 1;
    56. case ERROR_ACCESS_DENIED: //5
    57. fwprintf(stderr, L"设置用户组失败,无权访问!\n");
    58. QMessageBox::warning(NULL,"失败","设置用户组失败,无权访问!");
    59. return 1;
    60. case ERROR_NO_SUCH_MEMBER:
    61. fwprintf(stderr, L"指定的一个或多个成员不存在!\n");
    62. QMessageBox::warning(NULL,"失败","指定的一个或多个成员不存在!");
    63. return 1;
    64. case ERROR_MEMBER_IN_ALIAS:
    65. fwprintf(stderr, L"指定的一个或多个成员已经是本地组成员!\n");
    66. QMessageBox::warning(NULL,"失败","指定的一个或多个成员已经是本地组成员!");
    67. return 1;
    68. case ERROR_INVALID_MEMBER:
    69. fwprintf(stderr, L"帐户类型无效!\n");
    70. QMessageBox::warning(NULL,"失败","帐户类型无效!");
    71. return 1;
    72. default:
    73. fwprintf(stderr, L"未知错误!\n");
    74. QMessageBox::warning(NULL,"失败","未知错误!");
    75. return 1;
    76. }
    77. return 0;
    78. }

    上面的代码有不少可以优化的地方,这里主要做用法展示,就不去纠结它们了。

    UI界面

    现在关键的代码已经完成,创建一个UI界面来测试一下:

    拖入几个控件:Label、Line Edit、Push Button,并修改它们的文本,如图:

    右键点击“添加用户” 按钮,选择“转到槽”,选择 clicked() 确定:

    添加如下代码:

    1. wchar_t *Server = QStringToWchar(ui->lineEdit->text());
    2. wchar_t *User = QStringToWchar(ui->lineEdit_2->text());
    3. wchar_t *Password = QStringToWchar(ui->lineEdit_3->text());
    4. adduser( Server, User, Password );

    如图: 

    好了,代码全部完成!现在编译测试一下:

     

    用户添加成功!

    需要注意的是:

    一、密码是否能像我图中那样设置简单密码,还取决于系统中的密码策略设置:

    如果密码不符合这里的设置,那么用户就会添加失败!

    二、服务器地址可以是计算机名,也可以是IP。如果不填,那默认就是本机!

  • 相关阅读:
    2022搜狐校园NLP算法大赛情感分析第一名方案理解和复现
    vscode拉取git代码到本地提示 在签出前,请清理存储库工作树
    [ vulhub漏洞复现篇 ] Apache Solr RemoteStreaming 文件读取与SSRF漏洞 (CVE-2021-27905)
    CentOS即将停服,国产化系统替代参考
    leetcode2389--感染二叉树需要的总时间
    时尚夏季拖鞋出口英国要办理UKCA认证
    NodeMCU ESP8266硬件开发板的熟悉
    软件安全性测试要点有哪些?常用软件安全测试工具分享
    [Games 101] Lecture 13-16 Ray Tracing
    【生日快乐】SpringBoot SpringBoot 提高篇(第二篇) 第5章 SpringBoot 日志 5.1 日志介绍 & 5.2 日志框架
  • 原文地址:https://blog.csdn.net/s806903/article/details/126472648