C# и .NET 4.6.1. Создание дочернего процесса в другом родительском процессе.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 C# и .NET 4.6.1. Создание дочернего процесса в другом родительском процессе.

Сообщение Anonymous »

Я пытаюсь написать приложение, которое будет порождать дочерний процесс под другим родительским процессом, а также мне нужно получить его выходные данные.
В основном это будет в проводнике .exe того же пользовательского контекста, что не должно вызывать каких-либо проблем с безопасностью Windows. Я пытаюсь заставить это работать для Windows 7 и более поздних версий, а также пытаюсь заставить это работать от имени обычного пользователя, а не администратора.
У меня возникла проблема: что не похоже, что он порождает дочерний элемент под новым родителем. Если я создаю его в процессе работы приложения, оно работает нормально, не знаю, что я делаю не так.
Я просмотрел текст, и, похоже, это не помогает.< /p>

Код: Выделить всё

using System.Runtime.InteropServices;
using System;
using NLog;
using System.Diagnostics;
using System.Threading;
using System.Security.Permissions;
using System.Security.AccessControl;
using System.IO;
using NPOI.SS.Formula.Functions;
using Microsoft.Win32.SafeHandles;

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFOEX
{
public STARTUPINFO StartupInfo;
public IntPtr lpAttributeList;
}

public enum HANDLE_FLAGS : uint
{
None = 0,
INHERIT = 1,
PROTECT_FROM_CLOSE = 2
}

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int 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 int dwProcessId;
public int dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
public struct SIZE_T
{
public UIntPtr _value;
}

