Hi Sisyphus,
And sorry for the delay as I did some experiments rather than doing a rushed
reply, hehe.
Firstly, I tried to track down the cause of the problem and repeatedly ran a
small test script for perl2exe adding in a module at a time and using one
function per module in the script. I had some typos with the semaphores but
other than that I got a working exe file using each and every loaded library
except Win32::ActAcc. OLE does work as I'm able to automate speech synths
and the AutoIt scripting environment. By the way executable size for this
script is about 1.2 MB.
So here's yet another minimal test script that should fail nicely when you
run it as an exe but works fine as a script file (dot plx):
use strict; # As usual.
use bytes;
use Win32::OLE; # Required by Win32::ActAcc.
use Win32::ActAcc;
Win32::OLE->Initialize();
Win32::ActAcc::clearEvents();
# Bang! LoadLibrary API call fails or app crashes.
# But only when running the exe . .plx works fine.
Here's how that failure looks:
C:\tinyapps\perl2exe>test2.exe
WinError=0000007e in LoadLibrary at PERL2EXE_STORAGE/Win32/ActAcc.pm line
150.
This exe file was created with the evaluation version of Perl2Exe. <snip>
To track down the problem further I tried a number of things:
After checking the error code and finding out that it was in fact a failing
LoadLibrary call (lib not found), my first thought was to copy the files in:
\site\lib\auto\Win32\ActAcc
To the same directory in which the exe itself resides. MSDN
<http://tinyurl.com/28fq2> says that LoadLibrary should look in the current
directory first. Even though copying the files did suppress the error
message, things got worse. The whole exe file crashed so obviously this was
not the right solution.
I also intuitively tried some other locations, hoping that they might help,
including placing the exe file in the perl directory directly, \perl\bin is
in the path after all, as well as mirroring the \site\lib\etc... hierarchy
under the current dir for the exe. Needless to say these measures were not
of any help.
Then it dawned on me that I might actually find out where it's trying to
look for the library using some spying tools. Having recently learned how to
do a die handler in comp.lang.perl.misc I wrote one but oddly enough the exe
managed to skip the handling completely or else I just mysteriously messed
up <smile>. I also gave one Win32 API monitor a try and did catch the load
library calls the exe made but couldn't get at the strings, only some memory
addresses, oh well.
Lastly, I took a quick glance at the Win32::ActAcc guts written in C but was
not able to find any explicit LoadLibrary cals in the code. Thus I gave up
that route pretty quickly.
So, how can I know where Win32::ActAcc is trying to look for the missing
DLLs when the script has been compiled to an executable with perl2exe?
I would first try Module::ScanDeps which is used by PAR
I tried both installed with ppm. Par wasn't as smart as perl2exe and even
complained that say scalar doesn't export looks_like_number even if I had
certainly said I want to use the name directly in the code. After having
added the fully qualified names e.g. Scalar::Util::looks_like_number PAR was
able to find the files and compiled an exe file. It was bigger than the
unoptimized output of the perl2exe program, however, and had the same basic
problem.
Scandeps seemed like a nice tool and it provided quite a lot of information
on the ActAcc.pm file. It listed a number of modules the file uses but I
don't reckon perl2exe failing to find these modules is the real problem
here. I did make sure that I had loaded in all the modules in the Win32
namespace required by the ActAcc module. Scandeps didn't show any DLLS as
being required even though virtually all WIn32 modules seem to have a
corresponding dll in:
\site\lib\auto\Win32\
odd.
As to versions and other configuration data:
Perl: 5.8.6.
perl2exe: 8.60
Win32::OLE: 0.1403 (looking in the PM file directly)
Win32::ActAcc: 1.0
perl2exe-Win32.ini:
Win32PERL5LIB
=.;$BASE/perl-Win32/lib;$BASE/perl-Win32/lib;$BASE/perl-Win32/site
/lib;$BASE/perl-Win32/site/lib
PERLVERSION=5.86
Here's the script that I used to verify that in fact all the other modules
apart from Win32::ActAcc did work in a compiled executable with no errors. I
actually had printed output for the generated results and verified that
things went as expected but stripped some of the prints as soon as it was
apparent that things really worked:
use strict;
use warnings FATAL => qw|all|;
use bytes;
use File::Spec;
use Hash::Util qw|lock_hash unlock_hash|;
use List::Util qw|first|;
use Scalar::Util qw|looks_like_number|;
use Win32;
use Win32::OLE;
use Win32::OLE::Const;
use Win32::API;
use Win32::Console;
use Win32::Semaphore;
use Win32::ActAcc;
# File::Spec
my($volume, $dir, $file) = File::Spec->splitpath($0);
# Hash::Util
lock_hash(%ENV);
# List::Util
first{/\d+/} qw|foo bar 5 jar|;
# Scalar::Util;
looks_like_number "55";
# Win32::semaphore
my $sem = Win32::Semaphore->new(1, 1, "foo");
my $stat = $sem->wait(300);
die "timed out.\n" if $stat == 0;
# Win32 core
Win32::Sleep 500;
# Win32::Console
my $con = new Win32::Console(STD_OUTPUT_HANDLE);
$con->Cls();
# WIn32::OLE and OLE::Const
Win32::OLE->Initialize();
my $const = Win32::OLE::Const->Load('Microsoft Speech Object Library');
my $voice = Win32::OLE->new('SAPI.SpVoice') or die "SAPI error.\n";
$voice->Speak("Hello there.", $const->{SVSFlagsDefault});
print "Async flag: $const->{SVSFlagsAsync}\n";
# Win32::API
Win32::API::Struct->typedef( POINT => qw
{
LONG x;
LONG y;
}); # point.
Win32::API->Import('user32', 'BOOL GetCursorPos(LPPOINT lpPoint)');
my $point = Win32::API::Struct->new('POINT');
GetCursorPos($point);
my($x, $y) = ($point->{x}, $point->{y});
# Win32::ActAcc
# Win32::ActAcc::clearEvents();
With kind regards Veli-Pekka Tätilä ([EMAIL PROTECTED])
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/
_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs