asp.net如何启动服务上的应用程序 由于asp.net没有权限执行一些操作,而这些操作在服务器本地是可以的,所以我想在服务器上放一个winform程序用于执行这些操作,然后通过asp.net来启动,请各位大侠赐教,感激不尽! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Process调用exe文件Process p = new Process();p.StartInfo.UseShellExecute = false;p.StartInfo.RedirectStandardInput = true;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardError = true;p.StartInfo.CreateNoWindow = true;p.StartInfo.FileName = HttpContext.Current.Server.MapPath("~/A/a.exe");p.Start();p.Close(); 这样做不行,原因是新的进程会使用(继承)调用线程的用户权限的(ASPNET干不了的它也干不了)。可以用WindowsIdentity.Impersonate来暂时改变身份,比如换成Administrator,运行需要权限的操作后,再WindowsImpersonationContext.Undo回去。这样也不用"放一个winform程序"了。 WindowsIdentity.Impersonate是暂时转成当前登陆的windows用户的身份,如果当前用户也没有权限,就需要用以下的代码转到有权限的用户: private const int LOGON32_LOGON_INTERACTIVE = 2; private const int LOGON32_PROVIDER_DEFAULT = 0; private WindowsImpersonationContext impersonationContext;[DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool CloseHandle( IntPtr handle); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int DuplicateToken( IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);private void ImpersonateValidUser( string userName, string domain, string password) { WindowsIdentity tempWindowsIdentity = null; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; try { if (RevertToSelf()) { if (LogonUser( userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (token != IntPtr.Zero) { CloseHandle(token); } if (tokenDuplicate != IntPtr.Zero) { CloseHandle(tokenDuplicate); } } } [DllImport("advapi32.dll", SetLastError = true)] private static extern int LogonUser( string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool RevertToSelf();用完以后转回原来用户,用一句: impersonationContext.Undo();LogonUser是win32的api函数,就是以指定的用户在服务器上登陆。注意,如果登陆后有i/o操作(写文件等),有可能无法切换回原来的用户。这个问题我一直解决不了。 多谢楼上三位高手的解答,一位比一位的解答细致,不过用asp.net来处理WindowsIdentity.Impersonate我没有做过,有没有这方面的例子给一个谢谢!为了感谢各位,我再追加100分哈 告诉你个方法,你在服务器上开一个队列,里面启动调用你控制权限的WINFORM,然后定时开启队列 通过ASP.NET调用socket通讯,给winform发送消息,winform程序解析消息后,执行对应命令。 由于最近找到了解决我上面说的问题的方法,所以刷新一下。完整的类的代码,红色语句是新加的,用于解决上面说的那个无法切换回原来的用户的问题:public class Impersonator : IDisposable { private const int LOGON32_LOGON_INTERACTIVE = 2; private const int LOGON32_PROVIDER_DEFAULT = 0; private WindowsImpersonationContext impersonationContext; private IntPtr _oldTokenHandle = IntPtr.Zero; [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool CloseHandle(IntPtr handle); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int DuplicateToken(IntPtr hToken,int impersonationLevel,ref IntPtr hNewToken); [DllImport("advapi32.dll", SetLastError = true)] private static extern int LogonUser(string lpszUserName,string lpszDomain,string lpszPassword,int dwLogonType,int dwLogonProvider,ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool RevertToSelf(); public Impersonator(IntPtr oldTokenHandle, string userNameWithDomain,string password) { if (userNameWithDomain.Contains("\\")) { int start = userNameWithDomain.IndexOf("\\"); string domainName = userNameWithDomain.Substring(0, start); string userName = userNameWithDomain.Substring(start + 1); ImpersonateValidUser(oldTokenHandle, userName, domainName, password); } } public void ImpersonateValidUser(IntPtr oldTokenHandle, string userName,string domain,string password) { WindowsIdentity tempWindowsIdentity = null; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; _oldTokenHandle = oldTokenHandle; try { if (RevertToSelf()) { if (LogonUser(userName,domain,password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (token != IntPtr.Zero) { CloseHandle(token); } if (tokenDuplicate != IntPtr.Zero) { CloseHandle(tokenDuplicate); } } } private void UndoImpersonation() { if (impersonationContext != null) { impersonationContext.Undo(); WindowsIdentity tempWindowsIdentity = new WindowsIdentity(_oldTokenHandle); tempWindowsIdentity.Impersonate(); CloseHandle(_oldTokenHandle); } } public void Dispose() { UndoImpersonation(); } } 调用方法: IntPtr oldTokenHandle = WindowsIdentity.GetCurrent().Token; using (new Impersonator(oldTokenHandle, userName, password)) { //做需要impersonate后的用户权限做的事情 } //执行完后将自动恢复原先的windows用户 如果你有权限在服务器上放一个什么WinForm并且与之通信,你还不能设置asp.net的进程角色(权限)吗?! 一、本地调试A. Windows 2000 操作系统1、打开VS.Net工具选项 → 项目Web设置 → Web服务器连接 → Forntpage扩展2、用户的群组 → 删除“ (192.168.0.1) Admins”用户组”(可能不是 IP,是计算机名称,没有就不用删了)3、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) →右击“默认Web站点”所有任务→删除服务器扩展4、在 MS-DOS 命令下运行“C:\WINNT\Microsoft.NET\Framework\v1.0.3705\aspnet_regiis.exe -i”(此处也可能是“C:\WINNT\Microsoft.NET\Framework\ v1.1.4322\aspnet_regiis.exe -i”),接着在 “C:\WINNT\Microsoft.NET\Framework\v1.0.3705\Config\machine.config”文件找到“ <processModel …… />”把“ username="machine" ”改成“username="system" ”。5、按第 3 步,在“所有任务” → “配置服务器扩展”完成向导的过程中会提示你创建本地用户组“(192.168.0.1) Admins” → 刷新“用户组”即可看到,然后添加该组成员6、右击“Internet信息报务” → 属性 → 服务器扩展 → “充许作者上载可执行程序”;7、检查“c:\inetpub\wwwroot”文件夹(注意此处为站点所在根目录,必须是 NTFS 格式)安全属性,里面应该有“(192.168.0.1) Admins”用户组,没有就自己加上,并附上相应的权力8、运行VS.NET,新建项目会有用户名和密码提示框,输入(192.168.0.1) Admins 群组成员相应的账号及密码(用户密码不能为空,若该账号无密码请添加) B. Windows 2003操作系统1、同上2、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 站点 → 右击“默认Web站点” → 所有任务 → 删除 Server Extensions 2002 → 将打开一网页,输入 “Administrator ”及密码,按步骤做完3、在 MS-DOS 命令下运行“C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_regiis.exe –i”4、右击“默认Web站点” → 所有任务 → 设置 Server Extensions 2002 → 然后点击左上角的“管理” → 改变匿名访问 → 选择“开启”、“参与者”5、完成上述 4 个步骤,只有Administrators 用户组的成员才有权限进行调试,其他用户的调试请参照“远程调试” 二、远程调试首先,先介绍远程调试的先决条件:1、Web 服务器需要能够进行本地调试的条件2、Web 服务器需要安装 Visual Studio .NET 远程组件, 客户端只需要“Full Remote Debugging”一项 A. Windows 2000 操作系统 1、你需要有一个 Web 服务器的账号 ,该账号至少应该是”Debugger Users” ”WebAdmins”两个用户组的成员(此处我建立一个 ”cityhunter” 的账号,”Web Admins” 是设置本地调试时创建的)2、在服务器上的“C:\WINNT\Microsoft.NET\Framework\v1.0.3705\Config\machine.config”文件中找到“ <processModel …… />”把“username” 设成"cityhunter", “password” 设为 "123456"。然后重启服务器(不知重启 IIS 可不可以)3、用户必须以 用户名: ”cityhunter” 密码:”123456” 的帐号登录客户端电脑.。这一点对于 服务器与客户端 在同一工作组的用户来说是关键!!原因也许是 Web 服务器检测账号时,只对当前客户端电脑使用者的账户及密码,而不是检验 打开项目时用户输入的账户及密码。 B. Windows 2003 操作系统1、建立一个 ”cityhunter” 的账号,密码为 ”123456”,将其加入”Debugger Users “用户组2、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 站点 → 右击“默认Web站点” → 新增 → Server Extensions 2002 管理员 → 将打开一网页,输入 “Administrator ”及密码,按步骤做完,最后此账户也至少应该在二个工作组内3、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 应用程序池 → 右击“DefaultAppPool” → 属性 → 身份验证 → 指定为 “cityhunter”。完成后重启。 4、用户必须以 用户名: ”cityhunter” 密码:”123456” 的帐号登录客户端电脑.才能对 Web 服务器的项目进行调试。 http://www.pc592.com/vb/ShowArticle.asp?ArticleID=177这里有个例子,不过有点乱 楼上给的例子有我上面说的那个问题(不过我的解决方法倒是受了它的启发),原来的identity是WindowsIdentity.GetCurrent(),但是,执行impersonationContext.Undo();后返回的是IIS的应用池(application pool)的用户,如果设的是Network Service就等于是匿名用户,而不是原来的windows identity。如果在本地windows xp上调试,没有application pool,那样返回的才是原来的windows identity。解决方法是先保存原来的windows identity:IntPtr _oldTokenHandle = WindowsIdentity.GetCurrent().Token;impersonate完,要返回时,用这个已保存的token再impersonate一次,等于是恢复了原来的用户:WindowsIdentity oldWindowsIdentity = new WindowsIdentity(_oldTokenHandle); 先结帖哈,这个问题,一直没有机会再尝试,等以后试的时候有问题了再发出来请教。如果有朋友愿意帮忙一试并提供demo下载,请发给我邮箱一份baicaiATcnyu.net,感激不尽! IIS6.0下,CS中操作pfx的方法报错:系统找不到指定的文件 WCF当中1.客户端使用代理上网怎么访问服务器端2.客户端不使用配置文件就手写终节点怎么访问服务器端 哭求高手指点---gridview控件的显示问题 动态DataGridView的动态的添加列 请问怎么把string[] 转成 int[]? 未将对象引用实例化 未将对象引用设置到对象的实例。 c#的网络编程问题 汉字在String.length返回中是一个字节,可我想得到的是strlen()那种返回字节数,怎么办? 学.NET的来解释一下 怎样判断出输入的文字是int,string 爱提问!
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = HttpContext.Current.Server.MapPath("~/A/a.exe");
p.Start();
p.Close();
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private WindowsImpersonationContext impersonationContext;[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);private void ImpersonateValidUser(
string userName,
string domain,
string password)
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero; try
{
if (RevertToSelf())
{
if (LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
if (token != IntPtr.Zero)
{
CloseHandle(token);
}
if (tokenDuplicate != IntPtr.Zero)
{
CloseHandle(tokenDuplicate);
}
}
} [DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();用完以后转回原来用户,用一句:
impersonationContext.Undo();LogonUser是win32的api函数,就是以指定的用户在服务器上登陆。注意,如果登陆后有i/o操作(写文件等),有可能无法切换回原来的用户。这个问题我一直解决不了。
完整的类的代码,红色语句是新加的,用于解决上面说的那个无法切换回原来的用户的问题:
public class Impersonator : IDisposable
{
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private WindowsImpersonationContext impersonationContext;
private IntPtr _oldTokenHandle = IntPtr.Zero;
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(IntPtr hToken,int impersonationLevel,ref IntPtr hNewToken); [DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(string lpszUserName,string lpszDomain,string lpszPassword,int dwLogonType,int dwLogonProvider,ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf(); public Impersonator(IntPtr oldTokenHandle, string userNameWithDomain,string password)
{
if (userNameWithDomain.Contains("\\"))
{
int start = userNameWithDomain.IndexOf("\\");
string domainName = userNameWithDomain.Substring(0, start);
string userName = userNameWithDomain.Substring(start + 1);
ImpersonateValidUser(oldTokenHandle, userName, domainName, password);
}
}
public void ImpersonateValidUser(IntPtr oldTokenHandle, string userName,string domain,string password)
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
_oldTokenHandle = oldTokenHandle; try
{
if (RevertToSelf())
{
if (LogonUser(userName,domain,password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
if (token != IntPtr.Zero)
{
CloseHandle(token);
}
if (tokenDuplicate != IntPtr.Zero)
{
CloseHandle(tokenDuplicate);
}
}
}
private void UndoImpersonation()
{
if (impersonationContext != null)
{
impersonationContext.Undo();
WindowsIdentity tempWindowsIdentity = new WindowsIdentity(_oldTokenHandle);
tempWindowsIdentity.Impersonate();
CloseHandle(_oldTokenHandle);
}
}
public void Dispose()
{
UndoImpersonation();
}
}
调用方法: IntPtr oldTokenHandle = WindowsIdentity.GetCurrent().Token;
using (new Impersonator(oldTokenHandle, userName, password))
{
//做需要impersonate后的用户权限做的事情
}
//执行完后将自动恢复原先的windows用户
2、用户的群组 → 删除“ (192.168.0.1) Admins”用户组”(可能不是 IP,是计算机名称,没有就不用删了)
3、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) →右击“默认Web站点”所有任务→删除服务器扩展
4、在 MS-DOS 命令下运行“C:\WINNT\Microsoft.NET\Framework\v1.0.3705\aspnet_regiis.exe -i”(此处也可能是“C:\WINNT\Microsoft.NET\Framework\ v1.1.4322\aspnet_regiis.exe -i”),接着在 “C:\WINNT\Microsoft.NET\Framework\v1.0.3705\Config\machine.config”文件找到“ <processModel …… />”把“ username="machine" ”改成“username="system" ”。
5、按第 3 步,在“所有任务” → “配置服务器扩展”完成向导的过程中会提示你创建本地用户组“(192.168.0.1) Admins” → 刷新“用户组”即可看到,然后添加该组成员
6、右击“Internet信息报务” → 属性 → 服务器扩展 → “充许作者上载可执行程序”;
7、检查“c:\inetpub\wwwroot”文件夹(注意此处为站点所在根目录,必须是 NTFS 格式)安全属性,里面应该有“(192.168.0.1) Admins”用户组,没有就自己加上,并附上相应的权力8、运行VS.NET,新建项目会有用户名和密码提示框,输入(192.168.0.1) Admins 群组成员相应的账号及密码(用户密码不能为空,若该账号无密码请添加)
B. Windows 2003操作系统1、同上2、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 站点 → 右击“默认Web站点” → 所有任务 → 删除 Server Extensions 2002 → 将打开一网页,输入 “Administrator ”及密码,按步骤做完
3、在 MS-DOS 命令下运行“C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_regiis.exe –i”
4、右击“默认Web站点” → 所有任务 → 设置 Server Extensions 2002 → 然后点击左上角的“管理” → 改变匿名访问 → 选择“开启”、“参与者”
5、完成上述 4 个步骤,只有Administrators 用户组的成员才有权限进行调试,其他用户的调试请参照“远程调试” 二、远程调试首先,先介绍远程调试的先决条件:1、Web 服务器需要能够进行本地调试的条件2、Web 服务器需要安装 Visual Studio .NET 远程组件, 客户端只需要“Full Remote Debugging”一项
A. Windows 2000 操作系统 1、你需要有一个 Web 服务器的账号 ,该账号至少应该是”Debugger Users” ”WebAdmins”两个用户组的成员(此处我建立一个 ”cityhunter” 的账号,”Web Admins” 是设置本地调试时创建的)2、在服务器上的“C:\WINNT\Microsoft.NET\Framework\v1.0.3705\Config\machine.config”文件中找到“ <processModel …… />”把“username” 设成"cityhunter", “password” 设为 "123456"。然后重启服务器(不知重启 IIS 可不可以)
3、用户必须以 用户名: ”cityhunter” 密码:”123456” 的帐号登录客户端电脑.。这一点对于 服务器与客户端 在同一工作组的用户来说是关键!!原因也许是 Web 服务器检测账号时,只对当前客户端电脑使用者的账户及密码,而不是检验 打开项目时用户输入的账户及密码。 B. Windows 2003 操作系统1、建立一个 ”cityhunter” 的账号,密码为 ”123456”,将其加入”Debugger Users “用户组2、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 站点 → 右击“默认Web站点” → 新增 → Server Extensions 2002 管理员 → 将打开一网页,输入 “Administrator ”及密码,按步骤做完,最后此账户也至少应该在二个工作组内3、右击“我的电脑” → 管理 → 服务和应用程序 → Internet 信息管理服务器(IIS) → 应用程序池 → 右击“DefaultAppPool” → 属性 → 身份验证 → 指定为 “cityhunter”。完成后重启。 4、用户必须以 用户名: ”cityhunter” 密码:”123456” 的帐号登录客户端电脑.才能对 Web 服务器的项目进行调试。
这里有个例子,不过有点乱
如果在本地windows xp上调试,没有application pool,那样返回的才是原来的windows identity。解决方法是先保存原来的windows identity:IntPtr _oldTokenHandle = WindowsIdentity.GetCurrent().Token;impersonate完,要返回时,用这个已保存的token再impersonate一次,等于是恢复了原来的用户:WindowsIdentity oldWindowsIdentity = new WindowsIdentity(_oldTokenHandle);
如果有朋友愿意帮忙一试并提供demo下载,请发给我邮箱一份baicaiATcnyu.net,感激不尽!