3

編集

.vbsファイルにエラー処理を追加しましたが、これは実際にアクセス許可の問題です(「アクセス許可が拒否されました」エラーが発生します)。ただし、web.config<impersonate>タグでクレデンシャルを指定しても効果がないようです。

また、経由でプロセスにクレデンシャルを提供しようとする場合

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

新しいエラーが発生します:

cscript.exe-アプリケーションエラー

アプリケーションは正しく初期化できませんでした(0xc0000142)。[OK]をクリックして、アプリケーションを終了します。

これを引き起こしている原因がわかっている場合は、それを叫んでください。(または単に入力してください...

これまでのご協力に感謝します!


バックグラウンド

カスタムハンドラー(.ashx)から.vbsファイルを実行しようとしています。VBScriptは、iis5.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 ScriptHostバージョン5.7Copyright(C)MicrosoftCorporation。全著作権所有

コマンドラインから

Microsoft(R)Windows ScriptHostバージョン5.7Copyright(C)MicrosoftCorporation。全著作権所有

こんにちは

したがって、.vbsファイルが評価されておらず、cscriptが呼び出されていることを証明できます(私は思います)。また、.vbsファイルを参照せずにcscriptを呼び出すと、ヘルプドキュメントが表示されます。だから何かがうまくいかない。

何か案は?ありがとう!

4

3 に答える 3

1

問題(おそらく全体の問題ではない)は、IISを実行しているユーザーが、ターゲットマシンでスクリプトを実行する権限を持っていないことだと思います。

于 2010-10-01T18:28:32.093 に答える
1

Webサイトを作成するには、管理者である必要があります。管理者ユーザーとして実行するようにWebアプリを変更する必要があります。または、管理者ユーザーとしてcscriptプロセスを起動することもできます。

于 2010-10-01T18:31:13.470 に答える
1

System.Diagnostics.Processkernel32.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 に答える