Эквивалент Process.Start() без отдельных аргументов

Я пишу простое приложение, которое требуется для запуска произвольных команд, например:

powershell -File myscript.ps1
cmd /C "ping localhost"

Process.Start() был бы совершенным, за исключением того, что аргументы должны предоставляться как отдельный параметр. Первоначально я думал, что могу просто разбить строку на первый символ пробела, но тогда что, если исполняемый путь цитируется и содержит пробелы? Есть ли что-то вроде Process.Start(), которое позволяет вам просто указать ему строку с аргументами или без нее и просто выполнить ее, как если бы она была вставлена ​​в командную строку?

Ответ 1

Почему бы вам просто не запустить все через cmd/C?

Process.Start("cmd", "/C " + command);

Ответ 2

Просто вызовите функцию CreateProcess:

public static class Native
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

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

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

    public static void CreateProcessFromCommandLine(string commandLine)
    {
        var si = new STARTUPINFO();
        var pi = new PROCESS_INFORMATION();

        CreateProcess(
            null,
            commandLine,
            IntPtr.Zero,
            IntPtr.Zero,
            false,
            0,
            IntPtr.Zero,
            null,
            ref si,
            out pi);
    }
}

internal class Program
{
    public static void Main()
    {
        Native.CreateProcessFromCommandLine("ping google.com -t");

        Console.Read();
    }
}

Ответ 3

Вы можете использовать класс Path для оценки строки командной строки и прогона Process.Start следующим образом:

// This is our command string
var cmd = @"C:\Program Files\Sub folder 1\executable name.exe -arg1 -arg2 -argN"; 

var exeName = Path.GetFileName(cmd); // "executable name.exe -arg1 -arg2 -argN"

var borderPos = exeName.IndexOf(".exe") // or .cmd, .bat, etc.
borderPos = borderPos == -1 ? exeName.IndexOf(" ") : borderPos + 4;

var arguments = exeName.Substring(borderPos).Trim();
var program = cmd.Substring(0, cmd.Length - arguments.Length);

Process.Start(program, aguments);

Что-то вроде этого должно это сделать, но вышеприведенные коды непроверены...