从C#.ashx运行cscript.exe不会在vbscript文件中执行代码

时间:2010-10-01 18:24:12

标签: c# asp.net vbscript ashx wsh

修改

我在我的.vbs文件中添加了一些错误处理,这确实是一个权限问题(我现在得到一个“Permission Denied error”)。但是,在web.config <impersonate>标记中提供我的凭据似乎没有任何效果。

同时尝试通过

向流程提供凭据时
p.StartInfo.Password = Misc.CreateSecurityString("password");
p.StartInfo.UserName = "admin";

我收到一个新错误:

  

cscript.exe - 应用程序错误

     

应用程序无法初始化   正确(0xc0000142)。单击“确定”   终止申请。

如果你知道造成这种情况的原因,请大声说出来。 (或者只需输入...

到目前为止,感谢您的帮助!


背景

我正在尝试从自定义处理程序(.ashx)执行.vbs文件。 VBScript正在iis 5.1中设置Web应用程序。

到目前为止,以下代码执行时没有错误

string sToRun = "C:\CreateIISApplication.vbs" 
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cscript";
p.StartInfo.Arguments = sToRun;
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string sOutput = p.StandardOutput.ReadToEnd();
p.WaitForExit();

问题

我的问题是vbscript似乎根本没有运行。当我检查IIS时,我的应用程序没有创建。

当我直接从命令提示符运行脚本文件时,一切正常,我的应用程序显示在IIS中。

故障排除

我决定在.vbs文件中添加一些echo语句,这样我就可以确保它正在运行。在命令行上,所有语句都正确输出。检查字符串sOutput时,我得到标题消息,但没有后续消息。

来自C# - sOutput的内容

  

Microsoft(R)Windows脚本宿主   版本5.7版权所有(C)Microsoft   公司。保留所有权利

从命令行

  

Microsoft(R)Windows脚本宿主   版本5.7版权所有(C)Microsoft   公司。保留所有权利

     

您好

所以我可以证明(我认为).vbs文件没有被评估,并且正在调用cscript。如果我在没有引用.vbs文件的情况下调用cscript,那么我会获得帮助文档。所以出了点问题。

有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:1)

我认为问题(可能不是整个问题)是运行IIS的用户没有在目标计算机上运行脚本的权限。

答案 1 :(得分:1)

您需要成为管理员才能创建网站。您需要更改您的Web应用程序以管理员用户身份运行,或者您可以以管理员用户身份启动cscript进程。

答案 2 :(得分:1)

原来我需要跳过使用System.Diagnostics.Process并使用kernel32.dll和advapi32.dll方法。

  

“这是因为在ASP.NET中,   模仿是在   线程级别而不是在进程中   等级。“source

还需要使我的匿名访问帐户成为“替换进程级令牌”控制面板 - &gt;管理工具 - &gt;本地安全设置。 (您需要重新启动才能生效。

以下是来自MSDN(http://support.microsoft.com/kb/889251)的改编代码。

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;
using System.Security.Principal;

namespace UtilityLib
{
    public class Win32Process
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public int cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public extern static bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
            String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
        public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
            ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
            int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);


        public static void CreateProcess(string cmdline)
        {
            IntPtr Token = new IntPtr(0);
            IntPtr DupedToken = new IntPtr(0);
            bool      ret;
            //Label2.Text+=WindowsIdentity.GetCurrent().Name.ToString();


            SECURITY_ATTRIBUTES sa  = new SECURITY_ATTRIBUTES();
            sa.bInheritHandle       = false;
            sa.Length               = Marshal.SizeOf(sa);
            sa.lpSecurityDescriptor = (IntPtr)0;

            Token = WindowsIdentity.GetCurrent().Token;

            const uint GENERIC_ALL = 0x10000000;

            const int SecurityImpersonation = 2;
            const int TokenType = 1;

            ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);

            if (ret == false)
            {
                throw new Exception("DuplicateTokenEx failed with " + Marshal.GetLastWin32Error());
            }


            STARTUPINFO si          = new STARTUPINFO();
            si.cb                   = Marshal.SizeOf(si);
            si.lpDesktop            = "";

            string commandLinePath = cmdline;

            PROCESS_INFORMATION pi  = new PROCESS_INFORMATION();
            ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, "c:\\", ref si, out pi);

            if (ret == false)
            {
                throw new Exception("CreateProcessAsUser failed with " + Marshal.GetLastWin32Error() + ": if 1314, make sure user is a member 'Replace a process level token' Control Panel -> Administrative Tools -> Local Security Settings.");
            }
            else
            {
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
            }

            ret = CloseHandle(DupedToken);
            if (ret == false)
            {
                throw new Exception(Marshal.GetLastWin32Error().ToString());
            }

        }

    }
}

使用它很简单:

string sToRun = @"cscript C:\CreateIISApplication.vbs"; //OR C:\myfile.bat arguments, or whatever else you want to run. 

Win32Process.CreateProcess(sToRun);