怎样在ASP.NET页面下重启服务器

到Google搜索了一下,找到了一段似乎很普遍的代码

事实证明,这段代码在写桌面应用例如Console或者Windows Form程序的时候可以正常运行,但是通过ASP.NET调用则无法通过

但是我还是把这段代码贴出来,因为其中除了个别两行外,其他的还是重启服务器的必须代码

新建一个类,在里面填入如下代码:

首先是命名空间,调用Win API的时候,InteropServices不可少:

以下为引用的内容:

using System;
using System.Runtime.InteropServices;
然后是一系列的常量声明: protected const int SE_PRIVILEGE_ENABLED = 0x2;
protected const int TOKEN_QUERY = 0x8;
protected const int TOKEN_ADJUST_PRIVILEGES = 0x20;
protected const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
protected const int EWX_LOGOFF = 0x0;
protected const int EWX_SHUTDOWN = 0x1;
protected const int EWX_REBOOT = 0x2;
protected const int EWX_FORCE = 0x4;
protected const int EWX_POWEROFF = 0x8;
protected const int EWX_FORCEIFHUNG = 0x10;
定义Luid结构,注意属性: [StructLayout(LayoutKind.Sequential, Pack=1)]
protected struct LuidStruct {
    public int Count;
    public long Luid;
    public int Attr;
}
外部非托管DLL的声明: [DllImport("kernel32.dll", ExactSpelling=true)]
protected static extern IntPtr GetCurrentProcess();

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

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

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

[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
protected static extern bool ExitWindowsEx(int flg, int rea);
在NT级的操作系统上,需要先通知Windows系统即将关机,并且要获得关机的权限

以下就是关机、重启以及注销的实现: protected static void DoExitWindows(int flg) {
    LuidStruct tp;
    IntPtr hproc = GetCurrentProcess();
    IntPtr htok = IntPtr.Zero;

    OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
    tp.Count = 1;
    tp.Luid = 0;
    tp.Attr = SE_PRIVILEGE_ENABLED;
    LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
    AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
    ExitWindowsEx(flg, 0);
}

public static void Shutdown() {
    DoExitWindows(EWX_SHUTDOWN);
}

public static void Reboot() {
    DoExitWindows(EWX_REBOOT | EWX_FORCE);
}

public static void Logoff() {
    DoExitWindows(EWX_LOGOFF);
}

至此,重启代码结束,这段代码可以很好地工作在交互环境下,也就是在用户已经登录进Windows的情况下

但是ASP.NET是运行在非交互环境下的,查阅MSDN,在ExitWindowsEx函数定义下面发现这样一段话:

The ExitWindowsEx function returns as soon as it has initiated the shutdown process. The shutdown or logoff then proceeds asynchronously. The function is designed to stop all processes in the caller's logon session. Therefore, if you are not the interactive user, the function can succeed without actually shutting down the computer. If you are not the interactive user, use the InitiateSystemShutdown or InitiateSystemShutdownEx function.

于是得到启发,发现非交互下重启服务器不可以用ExitWindowsEx,需要将其替换成InitiateSystemShutdown:

[DllImport("advapi32.dll", SetLastError=true, ExactSpelling=false)]
protected static extern bool InitiateSystemShutdown(string name, string msg, int timeout, bool force, bool reboot);
参数解释:
name:机器名,用于重启局域网内的其它机器,如果为 null 则是本机
msg:重启消息,会显示在重启消息框上,在Windows 2003和XP中也会作为消息日志被保存
timeout:如果不是0,那么会显示一个重新消息框,倒计时timeout秒后重启
force:强制重启,不等待应用程序提示是否保存工作,对于服务器来说,应该是true
reboot:是否是重启,如果是false,那么做关机处理,对于服务器,应该是true

先按照文章一开始的方法调用 AdjustTokenPrivileges 得到Privilege,然后在ASP.NET页面里面执行: InitiateSystemShutdown(null,null,0,true,true);
系统就重启了

这里有一点说下,如果重启本机,那么多半会返回Service Unavailable错误,这是因为在ASP.NET执行结束之前系统已经开始结束各个进程了,当然包括ASP.NET进程,算是正常表现,虽然看起来有些不太舒服

另外由于目前我只在自己机器上测试通过,所以没有详细研究权限问题,所以无法确定在一般服务器上是否可以正常运行

初步只想到可以用权限模拟解决,即在web.config文件system.web节写上<identity impersonate="true" userName="Administrator" password="pass">,不过没有经过确认,有时间会尝试一下。web.config不是很安全,所以这里可能要借助于DPAPI,有点扯远了,就先到这里吧。

时间: 2024-11-03 22:06:59

怎样在ASP.NET页面下重启服务器的相关文章

利用.Net制作ASP脚本组件实现重启服务器

大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作! 大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作! 下面先说COM的制作,在VB中新建一工程,当然是AceiveX dll的! 1)先修改工程属性,在工程属性窗口将工程名称改为system,在类模块窗口将模块名称改为contral,保存工程;

