kostenloser Webspace werbefrei: lima-city


C# || Argument mit Leerzeichen an Konsole übergeben

lima-cityForumProgrammiersprachenProgrammieren mit .NET & Mono

  1. Autor dieses Themas

    adelwoehrer

    Kostenloser Webspace von adelwoehrer

    adelwoehrer hat kostenlosen Webspace.

    Ich google nun schon eine Weile nach einer Lösung, bisher hat aber nichts geklappt.
    Ich würde gerne über C# eine Konsolenanwendung starten und ihr Argumente übergeben (Pfade), die allerdings Leerzeichen enthalten.
    Mir ist bewusst, dass man Pfadangaben, die Leerzeichen enthalten, in Anführungszeichen setzen soll.
    Das funktioniert auch, aber nur wenn ich die Konsole per Hand starte und danach die Pfade übergebe.
    Wenn ich die Konsole via C# starte und die Pfade dort als Argument eintrage, funktioniert nichts mehr.

    Das Programm selbst wandelt im Prinzip nur eine Cache-Datei in eine lesbare CSV-Datei um.
    Dazu wird einfach die Datei "dumber.exe" mit dem Parameter "--market" aufgerufen....danach der Speicherort der Cache-Datei und nach dem ">" dann den Ausgabeort als CSV-Datei.

    Befehl in Konsole via copy/paste (FUNKTIONIERT)
    "C:\Dokumente und Einstellungen\Administrator.TEST\Desktop\dumber.exe" --market "C:\Dokumente und Einstellungen\Administrator.TEST\Lokale Einstellungen\Anwendungsdaten\Testordner\1aa0.cache" > "C:\Dokumente und Einstellungen\Administrator.TEST\Desktop\Testordner\1aa0.csv"


    Befehl in C# via Argument (FUNKTIONIERT NICHT)
    p.StartInfo.Arguments = "/c \"C:\Dokumente und Einstellungen\Administrator.TEST\Desktop\dumber.exe\" --market \"C:\Dokumente und Einstellungen\Administrator.Test\Lokale Einstellungen\Anwendungsdaten\Testordner\1aa0.cache\" > \"C:\Dokumente und Einstellungen\Administrator.TEST\Desktop\Testordner\1aa0.csv\""


    ....im Debug-Modus in der Schnellansicht ergibt die C#-Zeile dann im Prinzip den Befehl, den ich nun einfach per Copy/Paste in die Konsole schmeißen könnte und er würde funktionieren.....aber die Konsole, die über C# gestartet wurde, führt ihn nicht aus.

    Jemand eine Idee?
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. m**********n

    Wenn ich mich nicht gan täusche, escapst (gibt es dafür eine korrekte Schreibweise?) du innerhalb deines Strings:
    Du schreibst in deinem C#-String das da:
    "\"C:\Dokumente und Einstellungen\Administrator.TEST\Desktop\dumber.exe\""

    Die fetten Backslashes musst du entweder selbst nochmal escapen, also \\ schreiben oder du ersetzt sie duch Forwardslashes, also so:
    \"C:/Dokumente und Einstellungen/Administrator.TEST/Desktop/dumber.exe\"

    Das musst du natürlich im ganzen String machen, und nur an den richtigen Stellen.

    Lg

    mator

    Edit: Iwie kann ich Backslashes nicht fett machen...

    Beitrag zuletzt geändert: 10.10.2012 16:30:09 von mator-kaleen
  4. Hallo adelwoehrer,

    das Korrekte escapen von Kommandozeilenargumenten unter Windows ist gar nicht so einfach. Das liegt daran, dass das Betriebssystem dieses Konzept eigentlich gar nicht kennt und von sich aus auch gar nicht unterstützt.
    Die Folge davon ist, dass die Interpretation bzw. Zerlegung der übergebenen Kommandozeile vollständig im Verantwortungsbereich der aufgerufenen Anwendung liegt.
    Falls die aufgerufene Anwendung diese Zerlegung mittels GetCommandLine() und CommandLineToArgvW() macht (was bei den meisten Anwendungen der Fall sein sollte), dann kann Dir evtl. folgender Code helfen:
    static bool escape_argument(StringBuilder cl, const char * argument)
    {
      if( String_Contains(argument, " ") ||
        String_Contains(argument, "\t") ||
        String_Contains(argument, "\n") ||
        String_Contains(argument, "\v") ||
        String_Contains(argument, "\"") ||
        String_GetLength(argument) < 1)
      {
            StringBuilder_Append(cl, "\"");
    
        while(true)
        {
          long count_bs = 0;
    
          while(*argument == '\\')
          {
            count_bs++;
            argument++;
          }
    
          if(!(*argument))
          {
            if(count_bs && !StringBuilder_AppendMultiple(cl, "\\", 2*count_bs))
            {
              fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendMultiple() failed.\n");
              return false;
            }
    
            break;
          }
          else if(*argument == '"')
          {
            if(!StringBuilder_AppendMultiple(cl, "\\", 2*count_bs+1))
            {
              fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendMultiple() failed.\n");
              return false;
            }
    
            if(!StringBuilder_AppendChar(cl, '"'))
            {
              fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendChar() failed.\n");
              return false;
            }
          }
          else
          {
            if(count_bs && !StringBuilder_AppendMultiple(cl, "\\", 2*count_bs))
            {
              fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendMultiple() failed.\n");
              return false;
            }
    
            if(!StringBuilder_AppendChar(cl, *argument))
            {
              fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendChar() failed.\n");
              return false;
            }
          }
    
          argument++;
        }
    
        if(!StringBuilder_AppendChar(cl, '"'))
        {
          fprintf(stderr, "Error: Process::escape_argument: StringBuilder_AppendChar() failed.\n");
          return false;
        }
      }
      else
      {
        if(!StringBuilder_Append(cl, argument))
        {
          fprintf(stderr, "Error: Process::escape_argument: StringBuilder_Append() failed.\n");
          return false;
        }
      }
    
      return true;
    }
    
    static bool build_command_line(Process pr)
    {
      long i;
      StringBuilder cl = pr->command_line;
    
      StringBuilder_Clear(cl);
    
      if(!escape_argument(cl, pr->exe_path))
      {
        fprintf(stderr, "Error: Process::build_command_line: escape_argument() failed.\n");
        return false;
      }
    
      for(i=0; i<pr->arguments->size; i++)
      {
        if(!StringBuilder_AppendChar(cl, ' '))
        {
          fprintf(stderr, "Error: Process::build_command_line: StringBuilder_AppendChar() failed.\n");
          return false;
        }
    
        if(!escape_argument(cl, pr->arguments->value[i]))
        {
          fprintf(stderr, "Error: Process::build_command_line: escape_argument() failed.\n");
          return false;
        }
      }
    
      return true;
    }
    Das ist jetzt zwar C Code aber der sollte sich ziemlich einfach nach C# übersetzen lassen. Der StringBuilder kann einfach durch die C# StringBuilder-Klasse und die analogen Methoden ersetzt werden. Das 'const char *' kannst Du durch string ersetzen und anstelle von '*argument' musst Du dir noch einen Index anlegen und z.B. per Substring das Zeichen extrahieren.

    Beitrag zuletzt geändert: 11.10.2012 20:21:46 von darkpandemic
  5. burgi

    Co-Admin Kostenloser Webspace von burgi

    burgi hat kostenlosen Webspace.

    Ich hab mal etwas gegoogelt, und einige meiner Meinung nach brauchbare Seiten dazu gefunden, wo selbiges Problem aufgegriffen wird. Da ich mich mit C# noch nicht befasst habe, kann ich auch nicht beurteilen, ob diese Quelltexte auch funktionieren:
    http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/a4ed39e3-702e-46cd-bdb1-8f10e529c516/
    ganz unten:
    To avoid this behavior, you may access the raw command line value through the System.Environment.CommandLine property.

    Thanks,
    Josh Free
    Base Class Library Development


    Hier Links zu Seiten von Menschen, die glauben, die Kommandozeilenargumente korrekt escapen zu können:
    Link 1
    Link 2
  6. Autor dieses Themas

    adelwoehrer

    Kostenloser Webspace von adelwoehrer

    adelwoehrer hat kostenlosen Webspace.

    Die fetten Backslashes musst du entweder selbst nochmal escapen, also \\ schreiben oder du ersetzt sie duch Forwardslashes

    Die sind bereits escaped, ich hab sie im Zitat nur vergessen. =)

    Danke für die Links und Hilfestellungen, ich hab noch etwas herumprobiert und bin dann dahintergekommen, wie es klappt....auch wenn ich nicht weiß, wieso es so klappt.
    Vielleicht fällt euch dazu was ein.

    Also die Syntax ist ja wie schon gesagt: Pfad zum Program --market Pfad zur Cache-Datei > Pfad zur Ausgabedatei
    Wenn ich nun alle Pfade escape, funktioniert es nicht.
    Wenn ich keinen der Pfade escape, funktioniert das auch nicht.
    Was ich tun muss, ist, den Pfad zum Programm nicht zu escapen (auch wenn Leerzeichen drinnen sind) und die anderen beiden Pfade zu escapen.

    Also: Pfad zum Program --market \"Pfad zur Cache-Datei\" > \"Pfad zur Ausgabedatei\"

    Ich kann mir das nur so zusammenreimen, dass die Windows-Konsole den Programm-Pfad nur unescaped aufrufen kann (keinen Schimmer wieso) und die beiden anderen Pfade dann im Endeffekt an das eignetliche Programm übergeben werden, dass dann aber wiederrum escapte Pfade braucht.
    Alles ein bisschen aufwendig, funktioniert so aber.

    Danke mal für die Hilfe. =)
  7. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!