鱼C论坛

 找回密码
 立即注册
查看: 3640|回复: 4

[技术交流] 编程笔记——之VC 实现重启、关机、注销

[复制链接]
发表于 2012-12-11 23:55:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 username_badboy 于 2012-12-12 08:42 编辑

      近段时间开始学习VC编程,从今天开始会坚持将自己的学习笔记记录下来和大家一起分享,希望和大家一起共同进步!我相信分享即是快乐,能帮到别人是你价值的体现(最近才悟到的)。
     下面进入正题,我今天学习了使用C++调用api实现计算机的重启、关机等功能,我会附上源码并大致的讲解一下程序的主要代码,首先要介绍一个非常非常用的api函数WinMain函数:
  1. 应用程序入口
  2. int WINAPI WinMain(
  3. HINSTANCE hInstance, // handle to current instance 当前程序实例句柄
  4. HINSTANCE hPrevInstance, // handle to previous instance 上一个程序实例句柄(在NT以后就没有用了,只是为了兼容以前的程序)
  5. LPSTR lpCmdLine, // pointer to command line 运行时传入的参数
  6. int nCmdShow // show state of window 以哪种方式显示窗口
  7. );
复制代码
     第二个函数是真正实现功能的函数ExitWindowsEx:

  1. //退出程序,包括关机、注销、重启
  2. BOOL ExitWindowsEx(
  3. UINT uFlags, // shutdown operation
  4. DWORD dwReserved // reserved
  5. );

  6. uFlags参数的一些取值:
  7. EWX_LOGOFF:注销
  8. EWX_REBOOT:重启
  9. EWX_SHUTDOWN:关机

  10. 还可以加上下面的一个参数(取或运算):
  11. EWX_FORCE:强制结束
  12. EWX_FORCEIFHUNG:通知其他程序准备退出

  13. dwReserved参数是关机的原因(这个参数是可以忽略的):
  14. SHTDN_RESON_MAJOR_APPLICATION 应用程序原因等等..
复制代码
        还会使用到一个获取当前系统版本的函数GetVersionEx:
  1. BOOL GetVersionEx(
  2. LPOSVERSIONINFO lpVersionInformation // pointer to version
  3. // information structure
  4. );

  5. //旧版本(新版本OSVERSIONINFOEX与这个类似)
  6. typedef struct _OSVERSIONINFO{
  7. DWORD dwOSVersionInfoSize;
  8. DWORD dwMajorVersion;
  9. DWORD dwMinorVersion;
  10. DWORD dwBuildNumber;
  11. DWORD dwPlatformId; //我们这儿用到的只是这个值,平台ID
  12. TCHAR szCSDVersion[ 128 ];
  13. } OSVERSIONINFO;

  14. dwPlatformId的值有:
  15. VER_PLATFORM_WIN32_WINDOWS //windows 95 or windows 98
  16. VER_PLATFORM_WIN32_NT // windows NT xp 2000 ...
复制代码

      如果是NT以后的系统就需要提升权限了(不会让你乱来的!),提升权限也就是程序实现代码中的nableShutDownPriv()函数,这个函数是比较固定的,一般只需要修改一个地方,我在代码中有注明,这儿就不多说了,如果想对这个函数里的api函数深入了解的话,可以查查MSDN,也可以看看这篇文章http://zhidao.baidu.com/question/44997791.html。

        由于时间关系,代码讲解就到这里了,如果有不明白的地方可以查查MSDN或找我交流。到这里就可以测试程序了,最好是编译的时候选择release(发布)版本,不然可能会放到另外的电脑上就不能执行,还有就是最好在虚拟机上测试,因为它真的会不问问你就执行的哦。执行的时候可以使用两种方式,第一种是cmd的方式,因为要给它传参数, 还有一种就是创建快捷方式然后在快捷方式上-->右键-->属性-->目标-->在目标字符串中加参数,然后双击能执行了。累死我了,希望对大家有帮助,后边是源代码。
  1. #include <tchar.h>
  2. #include <WINDOWS.H>

  3. //为当前程序提升权限,这个函数比较固定,一般只用修改LookupPrivilegeValue中的第二个参数
  4. BOOL EnableShutDownPriv()
  5. {
  6. //存放访问令牌句柄
  7. HANDLE hToken = NULL;
  8. TOKEN_PRIVILEGES tkp;

  9. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
  10. {
  11. return false;
  12. }
  13. //一般只需改SE_SHUTDOWN_NAME的值
  14. if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid))
  15. {
  16. CloseHandle(hToken);
  17. return false;
  18. }
  19. tkp.PrivilegeCount = 1;
  20. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  21. if (!AdjustTokenPrivileges(hToken,false,&tkp,sizeof(TOKEN_ADJUST_PRIVILEGES),NULL,NULL))
  22. {
  23. CloseHandle(hToken);
  24. return false;
  25. }
  26. return true;
  27. }

  28. /*
  29. *dwFlags:执行操作类型
  30. *bForce:是否强制执行
  31. */
  32. BOOL ReSetWindows(DWORD dwFlags,BOOL bForce)
  33. {
  34. //检验参数是否合法
  35. if(dwFlags != EWX_LOGOFF && dwFlags != EWX_REBOOT && EWX_SHUTDOWN)
  36. {
  37. return false;
  38. }

  39. //存放返回值的结构
  40. OSVERSIONINFO ovsi;
  41. //这一步必不可少
  42. ovsi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  43. //获取系统版本号
  44. if (!GetVersionEx(&ovsi))
  45. {
  46. return false;
  47. }

  48. //判断是不是NT系统
  49. if (ovsi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  50. {
  51. //提升权限
  52. EnableShutDownPriv();
  53. }

  54. dwFlags |=bForce?EWX_FORCE:EWX_SHUTDOWN;//三元表达式
  55. //执行相应操作
  56. return ExitWindowsEx(dwFlags,0);
  57. }


  58. int WINAPI WinMain(
  59. HINSTANCE hInstance, // 当前程序实例句柄
  60. HINSTANCE hPrevInstance, //上一个程序实例句柄(在NT以后就没有用了,只是为了兼容以前的程序)
  61. LPSTR lpCmdLine, // 运行时传入的参数
  62. int nCmdShow // 以哪种方式显示窗口
  63. )
  64. {
  65. //_tcscmp函数作用是判断两个字串是否相等
  66. if (_tcscmp(lpCmdLine,_T("/r")) == 0)
  67. {
  68. ReSetWindows(EWX_REBOOT,false);
  69. }else if (_tcscmp(lpCmdLine,_T("/s")) == 0)
  70. {
  71. ReSetWindows(EWX_SHUTDOWN,false);
  72. }else if (_tcscmp(lpCmdLine,_T("/l")) == 0)
  73. {
  74. ReSetWindows(EWX_LOGOFF,false);
  75. }else
  76. {
  77. MessageBox(NULL,"请传入正确的参数! /r:重启 /s:关机 /l:注销","提示",NULL);
  78. }
  79. return 0;
  80. }



复制代码


===================================END=====================================   














小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-4-11 11:53:31 From FishC Mobile | 显示全部楼层
先看看!!
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-4-11 19:40:58 | 显示全部楼层
看不懂啊  我还是再学学吧
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-4-18 17:19:31 | 显示全部楼层
是不是也可以用system( )函数加cmd命令
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-10-5 18:59:14 | 显示全部楼层
太高深了,实在不明白!!!继续学习!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-8 04:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表