制作ASP脚本组件实现重启服务器

大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作! 下面先说COM的制作,在VB中新建一工程,当然是AceiveX dll的! 1)先修改工程属性,在工程属性窗口将工程名称改为system,在类模块窗口将模块名称改为contral,保存工程; 2)然后添加一个模块,用来声明需要使用的API和常数!下面是模块中的内容! Declare Function ExitWindowsEx Lib "use

如何用SQLDMO在ASP.NET页面下实现数据库的备份与恢复

asp.net|备份|恢复|数据|数据库|页面 我们知道,用SQLDMO可以实现对数据库的备份与恢复,下面给出简单的实现方法.首先需要添加对SQLDMO引用 1.实现数据库的备份: 1/**//// <summary> 2        /// 数据库备份 3        /// </summary> 4        /// <returns>备份是否成功</returns> 5        public bool DbBackup() 6      

通过ASP.NET页面重启服务器

asp.net|服务器|页面 最近在设计网站后台管理系统的时候,想到了是否可以通过页面重启Windows服务器 到Google搜索了一下,找到了一段似乎很普遍的代码 事实证明,这段代码在写桌面应用例如Console或者Windows Form程序的时候可以正常运行,但是通过ASP.NET调用则无法通过 但是我还是把这段代码贴出来,因为其中除了个别两行外,其他的还是重启服务器的必须代码 新建一个类,在里面填入如下代码: 首先是命名空间,调用Win API的时候,InteropServices不可少

巧用ASP脚本命令重启服务器

大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作! 下面先说COM的制作,在VB中新建一工程,当然是AceiveX dll的! 1)先修改工程属性,在工程属性窗口将工程名称改为system,在类模块窗口将模块名称改为contral,保存工程; 2)然后添加一个模块,用来声明需要使用的API和常数!下面是模块中的内容! Declare Function ExitWindowsEx Lib "use

使用ASP重启服务器

服务器 大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作!          下面先说COM的制作,在VB中新建一工程,当然是AceiveX dll的!     1)先修改工程属性,在工程属性窗口将工程名称改为system,在类模块窗口将模块名称改为contral,保存工程:     2)然后添加一个模块,用来声明需要使用的API和常数!下面是模块中的内容!     Declare Functi

dropdownlist-asp.net 页面下拉框数据绑定

问题描述 asp.net 页面下拉框数据绑定 <asp:DropDownList ID="ddl_select" runat="server" DataTextField="Name" DataValueField="ID" Width="100%"/> 报错 Object of type 'System.String' cannot be converted to type 'System.I

Linux下远程备份、上传工程,重启服务器

    Linux服务器实现远程,原项目的备份.删除,新项目上传,以及远程重启服务器! 分成一个主shell调用三个shell文件步骤完成. mainsh.sh一次按顺序执行多个脚本,将三步sh顺序完成: #!/bin/sh #此Shell一次按顺序执行多个脚本 #参数:: #远程jboss服务器所在的ip IP=127.0.0.1 #服务器登录账户 userx='tskk' #服务器登录密码 passx='sasa' #部署jboss远程服务器上项目war文件的全路径名称(用于备份) jbos

工具-为什么ssh框架运行期间直接从数据库更改数据必须重启服务器才能把数据更新到页面

问题描述 为什么ssh框架运行期间直接从数据库更改数据必须重启服务器才能把数据更新到页面 而从页面更改数据则不用重启服务器 一直弄不明白,我的是spring管理session跟事务,工具方法用的getHibernateTemplate() 解决方案 刚开始,你是创建了session,你虽然更改了数据库的数据,但是你的运行项目里面还是以前的session,必须重启服务,从新加载,获取最新的信息 解决方案二: 开始,你是创建了session,你虽然更改了数据库的数据,但是你的运行项目里面还是以前的s