Unify standard and Windows version

Started by obetz, June 21, 2019, 11:28:07 AM

Previous topic - Next topic

obetz

Hi Phil,

did you ever consider to consolidate the standard version and the Windows version of ExifTool in one file?

The differences are small:

1. The link following code. I didn't try whether this hurts with Windows, but it could simply be skipped if Windows is detected.

2. The "filename embedded arguments" likely won't hurt in the standard version. BTW: Using my Perl launcher, the parameters need to be extracted from $^X instead of $0.

3. The help. Instead of modifying the whole exiftool script and extracting parts of it at runtime to a text file in %temp%, you could create such a help text file offline and bundle it with the ExifTool distribution. Then it would be easy to select the output method at runtime (perldoc or "more").

Oliver

Phil Harvey

Hi Oliver,

This is a good idea.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

searching $^X instead of (or in addition to) $0 for "parameters in brackets" would save me from patching ExifTool when I prepare the installer.

I can't decide about the cleaner method:

  • Simply search both $^X and $0 for parameters in brackets. Seems to be foolproof.
  • Check the environment and decide whether to use $^X or $0.

In the mean, I also tried this: The "link following" check if (-l $0) {... doesn't need to be removed in the Windows version, since a "-l" test is always false in current Windows Perl and even my $lnk = eval { readlink $ARGV[0] }; wouldn't harm.

Oliver

obetz

Quote from: Phil Harvey on June 21, 2019, 11:36:33 AM
This is a good idea.

May I bump this topic?

At least points 1. "link following code" and 2. "filename arguments" seem to be pretty easy - see my posting dated 2019-07-05.

Maybe you also want to add (parts of) the "even more verbose" -ver output described in https://exiftool.org/forum/index.php/topic,10223.msg53445.html

Oliver

herb

Hello Phil, hello Oliver,

@Oliver: I tried to follow all your investigations to replace the Windows version of Exiftool.exe with your Ppl.exe=Exiftool.exe.
As far as I see this could be a good solution, but I have the following question:

(Windows)Exiftool.exe is also used by other applications (e.g. XnViewMP or IMatch) and the *.exe file is stored in a subdirectory of the application installation directory.
For me an advantage is that all these Exiftool.exe files use the "unpacked Perl modules" in ONE common directory - in %appdata%\... or defined by global environment variable PAR_GLOBAL_TEMP.

At the moment I do not see how this can be achieved using your Ppl(exiftool).exe.
All necessary files stored in directory "exiftool_files" should be stored only once on a Windows system.

Best regards
Herb

obetz

Herb, since this thread is about the merge of the exiftool and windows_exiftool scripts, I answer your posting in https://exiftool.org/forum/index.php/topic,10128.msg54593.html#msg54593

Phil Harvey

Hi Oliver,

Sorry for being so slow on this.  I'm looking into the $0/$^X business now...

I don't really like the idea of patching windows_exiftool to check both $0 and $^X for arguments in brackets, but I suppose it would be OK to do this.  However, I don't want to patch ExifTool.pm to check both directories for the config file since this would conflict with the documented behaviour.

If I could somehow check the environment to determine with certainty that your exe version is running, then I could patch both files to add an "if" statement and use $^X in this case.  Do you have any ideas about how this could be done?  Would it be possible for your launcher to set a special environment variable that ExifTool could check?

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Quote from: Phil Harvey on March 04, 2020, 08:52:49 AM
I don't really like the idea of patching windows_exiftool to check both $0 and $^X for arguments in brackets, but I suppose it would be OK to do this. 

However, I don't want to patch ExifTool.pm to check both directories for the config file since this would conflict with the documented behaviour.
I agree.

Quote from: Phil Harvey on March 04, 2020, 08:52:49 AM
If I could somehow check the environment to determine with certainty that your exe version is running, then I could patch both files to add an "if" statement and use $^X in this case.  Do you have any ideas about how this could be done?  Would it be possible for your launcher to set a special environment variable that ExifTool could check?

I could set an environment variable or a command line parameter but maybe that's not even necessary.

We need to distinguish three (Windows-) environments:

1. PAR packed
$0  : Z:\path_to_exiftool\exiftool-could-be-renamed.exe
$^X: perl.exe (par lies to us, there is no perl.exe)

There are many par specific environment variables, for example PAR_INITIALIZED, PAR_PROGNAME, PAR_SPAWNED so this case is easy to detect.
And par sets some strange, non-existing include directories like "CODE(0x3400d74)"

2. Script called by standard perl.exe
$0  : Z:\path_to_exiftool\exiftool-could-be-renamed.pl
$^X: Y:\path_to_perl\perl5.xx.y.exe

3. Perl launcher
$0  : Z:\path_to_exiftool\exiftool_files\exiftool.pl
$^X: Z:\full_path\ExifTool-could-be-renamed.exe

Currently, "exiftool_files\exiftool.pl" is hard coded in my launcher. Of course, we can change the directory name as well as the script name (think about exiftool4ppl.pl or blkqximukzcdzxnr0fhh.pl)

But even with a unique script name, checking only $0 wouldn't be 100% safe because people could run the script with perl.exe. I ship the original perl.exe in the archive and installer to make this possible.

But checking $^X in combination with $0 should be safe enough: If the directory part from $^X concatenated with the hard coded part of the script path matches $0, we can be rather sure that the launcher is used.

Phil Harvey

This sounds reasonable.  Are the directory delimiters of $0 and $^X always "\"?  Also, what happens if the directory name contains Unicode characters?  And is this impervious to changes in case (ie. file names in upper case but invoked using lower case)?

If all this is OK, the how about something like changing this in ExifTool.pm:

    -r $file or $config =~ /^\// or $file = ($0 =~ /(.*[\\\/])/ ? $1 : './') . $config;

to this

    my $dir = $0;
    if ($^O eq 'MSWin32') {
        my $test = $^X;
        $dir = $^X if $test =~ s/\\[^\\]*$/\\exiftool_files\\exiftool.pl/ and $0 eq $test;
    }
    -r $file or $config =~ /^\// or $file = ($dir =~ /(.*[\\\/])/ ? $1 : './') . $config;


And similarly in the exiftool script.

(This isn't the most heart-warming solution because it couldn't be used by other packages)

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Quote from: Phil Harvey on March 04, 2020, 12:53:02 PM
[...]
(This isn't the most heart-warming solution because it couldn't be used by other packages)
I agree.

Probably the cleanest method is to add a command line argument.

What do you think about "-xpath" or more cryptic as very first parameter (even before -config!) to indicate that $^X shall be used instead of $0?

How shall we forward this information to ExifTool.pm?

Oliver

obetz

Find a modified launcher attached: It inserts "-xpath" as first parameter. Use it instead of "exiftool.exe" from my package.

I hacked exiftool to make use of it, but I'm no Perl monk - you likely find a cleaner solution:

exiftool near line 17:

my $exePath;
BEGIN {
    if (@ARGV and $ARGV[0] eq '-xpath') {
        shift;
        $exePath = $^X;
    }
    else{
        $exePath = $0;
    }
    $Image::ExifTool::exePath = $exePath;

    # get exe directory
    $exeDir = ($exePath =~ /(.*)[\\\/]/) ? $1 : '.';


exiftool near line 345

# add arguments embedded in filename (Windows .exe version only)
if ($exePath =~ /\(([^\\\/]+)\)(.exe|.pl)?$/i) {


and in exiftool.pm around line

    $Image::ExifTool::exePath = $0 if (not defined $Image::ExifTool::exePath);
    -r $file or $config =~ /^\// or $file = ($Image::ExifTool::exePath =~ /(.*[\\\/])/ ? $1 : './') . $config;


This way, $^X is only used if ExifTool is invoked by my Perl launcher.

Oliver

Phil Harvey

I like this idea better.  I'll implement this in ExifTool 11.91.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

o.k., change the parameter name if you like.

Phil Harvey

-xpath is good.  I'll add this as an undocumented feature for now.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

I wasn't able to verify it, but as far as I see, exiftool_windows line 338 needs to use exePath instead of $0

I'll try to check this tomorrow.

BTW: Is it really intended that "$exeDir/lib" is added to the lib search path in the par version? I can't imagine that a Windows user adds a lib dir beneath exiftool.exe and puts some Perl libraries there to be used by ExifTool.

Oliver

Phil Harvey

Ooops.  You're right.  I missed that one. 

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

no problem, I can fix this myself, and test everything with my changed loader (next week, I'm loaded with work this weekend).

BTW: Do you want me to incorporate a nicer icon in the loader exe? The current "PPL" icon is more a general one.

Oliver

Phil Harvey

Hi Oliver,

Using a nicer icon would be good, but I don't have anything that I can provide.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

what about the one from Sourceforge:

I don't really know anything about it. Maybe a multi-resolution version is "state of the art".

Oliver

Phil Harvey

I wasn't thinking that would make a suitable application icon, but go ahead if you want.

I have made a number of the "PH" icons for the web site, and could make "ET" icons like this in any size you want:

android-chrome-192x192.png      

apple-touch-icon-167x167-precomposed.png

apple-touch-icon-precomposed.png

android-chrome-512x512.png      

apple-touch-icon-167x167.png      

apple-touch-icon.png

apple-touch-icon-114x114-precomposed.png

apple-touch-icon-180x180-precomposed.png

favicon-32x32.png

apple-touch-icon-114x114.png      

apple-touch-icon-180x180.png      

favicon-48x48.png

apple-touch-icon-120x120-precomposed.png

apple-touch-icon-57x57-precomposed.png

favicon.ico

apple-touch-icon-120x120.png      

apple-touch-icon-57x57.png      

favicon.png

apple-touch-icon-144x144-precomposed.png

apple-touch-icon-72x72-precomposed.png

mstile-150x150.png

apple-touch-icon-144x144.png      

apple-touch-icon-72x72.png      

apple-touch-icon-152x152-precomposed.png

apple-touch-icon-76x76-precomposed.png

apple-touch-icon-152x152.png      

apple-touch-icon-76x76.png


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Like my "PPL" icon, these seem to be black on transparent => hard to view on dark background. As I said, I'm rather clueless in this respect.

Windows seems to use 16, 32, 48 and 256px wide icons for applications.
https://stackoverflow.com/questions/3236115/which-icon-sizes-should-my-windows-applications-icon-include
https://docs.microsoft.com/en-us/windows/win32/uxguide/vis-icons

Some people do a lot of work with the icons. I don't even have the skill to design well.

It was just an idea...

Phil Harvey

OK, how about this for an icon?:



- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

nice!

Scaling down to 16x16 doesn't work very well, so this version might need some fine tuning.

Phil Harvey

Here's a 16x16 version



- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Hi Phil,

two patches were needed to make it work:

1. The already mentioned one near line line 338:
if ($Image::ExifTool::exePath =~ /\(([^\\\/]+)\)(.exe|.pl)?$/i) {

2. Line 24 to use $0 again (instead of $exeDir) to add /lib to @INC:
unshift @INC, ($0 =~ /(.*)[\\\/]/) ? "$1/lib" : './lib';


With these patches, I positively tested 11.91:

1. Embed arguments in the exe filename

  • $^X is used with my launcher
  • In the "plain perl" environment, parameters are extracted from the Perl script name. I don't know whether this is intended, but I think it doesn't hurt.

2. lib search path
Line 24 uses always $0 to add /lib to @INC.

Although adding this directory is not needed in my environment (because the Perl libs and ExifTool libs are already combined in one tree), it doesn't hurt. It just adds a redundant entry with different path delimiters as you can see with -ver -v2.

3. argfile search path
Uses $^X when called by my launcher, else $0, as intended.

4. config file search path (ExifTool.pm)
Uses $^X when called by my launcher, else $0, as intended.

I also embedded the new icons in my launcher:

https://oliverbetz.de/cms/files/Artikel/ExifTool-for-Windows/exiftool-11.91.zip

Oliver

Phil Harvey

Hi Oliver,

OK, great.  Thanks.

I'll make these changes for the next version.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

For 11.92, I didn't get a notification from Sourceforge, so my update is slightly delayed:

exiftool_windows 11.92 can now be used unmodified with my launcher, thanks for your changes!

I'm patching it nevertheless to add some diag output with exiftool -ver -v9

In addition, I added IO::String to the libs to enable processing of piped and zipped files like docx.

Should IO::String be listed by "-ver -v"?

Oliver

Phil Harvey

It's been more than a year since this change, but someone finally discovered that the -xpath patch broke the behaviour if exiftool is linked from another location.  The problem was that this line in exiftool which added the lib directory to the include path

    unshift @INC, "$exeDir/lib";

was changed to

    unshift @INC, ($0 =~ /(.*)[\\\/]/) ? "$1/lib" : './lib';

I'm assuming that your installation needs the include directory to be relative to $0, while the config file should be relative to $^X.

Unfortunately both files should be relative to the link target if the app is run via a link on Mac/Linux.  I don't know about running via a link in Windows, but I patch 12.35 to fix this for Mac/Linux.  Keep an eye out for this release and check to be sure it performs properly for you.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Hi Phil,

Quote from: Phil Harvey on November 03, 2021, 09:00:44 AM
I'm assuming that your installation needs the include directory to be relative to $0, while the config file should be relative to $^X.

we need to observe that the PAR environment differs in this respect.

Quote from: Phil Harvey on November 03, 2021, 09:00:44 AM
Unfortunately both files should be relative to the link target if the app is run via a link on Mac/Linux.  I don't know about running via a link in Windows, but I patch 12.35 to fix this for Mac/Linux.  Keep an eye out for this release and check to be sure it performs properly for you.

I'll do so but it will take a while since I have other urgent work.

Windows supports Symlinks, but almost nobody uses them not least because creating them requires elevated permissions (or "developer mode"). Most people use the gui links or the  search path.

So there are really a lot of permutations, and one question is how thoroughly we need to test them.

And I'm not completely sure which directories should be searched for which files.

Phil Harvey

It is only the application directory that is the problem here.  The other search directories shouldn't be affected.  The standard exiftool version should look in the directory of the application (link target) for both the libraries and the config file.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

obetz

Quote from: Phil Harvey on November 12, 2021, 08:20:13 AM
It is only the application directory that is the problem here.  The other search directories shouldn't be affected.  The standard exiftool version should look in the directory of the application (link target) for both the libraries and the config file.

My 12.36 package finds .ExifTool_config and argfiles in the application directory (beneath ExifTool.exe) and in the home directory, and not in the current directory. Tested with ExifTool in the path, with "GUI links" and even symlinks (although I doubt they are used by anobody). My extended tests also showed no abnormalities.

I just had to adjust the last two lines of my extension of the -ver option:


            if ($verbose > 8) {
                print "Current dir:    " . Cwd::getcwd() . "\n" if (eval { require Cwd });
                print "Script name \$0: $0\n";
                print "Exe name \$^X:   $^X\n";
                print "exeDir:         $Image::ExifTool::exeDir\n";
                print "exePath:        $exePath\n";
            }


Oliver

Phil Harvey

Hi Oliver,

Great, thanks for checking this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).