Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class UnManagedProcess : IProcess
- {
- private IntPtr _userToken;
- private IntPtr _duplicatedUserToken;
- private ProcessInformation _processInfo;
- private StartupInfo _startupInfo;
- private SecurityAttributes _securityAttributes;
- private ProfileInfo _profileInfo;
- private readonly ProcessStartInfo _processStartInfo;
- private readonly int _creationFlags;
- private readonly TimeSpan? _timeOut;
- private readonly List<string> _arguments;
- private readonly UnManagedEnvironmentVariables _environments;
- public bool RedirectStandardError => false;
- public bool RedirectStandardOutput => false;
- public bool IsExited { get; private set; }
- public int ExitCode { get; private set; }
- public DateTime StartTime { get; private set; }
- public DateTime ExitTime { get; private set; }
- public bool IsInterrupted { get; private set; }
- public int ErrorCode { get; private set; }
- public UnManagedProcess(Script script)
- {
- _processStartInfo = new ProcessInfoBuilder().FileName(script.FileName).AddEnvironmentVariables(script.Arguments).WithUsersCredentials(script.Login, script.Password, script.Domain).Create();
- _processInfo = new ProcessInformation();
- _userToken = IntPtr.Zero;
- _duplicatedUserToken = IntPtr.Zero;
- _securityAttributes = new SecurityAttributes();
- _securityAttributes.Length = Marshal.SizeOf(_securityAttributes);
- _startupInfo = new StartupInfo();
- _startupInfo.cb = Marshal.SizeOf(_startupInfo);
- _startupInfo.lpDesktop = string.Empty;
- _creationFlags = (int) (CreationFlags.CreateUnicodeEnvironment | CreationFlags.CreateNoWindow);
- _profileInfo = new ProfileInfo();
- _profileInfo.dwSize = Marshal.SizeOf(_profileInfo);
- _profileInfo.lpUserName = _processStartInfo.UserName;
- _profileInfo.dwFlags = 1;
- if (!script.WaitForever)
- {
- _timeOut = TimeSpan.FromSeconds(script.TimeOutInSeconds);
- }
- _arguments = script.Arguments;
- _environments = new UnManagedEnvironmentVariables();
- }
- public async Task StartAsync()
- {
- StartTime = DateTime.Now;
- StartProcess();
- var waitTask = new Task(WaitProcess);
- waitTask.Start();
- try
- {
- if (_timeOut != null)
- {
- await waitTask.TimeoutAfter(_timeOut.Value);
- }
- else
- {
- await waitTask;
- }
- }
- catch (TimeoutException)
- {
- IsInterrupted = true;
- KillProcess();
- }
- ExitTime = DateTime.Now;
- }
- public Task<string> ReadAllFromStandardErrorAsync(TimeSpan timeOut)
- {
- return Task.FromResult(string.Empty);
- }
- public Task<string> ReadAllFromStandardOutputAsync(TimeSpan timeOut)
- {
- return Task.FromResult(string.Empty);
- }
- public void Dispose()
- {
- if (_userToken != IntPtr.Zero)
- CloseHandle(_userToken);
- if (_duplicatedUserToken != IntPtr.Zero)
- CloseHandle(_duplicatedUserToken);
- if (_processInfo.hProcess != IntPtr.Zero)
- CloseHandle(_processInfo.hProcess);
- if (_processInfo.hThread != IntPtr.Zero)
- CloseHandle(_processInfo.hThread);
- }
- private void StartProcess()
- {
- LogOnUser(_processStartInfo.UserName, _processStartInfo.Domain, _processStartInfo.PasswordInClearText);
- DuplicateToken();
- FillEnvironment();
- LoadUserProfile();
- var arguments = "/c" + " " + _processStartInfo.FileName;
- CreateProcess("C:\\windows\\System32\\cmd.exe", arguments, _environments.GetEnvironmentBlock());
- }
- private void CreateProcess(string fileName, string arguments, IntPtr environment)
- {
- var successful = CreateProcessAsUser(_duplicatedUserToken,
- fileName,
- arguments,
- ref _securityAttributes,
- ref _securityAttributes,
- false,
- _creationFlags,
- environment,
- _processStartInfo.WorkingDirectory,
- ref _startupInfo,
- ref _processInfo);
- ThrowIfError(successful);
- }
- private void LoadUserProfile()
- {
- var successful = Win32ProcessUtility.LoadUserProfile(_duplicatedUserToken, ref _profileInfo);
- ThrowIfError(successful);
- }
- private void DuplicateToken()
- {
- var successful = DuplicateTokenEx(_userToken,
- GenericAllAccess,
- ref _securityAttributes,
- (int) SecurityImpersonationLevel.SecurityIdentification,
- (int) TokenType.TokenPrimary,
- ref _duplicatedUserToken);
- ThrowIfError(successful);
- }
- private void LogOnUser(string name, string domain, string password)
- {
- var successful = LogonUser(name,
- domain,
- password,
- LOGON32_LOGON_INTERACTIVE,
- LOGON32_PROVIDER_DEFAULT,
- ref _userToken) != 0;
- ThrowIfError(successful);
- }
- private void FillEnvironment()
- {
- var successful = _environments.ReadEnvironmentBlock(_userToken);
- if (_arguments != null)
- {
- foreach (var argument in _arguments)
- {
- var pair = argument.Split(new[] {'='}, 2);
- _environments.Add(pair[0], pair[1]);
- }
- }
- ThrowIfError(successful);
- }
- private void WaitProcess()
- {
- var result = WaitForSingleObject(_processInfo.hProcess, Infinite);
- switch ((WaitForSingleObjectResult) result)
- {
- case WaitForSingleObjectResult.WaitObject0:
- IsExited = true;
- ExitCode = GetExitCode();
- break;
- case WaitForSingleObjectResult.WaitTimeout:
- IsExited = true;
- IsInterrupted = true;
- KillProcess();
- ExitCode = GetExitCode();
- break;
- case WaitForSingleObjectResult.WaitFailed:
- IsExited = false;
- IsInterrupted = true;
- throw new Win32Exception(Marshal.GetLastWin32Error());
- case WaitForSingleObjectResult.WaitAbandoned:
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- private void KillProcess()
- {
- var successful = TerminateProcess(_processInfo.hProcess, 1);
- ThrowIfError(successful);
- ExitCode = GetExitCode();
- }
- private int GetExitCode()
- {
- var successful = GetExitCodeProcess(_processInfo.hProcess, out var result);
- ThrowIfError(successful);
- return (int) result;
- }
- private void ThrowIfError(bool successful)
- {
- if (successful) return;
- ErrorCode = Marshal.GetLastWin32Error();
- throw new Win32Exception(ErrorCode);
- }
- internal class UnManagedEnvironmentVariables
- {
- private static readonly string Format = "{0}={1}";
- private static readonly char[] SplitSymb = {'='};
- private Dictionary<string, string> Variables { get; }
- public UnManagedEnvironmentVariables()
- {
- Variables = new Dictionary<string, string>();
- }
- public bool ReadEnvironmentBlock(IntPtr userToken)
- {
- var successful = CreateEnvironmentBlock(out var environmentBlock, userToken, false);
- var startPosition = environmentBlock;
- if (successful)
- {
- while (true)
- {
- var value = Marshal.PtrToStringUni(startPosition);
- if (string.IsNullOrEmpty(value))
- break;
- var pair = value.Split(SplitSymb, 2);
- Variables.Add(pair[0], pair[1]);
- startPosition = startPosition + (value.Length + 1) * sizeof(char);
- }
- DestroyEnvironmentBlock(environmentBlock);
- }
- return successful;
- }
- public IntPtr GetEnvironmentBlock()
- {
- var stringEnv = string.Join("\0", Variables.Select(pair => string.Format(Format, pair.Key, pair.Value))) + "\0\0\0\0";
- return Marshal.StringToHGlobalUni(stringEnv);
- }
- public void Add(string key, string value)
- {
- Variables.Add(key, value);
- }
- }
- }
Add Comment
Please, Sign In to add comment