终止打开的应用程序并关闭计算机电源-Delphi Win10问题

问题描述 投票:-1回答:1

当前,我正在Delphi中创建一个应用程序,它将在关闭打开的应用程序后完全关闭计算机的电源。目前,我遇到的问题是代码在Win10企业版中无法正常运行,并且正在注销用户,但没有完全关闭PC。代码的头脑在下面,我不清楚为什么这只会让我登出,而没有完全关闭计算机。

用户将定义要通过CMD运行的参数,以关闭引用该应用程序的计算机。该应用程序将关闭打开的进程,并通过CMD传递关闭进程。

procedure TfrmCleanShutdown.ProcessCommandLine;
const
  CMD_CAPTION   = 'w';  // window capShuttion
  CMD_CLASSNAME = 'c';  // window class name
  CMD_ACTION    = 'a';
  CMD_TIMEOUT   = 't';

  S_SHUTDOWN    = 'shutdown';
  S_LOGOFF      = 'logoff';
  S_RESTART     = 'restart';

var
  cmdl: TCommandLineParameterList;
  cmd: TCommandLineParameter;


begin
  cmdl := TCommandLineParameterList.Create;
  cmdl.Initialize;

  cmd := cmdl.FindByParam(CMD_CAPTION);
  if Assigned(cmd) then
    FWaitForWindowCaption := cmd.Param
  else
    FWaitForWindowCaption := '';

  cmd := cmdl.FindByParam(CMD_CLASSNAME);
  if Assigned(cmd) then
    FWaitForWindowClassName := cmd.Param
  else
    FWaitForWindowClassName := '';

  cmd := cmdl.FindByParam(CMD_TIMEOUT);
  if Assigned(cmd) then
    FTimeout := StrToIntDef(cmd.Param, DEF_TIMEOUT)
  else
    FTimeout := DEF_TIMEOUT;
  FAction := EWX_LOGOFF or EWX_FORCEIFHUNG; // default action
  cmd := cmdl.FindByParam(CMD_ACTION);
  if Assigned(cmd) then begin
    if cmd.Param = S_SHUTDOWN then
      FAction := EWX_POWEROFF or EWX_FORCEIFHUNG
    else if cmd.Param = S_RESTART then
      FAction := EWX_REBOOT or EWX_FORCEIFHUNG
  end;
end;

procedure TfrmCleanShutDown.ThreadTerminate(Sender: TObject);
begin
  if (Sender as TWaitForWindowCloseThread).Success then
    ExitWindowsEx(FAction, 0)
  else
    Label1.Caption := 'Timeout';
end;

任何帮助将不胜感激。我不清楚为什么win10会以一种方式注销用户而不是关闭用户,因为该应用程序是通过CMD运行的,并且用户具有关闭用户的权限。这非常令人困惑。

从下面的注释中添加命令行代码。

unit uCommandLine;

interface

uses
  SysUtils, Classes, Contnrs;

const
  S_SWITCHES = '+-*';

type
  //======================================
  // TCommandLineParameter
  //======================================
  TCommandLineParameter = class
  private
    FParam: String;
    FSwitch: String;
    FOptions: String;
  public
    property Param: String read FParam write FParam;
    property Switch: String read FSwitch write FSwitch;
    property Options: String read FOptions write FOptions;
  end;  // TCommandLineParameter

  //======================================
  // TCommandLineParameterList
  //======================================
  TCommandLineParameterList = class(TObjectList)
  private
    function GetParameter(idx: Integer): TCommandLineParameter;
  public
    function Initialize: Boolean;
    function FindByParam(const ParamString: String): TCommandLineParameter;
    property Parameters[idx: Integer]: TCommandLineParameter read GetParameter;
  end;

implementation

const
  C_CMD_DELIM: Char = '-';

//======================================
// TCommandLineParameter
//======================================

//======================================
// TCommandLineParameterList
//======================================
//------------------------------------------------------------------------------
function TCommandLineParameterList.GetParameter(idx: Integer): TCommandLineParameter;
begin
  Result := TCommandLineParameter(Items[idx]);
end;

//------------------------------------------------------------------------------
function TCommandLineParameterList.Initialize: Boolean;
var
  n, idx: Integer;
  p: TCommandLineParameter;
  s: String;
begin
  Result := True;
  p := nil;
  n := ParamCount;
  for idx := 1 to n do begin
    s := Trim(ParamStr(idx));
    if s[1] = C_CMD_DELIM then begin
      System.Delete(s, 1, 1);
      p := FindByParam(s);
      if p = nil then begin
        p := TCommandLineParameter.Create;
        p.Param := s;
        Add(p);
      end
      else begin
        Result := False;
        break;
      end;
    end
    else begin
      if p <> nil then begin
        p.Options := s;  
        p := nil;
      end
      else begin
        Result := False;
        break;
      end;
    end;
  end;
end;

//------------------------------------------------------------------------------
function TCommandLineParameterList.FindByParam(const ParamString: String): TCommandLineParameter;
var
  idx: Integer;
begin
  Result := nil;
  for idx := 0 to Count-1 do
    if CompareStr(Parameters[idx].Param, ParamString) = 0 then begin
      Result := Parameters[idx];
      break;
    end;
end;
end.
delphi cmd windows-10 shutdown delphi-10.1-berlin
1个回答
0
投票

您没有正确处理命令行参数。

使用命令行时:

-w -a shutdown -t 45

FindByParam(CMD_ACTION)返回其TCommandLineParameterParam'a'Options'shutdown'。但是您正在'shutdown'中寻找Param,而不是Options

同样,您最终使用ExitWindowsEx()标志而不是EWX_LOGOFF标志。

如果调试了代码,您会看到这种情况。

您在所有命令中都犯了相同的错误。

改用它:

EWX_POWEROFF

话虽如此,您的procedure TfrmCleanShutdown.ProcessCommandLine; const CMD_CAPTION = 'w'; // window capShuttion CMD_CLASSNAME = 'c'; // window class name CMD_ACTION = 'a'; CMD_TIMEOUT = 't'; S_SHUTDOWN = 'shutdown'; S_LOGOFF = 'logoff'; S_RESTART = 'restart'; var cmdl: TCommandLineParameterList; cmd: TCommandLineParameter; begin cmdl := TCommandLineParameterList.Create; try cmdl.Initialize; cmd := cmdl.FindByParam(CMD_CAPTION); if Assigned(cmd) then FWaitForWindowCaption := cmd.Options else FWaitForWindowCaption := ''; cmd := cmdl.FindByParam(CMD_CLASSNAME); if Assigned(cmd) then FWaitForWindowClassName := cmd.Options else FWaitForWindowClassName := ''; cmd := cmdl.FindByParam(CMD_TIMEOUT); if Assigned(cmd) then FTimeout := StrToIntDef(cmd.Options, DEF_TIMEOUT) else FTimeout := DEF_TIMEOUT; FAction := EWX_LOGOFF or EWX_FORCEIFHUNG; // default action cmd := cmdl.FindByParam(CMD_ACTION); if Assigned(cmd) then begin if cmd.Options = S_SHUTDOWN then FAction := EWX_POWEROFF or EWX_FORCEIFHUNG else if cmd.Options = S_RESTART then FAction := EWX_REBOOT or EWX_FORCEIFHUNG end; finally cmdl.Free; end; end; 是完全多余的,可以删除,因为RTL的TCommandLineParameterList函数可以为您完成所有相同的工作,例如:

SysUtils.FindCmdLineSwitch()
© www.soinside.com 2019 - 2024. All rights reserved.