poner laptop invertida inverso inclinada hacia derecha como barra c# .net

c# - laptop - poner diagonal invertida php



Barra invertida y comillas en argumentos de línea de comandos (5)

De acuerdo con este artículo de Jon Galloway , puede haber un comportamiento extraño al usar barras diagonales inversas en los argumentos de la línea de comandos.

En particular, menciona que "la mayoría de las aplicaciones (incluidas las aplicaciones .NET) utilizan CommandLineToArgvW para decodificar sus líneas de comando. Utiliza reglas de escape locas que explican el comportamiento que está viendo " .

Explica que el primer conjunto de barras invertidas no requiere que se escape, pero las barras invertidas que vienen después de los caracteres alfa (¿quizás también numéricos?) Requieren que se escapen y que las comillas siempre deben escaparse.

Basado en estas reglas, creo que para obtener los argumentos que deseas deberías pasarlos como:

a "b" "//x////" "/x//"

"Whacky" de hecho.

¿El siguiente comportamiento es una característica o un error en C # .NET?

Aplicación de prueba:

using System; using System.Linq; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Arguments:"); foreach (string arg in args) { Console.WriteLine(arg); } Console.WriteLine(); Console.WriteLine("Command Line:"); var clArgs = Environment.CommandLine.Split('' ''); foreach (string arg in clArgs.Skip(clArgs.Length - args.Length)) { Console.WriteLine(arg); } Console.ReadKey(); } } }

Ejecutarlo con argumentos de línea de comando:

a "b" "//x//" "/x/"

En el resultado recibo:

Arguments: a b //x/ /x" Command Line: a "b" "//x//" "/x/"

Faltan barras invertidas y comillas no eliminadas en los argumentos pasados ​​al método Main (). ¿Cuál es la solución correcta, excepto el análisis manual de Environment.CommandLine ?


Después de mucha experimentación esto me funcionó. Estoy tratando de crear un comando para enviar a la línea de comandos de Windows. El nombre de una carpeta aparece después de la opción -graphical en el comando, y como puede tener espacios en ella, debe estar entre comillas dobles. Cuando utilicé barras diagonales para crear las comillas, salieron como literales en el comando. Así que esto. . . .

string q = @"" + (char) 34; string strCmdText = string.Format(@"/C cleartool update -graphical {1}{0}{1}", this.txtViewFolder.Text, q); System.Diagnostics.Process.Start("CMD.exe", strCmdText);

q es una cadena que contiene solo un carácter de comillas dobles. Está precedido por @ para convertirlo en un literal de cadena literal .

La plantilla de comando también es una cadena literal, y el método string.Format se usa para compilar todo en strCmdText .


Esto funciona para mí y funciona correctamente con el ejemplo de la pregunta.

/// <summary> /// https://www.pinvoke.net/default.aspx/shell32/CommandLineToArgvW.html /// </summary> /// <param name="unsplitArgumentLine"></param> /// <returns></returns> static string[] SplitArgs(string unsplitArgumentLine) { int numberOfArgs; IntPtr ptrToSplitArgs; string[] splitArgs; ptrToSplitArgs = CommandLineToArgvW(unsplitArgumentLine, out numberOfArgs); // CommandLineToArgvW returns NULL upon failure. if (ptrToSplitArgs == IntPtr.Zero) throw new ArgumentException("Unable to split argument.", new Win32Exception()); // Make sure the memory ptrToSplitArgs to is freed, even upon failure. try { splitArgs = new string[numberOfArgs]; // ptrToSplitArgs is an array of pointers to null terminated Unicode strings. // Copy each of these strings into our split argument array. for (int i = 0; i < numberOfArgs; i++) splitArgs[i] = Marshal.PtrToStringUni( Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); return splitArgs; } finally { // Free memory obtained by CommandLineToArgW. LocalFree(ptrToSplitArgs); } } [DllImport("shell32.dll", SetLastError = true)] static extern IntPtr CommandLineToArgvW( [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); [DllImport("kernel32.dll")] static extern IntPtr LocalFree(IntPtr hMem); static string Reverse(string s) { char[] charArray = s.ToCharArray(); Array.Reverse(charArray); return new string(charArray); } static string GetEscapedCommandLine() { StringBuilder sb = new StringBuilder(); bool gotQuote = false; foreach (var c in Environment.CommandLine.Reverse()) { if (c == ''"'') gotQuote = true; else if (gotQuote && c == ''//') { // double it sb.Append(''//'); } else gotQuote = false; sb.Append(c); } return Reverse(sb.ToString()); } static void Main(string[] args) { // Crazy hack args = SplitArgs(GetEscapedCommandLine()).Skip(1).ToArray(); }


He escapado al problema de la otra manera ...

En lugar de obtener argumentos ya analizados, obtengo la cadena de argumentos tal como está y luego uso mi propio analizador:

static void Main(string[] args) { var param = ParseString(Environment.CommandLine); ... } // The following template implements the following notation: // -key1 = some value -key2 = "some value even with ''-'' character " ... private const string ParameterQuery = "//-(?<key>//w+)//s*=//s*(/"(?<value>[^/"]*)/"|(?<value>[^//-]*))//s*"; private static Dictionary<string, string> ParseString(string value) { var regex = new Regex(ParameterQuery); return regex.Matches(value).Cast<Match>().ToDictionary(m => m.Groups["key"].Value, m => m.Groups["value"].Value); }

