The Windows service created to shut down the computer does not work when the computer is locked

I created a Windows service in C # to turn off the computer.

The service works fine when the computer is not locked (Ctrl + Alt + Del).

But some of them do not close when my computer is locked.

// call
DoExitWin(EWX_SHUTDOWN);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
    public int Count;
    public long Luid;
    public int Attr;
}

[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
    ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool ExitWindowsEx(int flg, int rea);

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
internal const int EWX_LOGOFF = 0x00000000;
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
internal const int EWX_FORCEIFHUNG = 0x00000010;

private static void DoExitWin(int flg)
{
    bool ok;
    TokPriv1Luid tp;
    IntPtr hproc = GetCurrentProcess();
    IntPtr htok = IntPtr.Zero;
    ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
    ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero,IntPtr.Zero);
    ok = ExitWindowsEx(flg, 0);
}

UPDATE:

Based on the help of Chris Haas, I am trying to find which call returns an error based on the value ok:

ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
int error = Marshal.GetLastWin32Error(); //error 87 ok return true 
ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid); 
error = Marshal.GetLastWin32Error(); //error 997 ok return true rest of ok true with zero error code

ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero,IntPtr.Zero);
ok = ExitWindowsEx(flg, 0); //This mean error in ok 

But okreturns true all the time.

+5
source share
3 answers

, , . , . ok, . , , ,

, , EWX_SHUTDOWN | EWX_POWEROFF

2

, Marshal.GetLastWin32Error()

3

GetLastError, ok false:

int error;
ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
if(!ok){
    error = Marshal.GetLastWin32Error();
    throw new ApplicationException('Error : ' + error);
}
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
if(!ok){
    error = Marshal.GetLastWin32Error();
    throw new ApplicationException('Error : ' + error);
}
ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero,IntPtr.Zero);
if(!ok){
    error = Marshal.GetLastWin32Error();
    throw new ApplicationException('Error : ' + error);
}
ok = ExitWindowsEx(flg, 0);
if(!ok){
    error = Marshal.GetLastWin32Error();
    throw new ApplicationException('Error : ' + error);
}
+2

InitiateSystemShutdownEx. . , , .

EDIT: , . MSDN :

* Windows Server 2003 Windows XP: bForceAppsClosed FALSE, : ERROR_MACHINE_LOCKED. , : ERROR_NOT_READY. . , ERROR_NOT_READY, . . *

+2

Windows , .

, " " ​​

AdministartiveTools- > service- > yourService. "LOCAL SERVICE",

try to enter the credentials of the account in which your service is running.

Please cross check whether you have done the following steps during windows service creation:

1.After creating the windows service project go to the service class design view(just double click the service1.cs class).

2.In the design view right click and select Add Installer. This will create an Installer class named ProjectInstaller.cs. With out ProjectInstaller.cs or any error in configuring ProjectInstaller.cs may result in non-showing of the service in service console.

3.Go to the design view of ProjectInstaller.cs you will find two installers there->

 a.**ServiceInstaller1**

    b.**ServiceProcessInstaller1**  
4.Right click ServiceInstaller1 and go to the properties tab

    a.Edit the ServiceName with the name you want to 
      see your service in the service console.

    b.Change the **StartType** to **Automatic**.
5.Right click ServiceProcessInstaller1 and go to the properties tab

    a.Change the account to **LocalService**

    6. Save and try it.

Hope this helps you ........

0
source

All Articles