Currently, I am creating an application in Delphi that will allow for the computer to fully power off after closing down open applications. Currently I am running into issues where the code isn't functioning properly in Win10 enterprise and it's logging the user out, but not shutting down the PC fully. the brains of the code is below, and I'm unclear why this would just log me out and not fully shut the computer down.
The user will define the params to run via a CMD to shut down the computer referencing the application. The application will shut down processes that are open and pass the shutdown process via the 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;
Any help would be appreciated. I am unclear why win10 would behave in a way to just log off a user instead of shutdown, since the application is being run via a CMD and the user has shutdown rights. It's very confusing.
adding the command line code from a comment below.
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.
FAction
gets assigned appropriately? I'm not familiar withTCommandLineParameterList
but it could be that you're expected to put-
or/
in front of each param. According to your code, if no parameters are found, default behavior is to log off. - Jerry Dodgeshutdown.exe
and its parameters. No need to reinvent the wheel... - Delphi Coder