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

发布于 2024-09-25 14:38:27 字数 1834 浏览 2 评论 0原文

编辑

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

此外,当尝试通过 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 脚本宿主 版本 5.7 版权所有 (C) Microsoft 公司。保留所有权利

从命令行

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

你好

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

有什么想法吗?谢谢!

EDIT

I added in some error handling to my .vbs file and it is indeed a permissions issue (I now get a "Permission Denied error"). However, supplying my credentials in the web.config <impersonate> tag does not seem to have any effect.

Also when trying to supply my credentials to the process via via

p.StartInfo.Password = Misc.CreateSecurityString("password");
p.StartInfo.UserName = "admin";

I get an new error:

cscript.exe - Application error

The application failed to initialize
properly (0xc0000142). Click on OK to
terminate the application.

Shout it out if you know what's causing this. (Or just type it...)

Thanks for your help so far!


Background

I'm trying to execute a .vbs file from an custom handler (.ashx). The VBScript is setting up a web application in iis 5.1.

So far the following code executes without errors

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

Problem

My problem is that the vbscript appears to not have run at all. When I check IIS, my application is not created.

When I run the script file directly from the command prompt everything works correctly and my application shows up in IIS.

Trouble Shooting

I decided to add some echo statements into the .vbs file so I could make sure it was running. On the command line, all the statements are outputted correctly. When checking the string sOutput I get the header message, but none of my subsequent messages.

From C# - contents of sOutput

Microsoft (R) Windows Script Host
Version 5.7 Copyright (C) Microsoft
Corporation. All rights reserved

From the Command Line

Microsoft (R) Windows Script Host
Version 5.7 Copyright (C) Microsoft
Corporation. All rights reserved

Hello

So I can prove (I think) that the .vbs file is not being evaluated, and cscript is being called. And if I call cscript without referencing a .vbs file, then I get the help documentation. So something is going wrong.

Any ideas? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

莳間冲淡了誓言ζ 2024-10-02 14:38:27

我认为一个问题(也许不是全部问题)是运行 IIS 的用户没有在目标计算机上运行脚本的权限。

I imagine that a problem (maybe not the entire problem) is that the user that IIS is running under doesn't have the privileges to run scripts on the target machine.

亚希 2024-10-02 14:38:27

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

You need to be an admin to create the website. You will need to change your web app to run as an admin user, or alternatively, you can launch the cscript process as an admin user.

脱离于你 2024-10-02 14:38:27

结果我需要跳过使用 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);

Turns out I needed to skip using System.Diagnostics.Process and use kernel32.dll and advapi32.dll methods.

"This is because in ASP.NET,
impersonation is performed at the
thread level and not at the process
level." source

Also needed make my Anonymous Access account a member of "Replace a process level token" Control Panel -> Administrative Tools -> Local Security Settings. (You'll need to restart for this to take effect.

Here's the adapted code from 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());
            }

        }

    }
}

Using it is simple:

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

Win32Process.CreateProcess(sToRun);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文