1
votes

Good evening!

I'm currently in the first stages of development with a new application in Firemonkey. It's my first run in with Firemonkey, but i've got a few years experience with Delphi.

So far, i've got an external application that extracts an icon from an exe and then saves it to a file as a BMP. I've coded in the ability to pass a parameter to this application (which provides a string value to tell it where the .exe to extract from is). It was built in VCL as i want to use the firemonkey framework mostly for the 3D features, but also allow me expansion onto Mac at a future date if i so wish. The external application is working correctly, so the code there doesn't need tweaking.

The issue i'm having is passing the parameter from my firemonkey application. I'm using a customised "fOpen" unit which allows passing of parameters;

unit fOpen;

interface

uses
{$IFDEF MSWINDOWS}
Winapi.ShellAPI, Winapi.Windows;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
  Posix.Stdlib;
{$ENDIF POSIX}

type
  TMisc = class
class procedure Open(sCommand, Params: string);
end;
implementation

class procedure TMisc.Open(sCommand, Params: string);
begin
{$IFDEF MSWINDOWS}
  ShellExecute(0, 'OPEN', PChar(sCommand), PChar(Params), '', SW_SHOWNORMAL);
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
  _system(PAnsiChar('open ' + AnsiString(sCommand)));
{$ENDIF POSIX}
end;
end.

As you can see, i've added the "Params" variable to the MSWINDOWS isdef.

On my firemonkey form, there's 2 buttons. 1 of them executes a TOpenDialog and outputs the selected filename into a TEdit. The other button executes the external application (the one that extracts the icon) and then loads the bitmap image that was saved into a TImageControl.

Here's the code i'm trying to use;

fOpen.TMisc.Open('HypExIcon.exe', '"' + edit1.Text +'"');

The issue is that the first line, which should execute the file with the parameter, doesn't actually work as intended. It doesn't even execute the file at all (i.e. there's no indication of the application launching as there should be). However, if i change it to this...

fOpen.TMisc.Open('HypExIcon.exe', 'C:\Windows\Notepad.exe');

...it functions as would be expected, executing the external application and creating the icon included in the parameter field. I've tried using PChar('"' + Edit1.text + '"'), as well as a similar PWideChar function, but neither of them remedy the issue.

I'm confident it's something extremely simple that i'm missing here. I'm so used to using PChar or PWideChar for these sorts of things in VCL, that it's thrown me off.

Any ideas?

1
Firemonkey would appear to be not relevant here since you are running on Windows and calling ShellExecute. Right? Are you putting the fully qualified path into Edit1.Text? The only thing that makes sense to me is that you don't have the full path to the file in Edit1.Text. I bet it works if you type C:\Windows\Notepad.exe into the edit control.David Heffernan
@DavidHeffernan That's strange. Now that i type it in and bypass the "browse" button and TOpenDialog, it works fine.Scott P
When you browse using a file dialog, the working directory gets changed (unless you disable that feature). I think. Perhaps that's what is happening. Is your extractor program sensitive to the current directory? You could pass ExtractFilePath(Application.ExeName) in the working directory parameter of the call to ShellExecute. That will force the working directory of the new process to be what it would be if you had not used the file dialog. I think. Anyway, the answer is in there somewhere!!David Heffernan
Ah, that's exactly what it was! Since i'm calling the external app as a relative path, changing the working directory was causing it to try and execute something that wasn't there. Changing ofNoChangeDir to true fixed the issue. Many thanks David!Scott P

1 Answers

2
votes

As we worked out in the comments, the problem is that the file dialog is changing the working directory behind your back. You can, and should, set the ofNoChangeDir option.

However, I recommend that you do not rely on relative paths when starting processes. When starting processes you really ought to maintain tight control over the location of the process. I would do it like this:

AppPath := ExtractFilePath(Application.ExeName);
fOpen.TMisc.Open(AppPath+'HypExIcon.exe', ...