如何从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. "
我应该做些什么来纠正这个问题?
您应该使用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();
}