namespace LaunchProcess
{
public static class LaunchProcess
{
private static readonly Logger Log = LogManager.GetCurrentClassLogger();

const uint MAXIMUM_ALLOWED = 0x02000000;
const int ProcessParentPid = 0x00000002;
public const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;
public const int STARTF_USESTDHANDLES = 0x00000100;
public const int STARTF_USESHOWWINDOW = 0x00000001;
public const ushort SW_HIDE = 0x0000;
public const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
public const uint CREATE_NO_WINDOW = 0x08000000;
public const uint CreateSuspended = 0x00000004;

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CreateProcess(
string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFOEX lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UpdateProcThreadAttribute(
IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue,
IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool InitializeProcThreadAttributeList(
IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);

[DllImport("kernel32.dll", SetLastError = true)]
[return:  MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, uint nSize);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);

public static string CreateProcess(string processName, string command, string parentProcess = null)
{
Log.Trace($"Spawning {processName} with command {command}");

const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;

// Create pipe for output capture
IntPtr hReadPipe = IntPtr.Zero, hWritePipe = IntPtr.Zero;
SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES();
securityAttributes.nLength = Marshal.SizeOf(securityAttributes);
securityAttributes.bInheritHandle = true;
CreatePipe(out hReadPipe, out hWritePipe, ref securityAttributes, 0);
SafeFileHandle safeReadPipe = new SafeFileHandle(hReadPipe, ownsHandle: false);
SetHandleInformation(hReadPipe, 1, 0); // Prevent inheritance of the read pipe

var pInfo = new PROCESS_INFORMATION();
var sInfoEx = new STARTUPINFOEX();
sInfoEx.StartupInfo.cb = Marshal.SizeOf(sInfoEx);
sInfoEx.StartupInfo.hStdOutput = hWritePipe;
sInfoEx.StartupInfo.dwFlags |= 0x00000100; // Set the STARTF_USESTDHANDLES flag
IntPtr lpValue = IntPtr.Zero;

bool processCreated = false; // Flag to indicate if the process was created successfully
string commandLine = $"{processName} {command}";
var lpApplicationName = Path.Combine(Environment.SystemDirectory, "cmd.exe");

try
{
if (string.IsNullOrEmpty(parentProcess))
{
Log.Trace($"Creating process with command: {commandLine}");

// Create the process
//processCreated = CreateProcess(null, commandLine, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
processCreated = CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref sInfoEx, out pInfo);

}
else
{
int PPID = GetParentProcessId(parentProcess);

if (PPID != -1)
{
var lpSize = IntPtr.Zero;
var success = InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize);

if (success || lpSize == IntPtr.Zero)
{
//Log.Error($"Failed to open parent process handle.  Error: {Marshal.GetLastWin32Error()}");
return "";
}

sInfoEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
success = InitializeProcThreadAttributeList(sInfoEx.lpAttributeList, 1, 0, ref lpSize);
if (!success)
{
return "";
}

var parentHandle = Process.GetProcessById(PPID).Handle;
// This value should persist until the attribute list is destroyed using the DeleteProcThreadAttributeList function
lpValue = Marshal.AllocHGlobal(IntPtr.Size);
Marshal.WriteIntPtr(lpValue, parentHandle);

success = UpdateProcThreadAttribute(
sInfoEx.lpAttributeList,
0,
(IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
lpValue,
(IntPtr)IntPtr.Size,
IntPtr.Zero,
IntPtr.Zero);

if (!success)
{
return "";
}

var pSec = new SECURITY_ATTRIBUTES();
var tSec = new SECURITY_ATTRIBUTES();
pSec.nLength = Marshal.SizeOf(pSec);
tSec.nLength = Marshal.SizeOf(tSec);
//var lpApplicationName = Path.Combine(Environment.SystemDirectory, "notepad.exe");
processCreated = CreateProcess(lpApplicationName, null, ref pSec, ref tSec, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref sInfoEx, out pInfo);
}
}

// Check if process was created successfully
if (!processCreated)
{
Log.Error($"CreateProcess failed.  Error: {Marshal.GetLastWin32Error()}");
return "";
}

Log.Trace($"Created process with PID: {pInfo.dwProcessId}");

Process proc = Process.GetProcessById(pInfo.dwProcessId);
proc.WaitForExit();

// Read process output using a StreamReader
string output = "";

using (var outputStream = new FileStream(safeReadPipe, FileAccess.Read, 4096, false))
using (var reader = new StreamReader(outputStream))
{
char[] buffer = new char[4096];
int read;

while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
output += new string(buffer, 0, read);
}
}

return output; // Return the captured output
}
finally
{
// Free the attribute list
if (sInfoEx.lpAttributeList != IntPtr.Zero)
{
DeleteProcThreadAttributeList(sInfoEx.lpAttributeList);
Marshal.FreeHGlobal(sInfoEx.lpAttributeList);
}
Marshal.FreeHGlobal(lpValue);

// Close process and thread handles
if (pInfo.hProcess != IntPtr.Zero)
{
CloseHandle(pInfo.hProcess);
}

if (pInfo.hThread != IntPtr.Zero)
{
CloseHandle(pInfo.hThread);
}

if (hReadPipe != IntPtr.Zero)
{
CloseHandle(hReadPipe);
}

if (hWritePipe != IntPtr.Zero)
{
CloseHandle(hWritePipe);
}
}
}

private static int GetParentProcessId(string processName)
{
// Find the process by the specified name
Process[] processes = Process.GetProcessesByName(processName);

if (processes.Length > 0)
{
Log.Trace($"Found {processName}.exe pid: {processes[0].Id}");
return processes[0].Id;
}
else
{
int currentProcessId = Process.GetCurrentProcess().Id;
Log.Trace($"Failed to find {processName}.exe");
Log.Trace($"Using current process pid: {currentProcessId}");
return currentProcessId;
}
}
}
}
И вот как я это называю:

Код: Выделить всё

var results = LaunchProcess.CreateProcess("cmd.exe", "/c " + command, "explorer");
Но когда я наблюдаю за процессами с помощью Process Explorer, я не вижу, чтобы он создавал новый процесс. Есть ли у кого-нибудь совет, как мне заставить это работать?

Подробнее здесь: https://stackoverflow.com/questions/790 ... nt-process
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»