es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Limpiar la transmisión de una lista de argumentos a ProcessStartInfo.

Los argumentos se reciben como string[] en un programa nuevo. Ya están parseados correctamente, por lo que las comillas mantendrán un parámetro junto, incluso si es una ruta que contiene espacios. Muy bien.

Ahora quiero enviarlos a un nuevo Process, pero ProcessStartInfo solo admite string para definir los argumentos.

Así que concatenarlos con espacios es incorrecto, ya que las rutas pueden entonces dividirse en varios argumentos. También tengo dudas si envolverlos en comillas y luego concatenarlos con espacios funciona en todos los casos, no creo que así sea, ya que el programa de destino puede no ver -u y "-u" como equivalentes. ¿Existe una forma limpia de hacer esto en el Framework .NET?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, existe una forma limpia de hacer esto en el Framework .NET. Puede utilizar la clase ‘ProcessStartInfo’ y configurar su propiedad ‘Arguments’ para que contenga un ‘string’ formateado correctamente utilizando la función ‘CommandLineToArgvW’ de la API Win32. Esta función maneja correctamente los argumentos que contienen espacios y comillas dobles, así como también escapa los caracteres que deben ser escapados.

    Aquí hay un ejemplo de cómo utilizar este enfoque:

    string[] arguments = ...; // argumentos recibidos
    
    string argumentsString = string.Join(" ", arguments); // convierte el array en un string con espacios
    
    ProcessStartInfo startInfo = new ProcessStartInfo("myprogram.exe");
    startInfo.Arguments = CommandLineToArgvW(argumentsString); // formatea el string de argumentos
    
    Process process = Process.Start(startInfo);
    

    Y aquí está la implementación de la función ‘CommandLineToArgvW’:

    [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern IntPtr CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
    
    private static string[] CommandLineToArgvW(string commandLine)
    {
        int numArgs;
        IntPtr argsPtr = CommandLineToArgvW(commandLine, out numArgs);
        if (argsPtr == IntPtr.Zero)
        {
            throw new Win32Exception();
        }
    
        string[] args = new string[numArgs];
        for (int i = 0; i < numArgs; i++)
        {
            IntPtr argPtr = Marshal.ReadIntPtr(argsPtr, i * IntPtr.Size);
            args[i] = Marshal.PtrToStringUni(argPtr);
        }
    
        return args;
    }
    

    Con este enfoque, puede pasar de manera segura los argumentos recibidos a un nuevo ‘Process’ sin tener que preocuparse por divisiones o formatos incorrectos.

Comments are closed.