1

I'm trying to get the arguments declared in ProjectName.cpp file (the file of the application) wich contains the following autogenerated code:

extern "C" int FMXmain()
{
    try
    {
        Application->Initialize();
        Application->CreateForm(__classid(TfrmPrincipal), &frmPrincipal);
        Application->CreateForm(__classid(TfrmCarregar), &frmCarregar);
        Application->CreateForm(__classid(TfrmCodigo), &frmCodigo);
        Application->CreateForm(__classid(TfrmConfig), &frmConfig);
        Application->CreateForm(__classid(TfrmImgConf), &frmImgConf);
        Application->CreateForm(__classid(TfrmSobre), &frmSobre);
        Application->CreateForm(__classid(TfrmTradutor), &frmTradutor);
        Application->Run();
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}

I just would like to get the arguments when the application is launched, so i've tried to change the declaration of the function to:

extern "C" int FMXmain(String argv)

and

extern "C" int FMXmain(wchar_t* argv[]) // as I may need wide char support (TCHAR doesn't seems to be useful in this case)

or (the default)

extern "C" int FMXmain(char* argv[])

The only doubt I have is how to pass the value I get to the main form. Should I pass it after creation or after the application is already running? How do I do it?

OBS: Main form: frmPrincipal

If I'm making something wrong, please tell me. PS.: I'm just trying to get the file path after double click on it (I've already gotten the function wich will link my application to the registry)

References that helped me a little bit:

WIKI Double Click on Your File(extension) & open it with your EXE(application) Opening c++ program by double clicking associated file. How do I get the file name?

Since now, Thank you A LOT.

Community
  • 1
  • 1
mauroaraujo
  • 332
  • 1
  • 10
  • 23
  • 2
    See the documentation for `ParamStr`, found in the System unit. It allows you to access the command line values from anywhere after launch. You don't have to modify `FMXMain`. – Ken White Dec 15 '15 at 01:24
  • 1
    On Windows, the command line is stored in the PEB, and is accessible from anywhere throughout the process by calling [GetCommandLine](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156.aspx) (or [CommandLineToArgvW](https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391.aspx) if you need an *argv* style array of strings). In case you are looking for the location where the executable image resides, call [GetModuleFileName](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197.aspx) instead, and strip the file name off the end. – IInspectable Dec 15 '15 at 01:44
  • 1
    @IInspectable: This is C++ Builder, which shares the Delphi RTL. It's much easier than going directly to the WinAPI to just use the wrappers that are already provided, which already parse out the command line parameters, provide a count, and where `ParamStr(0)` already contains the fully qualified pathname to the executable. – Ken White Dec 15 '15 at 02:23
  • @KenWhite: Depending on the specific needs, using the wrappers might be easier (although you do get the parsed command line calling `CommandLineToArgvW` just as easily). Your assessment, that `ParamStr(0)` would always contain the fully qualified pathname is not necessarily true. While conventional to pass the executable image as the first argument, there is no requirement to do so. [CreateProcess](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425.aspx) allows you to pass an arbitrary command line to the process. `GetModuleFileName` is the safe alternative. – IInspectable Dec 15 '15 at 09:37
  • 1
    @IInspectable: Delphi's RTL documents the behavior of `ParamStr(0)`, so my assertion that it will also do so is quite accurate. :-) – Ken White Dec 15 '15 at 13:26
  • @KenWhite: Why don't you just try for yourself? Launch your test application (using [CreateProcess](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425.aspx), without replicating the executable pathname as the first argument to *lpCommandLine*) that doesn't do anything but dump the contents of `ParamStr(0)`. When done you are free to file a documentation defect report. – IInspectable Dec 15 '15 at 13:40
  • @IInspectable: Look at the source code of `ParamStr()` in `System.pas` for yourself. On Windows, `ParamStr(0)` does not look at the command line at all, it retrieves the filename of the calling process using `GetModuleFileName()` and returns that instead (and always has). On other platforms, all indexes of `ParamStr()` simply return data from the global `System.ArgValues` array that gets initialized at process startup, where index 0 is always the calling process's filename. – Remy Lebeau Dec 15 '15 at 20:32

2 Answers2

2

You can use System::ParamCount() and System::ParamStr() to retrieve the command line arguments from anywhere (including FMXMain(), without modifying it). Here's an example using it from a form's OnShow event handler to populate a TMemo control, for instance:

void __fastcall TForm1::FormShow(TObject *Sender)
{
  Memo1->Lines->Clear();
  for(int i = 0; i < System::ParamCount(); ++i)
  {
    Memo1->Lines->Add(System::ParamStr(i));
  }
}

ParamStr(0) is always the fully-qualified executable name of the application itself.

You can test it by using the Run->Parameters menu item in the IDE. Add some values as parameters and run the application.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • I incorrectly rejected the proposed edit. The VCL TMemo has a `Clear` method that does not require `Lines->Clear`, but the FMX TMemo does not contain that method. I missed that it was FMX, and compiled my test code using the VCL control instead. My mistake. – Ken White Dec 19 '15 at 21:10
1

Embarcadero Firemonkey is a bit like Delphi: you can get command line parameters (argc/argv) from the special functions:

  • ParamCount()

  • ParamStr().

paulsm4
  • 114,292
  • 17
  • 138
  • 190