如何从Web服务运行powershell脚本文件

时间:2013-01-10 19:47:10

标签: c# web-services powershell webserver asmx

我已经创建了一个Web服务,我想从webservice运行一个PowerShell脚本。我已将.ps1文件存储在存储Web服务的服务器的c:\上。当我调用webservice时,我收到一条错误消息,指出“术语--name of method--不被识别为cmdlet,函数,脚本文件或可操作程序的名称

当我从服务器调用web服务时,它正常运行。

这是我的方法:

[WebMethod]
public void RunUserProfileSync(string scriptText)
{
    RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
    runspace.Open();

    RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.Add(scriptText);

    // Execute PowerShell script
    pipeline.Invoke();
}

所以,在调用webmethod时,我在参数中放置了“c:\ nameoffile.ps1”。

我该怎么做才能纠正这个问题?

2 个答案:

答案 0 :(得分:1)

您应该使用AddScript方法而不是Add方法。现在它正在尝试查找单个命令,而您的脚本可能有多个命令。

编辑:您也可以尝试读取文件的内容,然后将其传递给AddScript。

答案 1 :(得分:0)

现在,这种方法可能已经过时了,但是如果您的脚本需要执行更强大的操作(例如与用户互动或显示UI),则值得分享。如果不是这种情况,请不要选择此方法。如果是这样,则此方法将Web服务apppool作为SYSTEM帐户运行,然后可以在任何用户会话(不仅仅是会话0)中运行脚本,如下所示:

[DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
        private static extern int OpenProcessToken(System.IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);

        [DllImport("kernel32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
        private static extern bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, IntPtr lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
        extern static Boolean DuplicateTokenEx(IntPtr ExistingTokenHandle, UInt32 dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, Int32 TokenType, Int32 ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private 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);

        #region Win32 Constants

        private const int NORMAL_PRIORITY_CLASS = 0x00000020;
        private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
        private const int CREATE_NO_WINDOW = 0x08000000;
        private const int CREATE_NEW_CONSOLE = 0x00000010;
        private const uint INVALID_SESSION_ID = 0xFFFFFFFF;
        private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
        private const int TOKEN_DUPLICATE = 2;
        private const int TOKEN_QUERY = 0X00000008;
        private const int TOKEN_IMPERSONATE = 0X00000004;
        private const uint MAXIMUM_ALLOWED = 0x2000000;
        private const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
        private const uint PROCESS_QUERY_INFORMATION = 0x0400;

        #endregion


        #region Win32 Structs

        private enum SW
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_NORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_MAXIMIZE = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_MAX = 10
        }

        private enum WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }

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

        private enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous = 0,
            SecurityIdentification = 1,
            SecurityImpersonation = 2,
            SecurityDelegation = 3,
        }

        [StructLayout(LayoutKind.Sequential)]
        private 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;
        }

        private enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation = 2
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct WTS_SESSION_INFO
        {
            public readonly UInt32 SessionID;

            [MarshalAs(UnmanagedType.LPStr)]
            public readonly String pWinStationName;

            public readonly WTS_CONNECTSTATE_CLASS State;
        }

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

然后您可以运行类似于我的功能,如下所示:

       public string Get(string YOURSCRIPT)
        {
            string command = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File " + YOURSCRIPT;
            bool isSuccessful = false;
            int targetSessionId = 1;
            uint targetWinlogonProcessId = 0;
            IntPtr hToken = IntPtr.Zero, hTokenDup = IntPtr.Zero;
            var procInfo = new PROCESS_INFORMATION();

            Process[] processes = Process.GetProcessesByName("winlogon");
            foreach (Process p in processes)
            {
                if ((uint)p.SessionId == targetSessionId)
                {
                    targetWinlogonProcessId = (uint)p.Id;
                }
            }

            IntPtr hProcess = OpenProcess(MAXIMUM_ALLOWED, false, targetWinlogonProcessId);


            if (OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hToken) != 0)
            {
                SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
                sa.Length = Marshal.SizeOf(sa);
                if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hTokenDup))
                {
                    STARTUPINFO si = new STARTUPINFO();
                    si.cb = (int)Marshal.SizeOf(si);

                    // interactive window station parameter; basically this indicates 
                    // that the process created can display a GUI on the desktop
                    si.lpDesktop = "winsta0\\default";

                    // flags that specify the priority and creation method of the process
                    int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

                    // create a new process in the current User's logon session
                    if (CreateProcessAsUser(hTokenDup,  // client's access token
                                                    null,             // file to execute
                                                    command,          // command line
                                                    ref sa,           // pointer to process SECURITY_ATTRIBUTES
                                                    ref sa,           // pointer to thread SECURITY_ATTRIBUTES
                                                    false,            // handles are not inheritable
                                                    dwCreationFlags,  // creation flags
                                                    IntPtr.Zero,      // pointer to new environment block 
                                                    null,             // name of current directory 
                                                    ref si,           // pointer to STARTUPINFO structure
                                                    out procInfo      // receives information about new process
                                                    ))
                    {
                        isSuccessful = true;
                    }
                    else
                    {
                        int error = Marshal.GetLastWin32Error();
                        int hr = Marshal.GetHRForLastWin32Error();
                    }

                }
                else
                {
                    CloseHandle(hProcess);
                    CloseHandle(hToken);
                }                
            }
            else
                CloseHandle(hProcess);

            return isSuccessful.ToString();
        }