Este concepto le permite escribir comillas sin el prefijo de escape.


Me encontré con este mismo problema el otro día y tuve un momento difícil para solucionarlo. En mi búsqueda en Google, encontré este artículo relacionado con VB.NET (el idioma de mi aplicación) que resolvió el problema sin tener que cambiar ninguno de mis otros códigos según los argumentos.

En ese artículo, se refiere al artículo original que fue escrito para C #. Aquí está el código real, lo pasas Environment.CommandLine() :

DO#

class CommandLineTools { /// <summary> /// C-like argument parser /// </summary> /// <param name="commandLine">Command line string with arguments. Use Environment.CommandLine</param> /// <returns>The args[] array (argv)</returns> public static string[] CreateArgs(string commandLine) { StringBuilder argsBuilder = new StringBuilder(commandLine); bool inQuote = false; // Convert the spaces to a newline sign so we can split at newline later on // Only convert spaces which are outside the boundries of quoted text for (int i = 0; i < argsBuilder.Length; i++) { if (argsBuilder[i].Equals(''"'')) { inQuote = !inQuote; } if (argsBuilder[i].Equals('' '') && !inQuote) { argsBuilder[i] = ''/n''; } } // Split to args array string[] args = argsBuilder.ToString().Split(new char[] { ''/n'' }, StringSplitOptions.RemoveEmptyEntries); // Clean the ''"'' signs from the args as needed. for (int i = 0; i < args.Length; i++) { args[i] = ClearQuotes(args[i]); } return args; } /// <summary> /// Cleans quotes from the arguments.<br/> /// All signle quotes (") will be removed.<br/> /// Every pair of quotes ("") will transform to a single quote.<br/> /// </summary> /// <param name="stringWithQuotes">A string with quotes.</param> /// <returns>The same string if its without quotes, or a clean string if its with quotes.</returns> private static string ClearQuotes(string stringWithQuotes) { int quoteIndex; if ((quoteIndex = stringWithQuotes.IndexOf(''"'')) == -1) { // String is without quotes.. return stringWithQuotes; } // Linear sb scan is faster than string assignemnt if quote count is 2 or more (=always) StringBuilder sb = new StringBuilder(stringWithQuotes); for (int i = quoteIndex; i < sb.Length; i++) { if (sb[i].Equals(''"'')) { // If we are not at the last index and the next one is ''"'', we need to jump one to preserve one if (i != sb.Length - 1 && sb[i + 1].Equals(''"'')) { i++; } // We remove and then set index one backwards. // This is because the remove itself is going to shift everything left by 1. sb.Remove(i--, 1); } } return sb.ToString(); } }

VB.NET:

Imports System.Text '' Original version by Jonathan Levison (C#)'' '' http://sleepingbits.com/2010/01/command-line-arguments-with-double-quotes-in-net/ '' converted using http://www.developerfusion.com/tools/convert/csharp-to-vb/ '' and then some manual effort to fix language discrepancies Friend Class CommandLineHelper '''''' <summary> '''''' C-like argument parser '''''' </summary> '''''' <param name="commandLine">Command line string with arguments. Use Environment.CommandLine</param> '''''' <returns>The args[] array (argv)</returns> Public Shared Function CreateArgs(commandLine As String) As String() Dim argsBuilder As New StringBuilder(commandLine) Dim inQuote As Boolean = False '' Convert the spaces to a newline sign so we can split at newline later on '' Only convert spaces which are outside the boundries of quoted text For i As Integer = 0 To argsBuilder.Length - 1 If argsBuilder(i).Equals(""""c) Then inQuote = Not inQuote End If If argsBuilder(i).Equals(" "c) AndAlso Not inQuote Then argsBuilder(i) = ControlChars.Lf End If Next '' Split to args array Dim args As String() = argsBuilder.ToString().Split(New Char() {ControlChars.Lf}, StringSplitOptions.RemoveEmptyEntries) '' Clean the ''"'' signs from the args as needed. For i As Integer = 0 To args.Length - 1 args(i) = ClearQuotes(args(i)) Next Return args End Function '''''' <summary> '''''' Cleans quotes from the arguments.<br/> '''''' All signle quotes (") will be removed.<br/> '''''' Every pair of quotes ("") will transform to a single quote.<br/> '''''' </summary> '''''' <param name="stringWithQuotes">A string with quotes.</param> '''''' <returns>The same string if its without quotes, or a clean string if its with quotes.</returns> Private Shared Function ClearQuotes(stringWithQuotes As String) As String Dim quoteIndex As Integer = stringWithQuotes.IndexOf(""""c) If quoteIndex = -1 Then Return stringWithQuotes '' Linear sb scan is faster than string assignemnt if quote count is 2 or more (=always) Dim sb As New StringBuilder(stringWithQuotes) Dim i As Integer = quoteIndex Do While i < sb.Length If sb(i).Equals(""""c) Then '' If we are not at the last index and the next one is ''"'', we need to jump one to preserve one If i <> sb.Length - 1 AndAlso sb(i + 1).Equals(""""c) Then i += 1 End If '' We remove and then set index one backwards. '' This is because the remove itself is going to shift everything left by 1. sb.Remove(System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1), 1) End If i += 1 Loop Return sb.ToString() End Function End Class