由于asp.net没有权限执行一些操作,而这些操作在服务器本地是可以的,所以我想在服务器上放一个winform程序用于执行这些操作,然后通过asp.net来启动,请各位大侠赐教,感激不尽!

解决方案 »

  1.   

    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();
      

  2.   

    这样做不行,原因是新的进程会使用(继承)调用线程的用户权限的(ASPNET干不了的它也干不了)。可以用WindowsIdentity.Impersonate来暂时改变身份,比如换成Administrator,运行需要权限的操作后,再WindowsImpersonationContext.Undo回去。这样也不用"放一个winform程序"了。
      

  3.   

    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操作(写文件等),有可能无法切换回原来的用户。这个问题我一直解决不了。
      

  4.   

    多谢楼上三位高手的解答,一位比一位的解答细致,不过用asp.net来处理WindowsIdentity.Impersonate我没有做过,有没有这方面的例子给一个谢谢!为了感谢各位,我再追加100分哈
      

  5.   

    告诉你个方法,你在服务器上开一个队列,里面启动调用你控制权限的WINFORM,然后定时开启队列
      

  6.   

    通过ASP.NET调用socket通讯,给winform发送消息,winform程序解析消息后,执行对应命令。
      

  7.   

    由于最近找到了解决我上面说的问题的方法,所以刷新一下。
    完整的类的代码,红色语句是新加的,用于解决上面说的那个无法切换回原来的用户的问题:
    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用户
      

  8.   

    如果你有权限在服务器上放一个什么WinForm并且与之通信,你还不能设置asp.net的进程角色(权限)吗?!
      

  9.   

    一、本地调试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 服务器的项目进行调试。  
      

  10.   

    http://www.pc592.com/vb/ShowArticle.asp?ArticleID=177
    这里有个例子,不过有点乱
      

  11.   

    楼上给的例子有我上面说的那个问题(不过我的解决方法倒是受了它的启发),原来的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);
      

  12.   

    先结帖哈,这个问题,一直没有机会再尝试,等以后试的时候有问题了再发出来请教。
    如果有朋友愿意帮忙一试并提供demo下载,请发给我邮箱一份baicaiATcnyu.net,感激不尽!