c# Windows Shutdown process weirdness

2

I need help on an issue which is kind of simple but weird. The problem is with the shutdown and restart windows from my app. I know its simple and there are many examples online, but here's the deal. The shutdown/restart performed by these methods like process.start() or win api or managmentobject is not similar to the one done with clicking the windows shutdown or restart button. How?

Ok, I have made an client side app for school lab that helps teachers monitor student activity on desktop with screen capture and other things like shutdown, restart, lockdown etc. If i shutdown/restart the PC from my app the student pc windows startup screen wont show on the teacher machine until the student logs - in. But if i perform a shutdown or restart from the windows menu on student machine, then the student machine startup screen will showup on the teacher machine.

I know that the shutdown/restart initiated by my app does a clean shutdown/restart of the student pc whereas the windows shutdown/restart does some kind of hybrid type thing where the user session is somehow saved. and passed on to the next startup.

I want to know how to write a code which can replicate this behavior to shutdown or restart.("some kind of hybrid type thing where the user session is somehow saved. and passed on to the next startup"). Also /hybrid doesnt work.

The client app is a wpf app which run in elevated privilege from task scheduler with startup and logon task. The wpf app minimizes to system tray and hosts a wcf service with tcp server.

the code for shutdown:

var psi = new ProcessStartInfo("shutdown", "/s /t 5");
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            Process.Start(psi);

other code for shutdown: //from : How to shut down the computer from C#

void Shutdown()
{
ManagementBaseObject mboShutdown = null;
ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
mcWin32.Get();

// You can't shutdown without security privileges
mcWin32.Scope.Options.EnablePrivileges = true;
ManagementBaseObject mboShutdownParams =
         mcWin32.GetMethodParameters("Win32Shutdown");

 // Flag 1 means we want to shut down the system. Use "2" to reboot.
mboShutdownParams["Flags"] = "1";
mboShutdownParams["Reserved"] = "0";
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
    mboShutdown = manObj.InvokeMethod("Win32Shutdown", 
                                   mboShutdownParams, null);
}

}

another one : from :How to shut down the computer from C#

using System.Runtime.InteropServices;

[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 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 );
}
c#
wpf
windows
wcf
asked on Stack Overflow Sep 19, 2018 by Quest • edited Sep 19, 2018 by Quest

1 Answer

2

Ok people....finally got it solved. If anyone ever needs this here it is.

If you have an app that is started by task scheduler on startup, it will only start at startup if you click windows button to restart or shutdown. This was a problem for me because my app needed to start before user logged in and start sending screen captured to Teacher PC.

I used various shutdown methods mentioned at stackoverflow and other sites, they worked but not like the way windows power down and reboot button work.

Here is the method that replicates this behaviour

If you look at the parameters that "shutdown" command takes in command prompt it mentions :

/g : Full shutdown and restart the computer. After the system is rebooted, restart any registered applications.

/sg : Shutdown the computer. On the next boot, restart any registered applications.

"Restart Any Registered Application" <- this is what makes it click...lol.

So I used this code :

For Shutdown :

var psi = new ProcessStartInfo("shutdown", "/sg /t 0");
        psi.CreateNoWindow = true;
        psi.UseShellExecute = false;
        Process.Start(psi);

For Restart :

var psi = new ProcessStartInfo("shutdown", "/g /t 0");
        psi.CreateNoWindow = true;
        psi.UseShellExecute = false;
        Process.Start(psi);

Any Application is task scheduler which runs at high privilege during startup will run before user logs in. Phew...

PS : Shutdown commands /sg and /g are only supported in recent versions of windows. I can confirm that its missing in windows 7 and lower. Works on windows 10. Dont know about windows 8 and 8.1.

answered on Stack Overflow Sep 20, 2018 by Quest • edited Oct 16, 2018 by Quest

User contributions licensed under CC BY-SA 3.0