ParamCount() und ParamStr() bei 64 bit



  • Hallo,
    wenn ich ParamCount() und ParamStr() auf 32 bit Plattform verwende ist alles ok. Wenn ich das gleiche Projekt unter 64 bit erzeuge, dann fehlt der erste Switch, z.B bei -M 5 -C 11 -S 1 kommt 5 -C 11 -S 1. Im Internet habe ich dazu folgendes gefunden: "ParamStr (64bit) looses first backslash with UNC path". Das soll aber mit 11.1 gelöst sein, bei mir unter 11.3 bleibt der erste switch aber immer noch weg. Gibt es einen workaround ?



  • Der Fehler bezieht sich auf UNC-Pfade mit dem umgekehrten Schrägstrich \, nicht auf Parameter mit Bindestrich -.
    Du könntest mal direkt die (intern auch von ParamStr verwendete) WinAPI-Funktion CommandLineToArgvW mit CmdLine als Parameter aufrufen.

    Evtl. zeige mal den kompletten CmdLine-String.



  • //---------------------------------------------------------------------------

    #include <vcl.h>
    #pragma hdrstop

    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent
    Owner)
    : TForm(Owner)
    {
    // Unter Projekt Optionen Debugger Parameter: -M 5 -C 11 -S 1
    // Bei 32 bit ok, bei 64 bit fehlt der erste switch
    //
    Label1->Caption = IntToStr( ParamCount() );

    Label2->Caption = "";
    for ( int i = 1; i <= ParamCount(); i++ )
    {
    Label2->Caption += (ParamStr(i) + " ");
    }
    }
    //---------------------------------------------------------------------------```cpp

    @Th69 Es hat nicht nur ParamStr() ein Problem, ParamCount() bringt in dem Beispiel auch nur die 5 und nicht 6


  • @Ronco

    for ( int i = 1; i <= ParamCount(); i++ )
    {
       Label2->Caption += (ParamStr(i) + " ");
    }
    

    Der Index passt nicht, der sollte von 0 bis ParamCount -1 laufen.



  • @DocShoe: Der Code ist schon richtig so, s. ParamStr - in ParamStr(0) steht der (Pfad +) Name der Anwendung.



  • @Th69 sagte in ParamCount() und ParamStr() bei 64 bit:

    @DocShoe: Der Code ist schon richtig so, s. ParamStr - in ParamStr(0) steht der (Pfad +) Name der Anwendung.

    😨
    Delphi ist konsequent inkonsequent. Dass die Zeichen in einem String ab Index 1 anfangen wusste ich, aber dass das auch für manche Funktionen gilt ist gruselig.



  • Das ist bei C und C++ doch auch nicht anders - in argv[0] steht der Anwendungsname und ab Index 1 die übergebenen Parameter (einzig argc gibt die Gesamtanzahl des Arrays an, nicht wie ParamCount nur die Anzahl der Parameter).

    @Ronco: Hast du jetzt mal mit CommandLineToArgvW getestet?



  • @Th69 Vielen Dank für den Tipp, habe es jetzt so gelöst:

    	String sParams = "";
    	int Param;
    	int iError = 0;
    
    	LPWSTR *szArgList;
    	int argCount;
    	szArgList = CommandLineToArgvW( GetCommandLineW(), &argCount );
    
    
    	if ( argCount == 0 || ( argCount % 2 ) != 0 )
    	  {
    	   iError |= 0x01;
    	  }
    
    	for ( int i = 0; i < argCount && iError == 0; i += 2 )
    	   {
    		LPWSTR s1 = szArgList[i];
    		LPWSTR s2 = szArgList[i+1];
    		String S1 = s1;
    		String S2 = s2;
    		sParams += (S1 + " " + S2 + " ");
    	   }
    
     Label1->Caption = IntToStr( argCount );
     Label2->Caption = sParams;
    

    Das funktioniert in 32 und 64 bit Version. Ich denke du hast da auch nichts auszusetzen, oder ? Das mit LPWSTR nach String gefällt mir noch nicht ...



  • Für das Zusammensetzen des sParam-Strings könntest du Format benutzen:

    sParams += Format("%s %s ", szArgList[i], szArgList[i+1]);
    

    (so brauchst du keine temporären Strings erzeugen)

    PS: Falls du nicht den Clang-Compiler, sondern den klassischen benutzt, dann mußt du stattdessen ARRAYOFCONST((...)) als Parameter verwenden.
    PPS: Packe den Nicht-UI-Code am besten in eine eigene Funktion.



  • @Th69 Nochmals danke, ich hab jetzt den code angepasst für die Verwendung über eine Verknüpfung. Die Version oben ist zum Test über Projekt Optionen.

    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    
    const int _Debug = true;
    
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    	String sParams = "";
    	int iParam;
    	int iError = 0;
    
    	LPWSTR *szArgList;
    	int argCount;
    	szArgList = CommandLineToArgvW( GetCommandLineW(), &argCount );
    
    	int z;
    	if ( _Debug )
    	   z = 0;   // IDE time
    	else
    	   z = 1;   // runtime
    
    	if ( argCount == 0 || ( (argCount-z) % 2 ) != 0 )
    	  {
    	   iError |= 0x01;
    	  }
    
    	for ( int i = z; i < argCount && iError == 0; i += 2 )
    	   {
    		LPWSTR s1 = szArgList[i];
    		LPWSTR s2 = szArgList[i+1];
    		sParams += Format( L"%s %s ", String( szArgList[i] ), String( szArgList[i+1] ) );
    
    		if ( LowerCase( s1 ) == "-m" )
    		  {
    		   if ( TryStrToInt( s2, iParam ) )
    		     {
                          // ...
    		     }
    		  }
    	   }
    
     Label1->Caption = IntToStr( argCount );
     Label2->Caption = sParams;
    

Anmelden zum Antworten