繁体   English   中英

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

[英]Running cscript.exe from C# .ashx does not execute code in vbscript file

编辑

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

此外,当尝试通过via向进程提供我的凭据时

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 Script Host版本5.7版权所有(C)Microsoft Corporation。 版权所有

从命令行

Microsoft(R)Windows Script Host版本5.7版权所有(C)Microsoft Corporation。 版权所有

你好

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

有任何想法吗? 谢谢!

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

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

事实证明我需要跳过使用System.Diagnostics.Process并使用kernel32.dll和advapi32.dll方法。

“这是因为在ASP.NET中,模拟是在线程级别而不是在进程级别执行的。” 资源

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

这是来自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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM