punkish has asked for the wisdom of the Perl Monks concerning the following question:

O Perl-on-Windows-mavens,

In my continuing quest for implementing a perl program on a windows box, I did the following --

wrote a perl script that works correctly. Let's call it foo.pl

converted foo.pl into a executable, foo.exe using pp. foo.exe also works correctly. It is actually magical to take foo.exe, stick it on a computer without perl on it, and see it work just fine.

wrote a variation of foo.pl using Win32::Daemon (lets call this bar.pl), and used sc to install it as a service, start, and stop it. Works correctly.

Now, I would like to convert bar.pl into bar.exe using pp and then install bar.exe as a service. Uh oh. Doesn't work. Here is the error (everything else being the same) --

Can't locate loadable object for module Win32::Daemon in @INC (@INC co +ntains: CO DE(0xcba6f8) CODE(0xdaa078) .) at ../blib/lib/PAR/Heavy.pm line 101 Compilation failed in require at script/bar.pl line 11. BEGIN failed--compilation aborted at script/bar.pl line 11.

Making an exe is really cool because then I don't need to install Perl on the target computer. However, I still need to open up a cmd window and run the darn thing.

Making a service is really cooly because then I don't have to worry about opening a cmd window to run it, however, if I can't make a service out of the exe then I will have to install Perl on the target computer.

Guidance will be much appreciated on this penultimate day of the year.

Replies are listed 'Best First'.
Re: Perl script to EXE to Windows Service
by Jenda (Abbot) on Dec 31, 2004 at 00:55 UTC

    Is the foo.pl using some modules with XS parts? Are you sure you call pp with the right parameters? I'm using PerlApp myself and never had any problems with Win32::Daemon myself. And I do have quite a few services using that module compiled to EXEs. Anyway try to force pp to include the ...\perl\site\lib\auto\Win32\Daemon\Daemon.dll

    P.S.: You might want to consider Win32::Daemon::Simple. Not that it'd help you with this problem, it's a wrapper above Win32::Daemon, but it hides some complexities.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

      Anyway try to force pp to include the ...\perl\site\lib\auto\Win32\Daemon\Daemon.dll

      That was it. It works now. Is this something I should not have had to do under "normal" circumstances? Is there something that I should look for to determine whether or not to explicitly linking in the daemon.dll?

      In any case, what a great piece of advice. I am off to drink some eggnog now. I will lift a chalice to you as thanks for your invaluable help.

      Update: A thought occurred to me. My script is writing out a log. I have hard-coded the path to the log in my script before converting it to the exe which I then converted to the service. This path is likely going to be different in the target computer(s). How do I externalize this path to the log file so I can still create the exe and install it as a service on a target computer, yet change the log file path (and, perhaps, other config vars as well) at will... you know, stop the service, change a few config params, restart the service, a la Apache.exe does on Windows?

        No you should not have to tell PAR to include the DLL, it should do that automaticaly.

        I can only repeat the Win32::Daemon::Simple suggestion. It'll allow you to add the ability to install/uninstall/start/stop the service by the executable itself, set parameters that will be stored in the registry, be changed by the executable and presented to the script as constants.

        Jenda
        We'd like to help you learn to help yourself
        Look around you, all you see are sympathetic eyes
        Stroll around the grounds until you feel at home
           -- P. Simon in Mrs. Robinson

        use
        a) the registry
        b) a .ini-file located in the directory where the .exe is. you can get the path to the .exe by calling PerlSvc::exe()
Re: Perl script to EXE to Windows Service
by holli (Abbot) on Dec 30, 2004 at 21:27 UTC
    you have to supply every .dll (loadable object) that a module uses (put it into the same path the .exe resides, i think).
      I thought that was the idea behind pp. That it took all the requirements of the script and wrapped them up along with a perl interpreter into a .exe.
        all the perl-code. c-parts (dlls in windows) are different (because the are already compiled).
        you will have to supply them. (as you would have to if you deploy you program in perl-sourcecode)
Re: Perl script to EXE to Windows Service
by erix (Prior) on Dec 30, 2004 at 23:34 UTC

    It looks like you should use pp's --link option. This lets you specify .dll files.

        -l, --link=*FILE*|*LIBRARY*
            Add the given shared library (a.k.a. shared object or DLL) into the
            packed file. Also accepts names under library paths; i.e. "-l
            ncurses" means the same thing as "-l libncurses.so" or "-l
            /usr/local/lib/libncurses.so" in most Unixes. May be specified
            multiple times.
    
    
      thanks. Now, of course, I have to somehow figure out exactly _what_ files are not getting loaded. Unfortunately the error is a bit too terse. I look through Win32::Daemon docs to see if I can figure this out. In the meantime, if anyone else has converted a script with Win32::Daemon into an exe, and then that exe into a service, I would love to hear from you.