3

编辑

我在我的 .vbs 文件中添加了一些错误处理,这确实是一个权限问题(我现在收到“权限被拒绝错误”)。但是,在 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,那么我会得到帮助文档。所以出了点问题。

有任何想法吗?谢谢!

4

3 回答 3

1

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

于 2010-10-01T18:28:32.093 回答
1

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

于 2010-10-01T18:31:13.470 回答
1

原来我需要跳过使用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);
于 2010-10-04T14:30:56.277 回答