c#Windows关闭进程异常

时间:2018-09-19 10:02:03

标签: c# wpf windows wcf

我需要一个简单但奇怪的问题的帮助。问题是从我的应用程序关闭并重新启动Windows。我知道它很简单,并且在线上有很多示例,但这是交易。这些方法(如process.start()或win api或managmentobject)执行的关闭/重新启动与单击Windows关闭或重新启动按钮所执行的关闭/重新启动不同。怎么样?

好吧,我为学校实验室制作了一个客户端应用程序,可通过屏幕截图和其他诸如关机,重新启动,锁定等操作帮助教师监控台式机上的学生活动。如果我从我的应用程序关闭/重新启动PC,则该学生PC在学生登录之前,Windows启动屏幕不会显示在教师计算机上。但是,如果我执行关机或从学生计算机上的Windows菜单重新启动,则学生计算机启动屏幕将显示在教师计算机上。

我知道我的应用程序启动的关闭/重新启动会完全清除学生PC的关闭/重新启动,而Windows关闭/重新启动则会执行某种混合类型的操作,从而以某种方式保存了用户会话。并传递到下一次启动。

我想知道如何编写代码来复制此行为以关闭或重新启动。(“某种混合类型的东西,以某种方式保存了用户会话。然后传递给下一次启动”)。 / hybrid也不起作用。

客户端应用程序是一个wpf应用程序,可从任务计划程序以提升的特权运行,并具有启动和登录任务。 wpf应用程序最小化到系统托盘,并通过tcp服务器托管wcf服务。

关机代码:

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

其他关闭代码: //来自: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);
}

}

另一个:来自: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 );
}

1 个答案:

答案 0 :(得分:2)

好吧。。。终于解决了。如果有人在这里需要它。

如果您有一个由任务计划程序在启动时启动的应用程序,则只有在您单击Windows按钮以重新启动或关闭时,它才会在启动时启动。这对我来说是个问题,因为我的应用需要在用户登录之前启动并开始将捕获的屏幕发送到Teacher PC。

我使用了stackoverflow和其他站点提到的各种关闭方法,这些方法可以工作,但不像Windows关机和重新启动按钮的工作方式。

这是复制此行为的方法

如果您在命令提示符下查看“ shutdown”命令所包含的参数,则会提及:

/ g:完全关闭并重新启动计算机。重新启动系统后,重新启动所有已注册的应用程序。

/ sg:关闭计算机。下次启动时,重新启动所有已注册的应用程序。

“重新启动任何已注册的应用程序” <-这就是使它单击...大声笑的原因。

所以我用了这段代码:

关机:

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

重新启动:

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

任何应用程序都是任务调度程序,它在启动时以高特权运行,将在用户登录之前运行。....

PS:仅在Windows的最新版本中支持关机命令/ sg和/ g。我可以确认Windows 7及更低版本中缺少它。在Windows 10上运行。不了解Windows 8和8.1。