我需要一个简单但奇怪的问题的帮助。问题是从我的应用程序关闭并重新启动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 );
}
答案 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。