我的应用程序使用Windows的未公开的函数SHChangeNotifyRegister及SHChangeNotifyDeRegister来监视WIndows文件操作,正常关闭程序,一切正常。
但如果不结束应用程序,Windows 9X/2000均无法关闭/注销计算机。
   请高手指点:如何解决不结束应用程序而不影响Windows关闭.

解决方案 »

  1.   

    解决方案能发Email到[email protected]最好。谢谢。我试过用截获WM_QUIT的方法:先SHChangeNotifyDeRegister,然后再关闭程序,但不行?为什么?
      

  2.   

    可以调用Win API函数ExitWindowsNT()来实现关机(或注销,重启等):
    procedure ExitWindowsNT(uFlags : integer);
    var
      hToken : THANDLE;
      tkp, tkDumb : TTokenPrivileges;
      DumbInt : integer;
    begin
      FillChar(tkp, sizeof(tkp), 0);
      // Get a token for this process
      if not (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES 
              or TOKEN_QUERY, hToken)) then
         raise Exception.create('OpenProcessToken failed with code '
                   + inttostr(GetLastError));  // Get the LUID for the Shutdown privilege
      LookupPrivilegeValue(nil, pchar('SeShutdownPrivilege'),
                           tkp.Privileges[0].Luid);  tkp.PrivilegeCount := 1; // one privilege to set
      tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;  // Get the shutdown provolege for this process
      AdjustTokenPrivileges(hToken, false, tkp, sizeof(tkDumb), tkDumb, DumbInt);  // Cannot test the return value of AdjustTokenPrivileges
      if GetLastError <> ERROR_SUCCESS then
         Raise Exception.create('AdjustTokenPrivileges failed with code ' 
                   + inttostr(GetLastError));  // shut down the system and for all applications to close
      if not ExitWindowsEx(uFlags, 0) then
         Raise Exception.create('ExitWindowsEx failed with code '
                   + inttostr(GetLastError));
    end;
    本函数详细的说明请查看有关文档,我以前做过类似的东西,测试成功,没有任何问题!
    至于要实现的操作(如关机或重启),在于函数的返回值,可以自己定夺。
      

  3.   

    要关闭Windows可以用API函数ExitWindowsEx(),它能实现“注销当前用户”,
      “关闭Windows(应该是关机)”,“使Windows重启”等功能,返回值布尔类型。  ExitWindowsEx(关闭类型参数,系统保留参数)  系统保留参数一般为0。  关闭类型参数:  EWX_FORCE :强制关闭,不会发送任何消息给正在运行的程序,强行关闭Windows。  EWX_LOGOFF :注销当前用户,并重新登陆。  EWX_POWEROFF :关闭Windows,并关机(主板需支持软关机,就是电源管理啦)  EWX_REBOOT :不用说了Reboot重启系统  EWX_SHUTDOWN :安全关闭Windows,书上说缓冲区内数据将被写入磁盘。  EWX_FORCEIFHUNG :在Windows2000以上版本中才有,用EWX_FORCE就很好。  example:  ExitWindowsEx(ewx_logooff,0);//注销用户  ExitWindowsEx(ewx_reboot,0);//重启系统  ExitWindowsEx(ewx_shutdown,0);//安全关机(软关机)  另外在WindowsNT版本中(NT4,Win2000,WinXP)调用这些函数必须具有系统管理员身份  或使SE_SHUTDOWN_NAME特权有效才能关机。  另外ExitWindows()函数只能注销当前用户,调用为ExitWindows(0,0)返回值为布尔类  型。 
      

  4.   

    //--重启动
          if Win32Platform <> VER_PLATFORM_WIN32_NT then //不是NT
            ExitWindowsEx(EWX_REBOOT, 0)
          else
          begin
               SetPrivilege('SeShutdownPrivilege', True);
                 if not ExitWindowsEx(EWX_REBOOT + EWX_FORCE, 0) then
                   SetPrivilege('SeShutdownPrivilege', False);
          end;      //--关机
          if Win32Platform <> VER_PLATFORM_WIN32_NT then //不是NT
            ShellExecute(handle, 'open', 'RUNDLL32.EXE', 'user.exe,ExitWindows', nil, SW_ShowNormal)
          else
          begin
               SetPrivilege('SeShutdownPrivilege', True);
                 if not ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE+EWX_POWEROFF, 0) then
                   SetPrivilege('SeShutdownPrivilege', False);
          end;
      

  5.   

    var
      Form1: TForm1;implementation{$R *.dfm}procedure AdjustToken();
    var
      hdlProcessHandle : Cardinal;
      hdlTokenHandle   : Cardinal;
      tmpLuid          : Int64;
      tkp              : TOKEN_PRIVILEGES;
      tkpNewButIgnored : TOKEN_PRIVILEGES;
      lBufferNeeded    : Cardinal;
      Privilege        : array[0..0] of _LUID_AND_ATTRIBUTES;
    begin
      hdlProcessHandle := GetCurrentProcess;
      OpenProcessToken(hdlProcessHandle,
                       (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY),
                       hdlTokenHandle);
      // Get the LUID for shutdown privilege.
      LookupPrivilegeValue('', 'SeShutdownPrivilege', tmpLuid);
      Privilege[0].Luid := tmpLuid;
      Privilege[0].Attributes := SE_PRIVILEGE_ENABLED;
      tkp.PrivilegeCount := 1;   // One privilege to set
      tkp.Privileges[0] := Privilege[0];
      // Enable the shutdown privilege in the access token of this process.
      AdjustTokenPrivileges(hdlTokenHandle,False,tkp,Sizeof(tkpNewButIgnored),
                            tkpNewButIgnored,lBufferNeeded);
    end;
    procedure ShutDown(uFlags: Cardinal);
    begin
      AdjustToken;
      //ExitWindowsEx(EWX_LOGOFF , 0);
      //ExitWindowsEx(EWX_SHUTDOWN, 0);
      //ExitWindowsEx(EWX_REBOOT , 0);
      //ExitWindowsEx(EWX_FORCE , 0);
      ExitWindowsEx(uFlags, 0);
      //ExitWindowsEx(EWX_FORCEIFHUNG , 0);
      {EWX_FORCE or EWX_SHUTDOWN,0}
    end;
    procedure TForm1.BitBtn2Click(Sender: TObject);//注销
    begin
      ShutDown(EWX_FORCE or EWX_LOGOFF);
    end;procedure TForm1.BitBtn3Click(Sender: TObject);//关机
    begin
      ShutDown(EWX_FORCE or EWX_POWEROFF);
    end;procedure TForm1.BitBtn4Click(Sender: TObject);//重启
    begin
      ShutDown(EWX_FORCE or EWX_REBOOT);
    end;