web-dev-qa-db-fra.com

Passer des arguments de ligne de commande en C #

J'essaye de passer des arguments de ligne de commande à une application C #, mais j'ai du mal à passer quelque chose comme ça

"C:\Documents and Settings\All Users\Start Menu\Programs\App name"

même si j'ajoute " " à l'argument.

Voici mon code:

    public ObjectModel(String[] args)
    {
        if (args.Length == 0) return; //no command line arg.
        //System.Windows.Forms.MessageBox.Show(args.Length.ToString());
        //System.Windows.Forms.MessageBox.Show(args[0]);
        //System.Windows.Forms.MessageBox.Show(args[1]);
        //System.Windows.Forms.MessageBox.Show(args[2]);
        //System.Windows.Forms.MessageBox.Show(args[3]);
        if (args.Length == 3)
        {
            try
            {
                RemoveInstalledFolder(args[0]);
                RemoveUserAccount(args[1]);
                RemoveShortCutFolder(args[2]);
                RemoveRegistryEntry();
            }
            catch (Exception e)
            {
            }
        }
        }

Et voici ce que je passe:

C:\WINDOWS\Uninstaller.exe  "C:\Program Files\Application name\"  "username"  "C:\Documents and Settings\All Users\Start Menu\Programs\application name"

Le problème est que je peux obtenir le premier et le second argument correctement, mais le dernier qu'il obtient comme C:\Documents.

De l'aide?

18
Mark

J'ai juste fait une vérification et vérifié le problème. Cela m'a surpris, mais c'est le dernier\du premier argument.

"C:\Program Files\Application name\" <== remove the last '\'

Cela nécessite plus d'explications, est-ce que quelqu'un a une idée? J'ai tendance à appeler cela un bug.


Partie 2, j'ai effectué quelques tests supplémentaires et

"X:\\aa aa\\" "X:\\aa aa\" next

devient

X:\\aa aa\
X:\\aa aa" next

Une petite action de Google donne un aperçu d'un blog de Jon Galloway , les règles de base sont:

  • la barre oblique inverse est le caractère d'échappement
  • toujours échapper aux citations
  • échapper uniquement aux contre-obliques lorsqu'elles précèdent une citation.
27
Henk Holterman

Pour ajouter la réponse de Ian Kemp

Si votre Assembly s'appelle "myProg.exe" et que vous passez la chaîne "C:\Documents and Settings\All Users\Start Menu\Programs\App name", alors

C:\>myprog.exe "C:\Documents and Settings\All Users\Start Menu\Programs\App name"

la chaîne "C:\Documents and Settings\All Users\Start Menu\Programs\App name"

sera à args [0].

5
Johnno Nolan

J'ai remarqué le même problème ennuyeux récemment et j'ai décidé d'écrire un analyseur pour analyser moi-même le tableau d'arguments de ligne de commande.

Remarque: le problème est que les arguments .NET CommandLine passés à la fonction static void Main (string [] args) échappent à\"et \\. C'est par conception, car vous pouvez en fait passer un argument avec barre oblique inverse. Un exemple:

disons que vous vouliez passer ce qui suit comme argument unique:

-msg: Hé, "Où es-tu?"

par exemple.

sampleapp -msg: "Hé, \" Où es-tu?\""

Serait comment l'envoyer avec le comportement par défaut.

Si vous ne voyez aucune raison pour que quiconque doive échapper des guillemets ou des barres obliques inverses pour votre programme, vous pouvez utiliser votre propre analyseur pour analyser la ligne de commande, comme ci-dessous.

C'EST À DIRE. [programme] .exe "C:\test \" arg1 arg2

aurait un args [0] = c:\test "arg1 arg2

Ce que vous attendez, c'est args [0] = c:\test\puis args [1] = arg1 et args [2] = arg2.

La fonction ci-dessous analyse les arguments dans une liste avec ce comportement simplifié.

Notez que arg [0] est le nom du programme utilisant le code ci-dessous. (Vous appelez List.ToArray () pour convertir la liste résultante en un tableau de chaînes.)

protected enum enumParseState : int { StartToken, InQuote, InToken };
public static List<String> ManuallyParseCommandLine()
{
    String CommandLineArgs = Environment.CommandLine.ToString();

    Console.WriteLine("Command entered: " + CommandLineArgs);

    List<String> listArgs = new List<String>();

    Regex rWhiteSpace = new Regex("[\\s]");
    StringBuilder token = new StringBuilder();
    enumParseState eps = enumParseState.StartToken;

    for (int i = 0; i < CommandLineArgs.Length; i++)
    {
        char c = CommandLineArgs[i];
    //    Console.WriteLine(c.ToString()  + ", " + eps);
        //Looking for beginning of next token
        if (eps == enumParseState.StartToken)
        {
            if (rWhiteSpace.IsMatch(c.ToString()))
            {
                //Skip whitespace
            }
            else
            {
                token.Append(c);
                eps = enumParseState.InToken;
            }


        }
        else if (eps == enumParseState.InToken)
        {
            if (rWhiteSpace.IsMatch(c.ToString()))
            {
                Console.WriteLine("Token: [" + token.ToString() + "]");
                listArgs.Add(token.ToString().Trim());
                eps = enumParseState.StartToken;

                //Start new token.
                token.Remove(0, token.Length);
            }
            else if (c == '"')
            {
               // token.Append(c);
                eps = enumParseState.InQuote;
            }
            else
            {
                token.Append(c);
                eps = enumParseState.InToken;
            }

        }
            //When in a quote, white space is included in the token
        else if (eps == enumParseState.InQuote)
        {
            if (c == '"')
            {
               // token.Append(c);
                eps = enumParseState.InToken;
            }
            else
            {
                token.Append(c);
                eps = enumParseState.InQuote;
            }

        }


    }
    if (token.ToString() != "")
    {
        listArgs.Add(token.ToString());
        Console.WriteLine("Final Token: " + token.ToString());
    }
    return listArgs;
}
1
WWC

Pour ajouter à ce que tout le monde a déjà dit, cela pourrait être un problème échappant. Vous devez échapper vos contre-obliques par une autre contre-oblique.

Devrait être quelque chose comme:

C: \> myprog.exe "C: \\ Documents and Settings \\ All Users \\ Start Menu \\ Programs \\ App name"

1
Aamir

En réponse à la réponse de WWC, Jamezor a fait remarquer que son code échouera si le premier caractère est une citation.

Pour résoudre ce problème, vous pouvez remplacer le cas StartToken par ceci:

            if (eps == enumParseState.StartToken)
            {
                if (rWhiteSpace.IsMatch(c.ToString()))
                {
                    //Skip whitespace
                }
                else if (c == '"')
                {
                    eps = enumParseState.InQuote;
                }
                else
                {
                    token.Append(c);
                    eps = enumParseState.InToken;
                }
            }
1
guesser

Quel est le problème exactement? Quoi qu'il en soit, voici quelques conseils généraux:

Assurez-vous que votre méthode Main (dans Program.cs) est définie comme:

void Main(string[] args)

Alors args est un tableau contenant les arguments de ligne de commande.

0
Ian Kemp