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

本文关键字:运行 powershell 脚本 文件 服务 web | 更新日期: 2023-09-27 17:51:19

我创建了一个web服务,我想从web服务运行一个powershell脚本。我已经将.ps1文件存储在存储web服务的服务器的c:'目录下。当我调用webservice时,我得到一个错误,说"术语——方法名——不被识别为cmdlet、函数、脚本文件或可操作程序的名称

当我从服务器上调用webservice时,它工作得很好

方法如下:

[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. "

我应该做些什么来纠正这个问题?

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

您应该使用AddScript方法而不是Add方法。现在它试图寻找一个命令,而你的脚本可能有多个命令。

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

现在这种方法可能有点过头了,但是如果您的脚本需要执行更强大的操作(如与用户交互或显示UI),则值得分享。如果不是这种情况,不要选择这种方法。如果是,则此方法将web服务appool作为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();
        }