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

I have created a small pop-up window which shows all the files in a certain directory. Now I would like to link the files to certain programs based on the extension of the file. To be able to launch the program I need to know were the program has been installed. I do this by looking at the registry for the installation path. I have been succesfull by doing this for excel files. Ext .xls. I have not been able to get the correct path from the registery for Acrobat Reader. The reason is that the registery key is (Default) and it does not want to read it. Does anybody has a clue to correctly read the (Default) key for Adobe installation path. Below a small sample script. Change the path to any directory you would like to read. (Def. c:/public).

#!/perl/bin -w ################################################################### # # Purpose: Declaration of Modules to use in this script ################################################################### use Tk; use strict; use TK::FileSelect; use Tk::LabEntry; use Cwd; use FileHandle; use DirHandle; use Win32::Process; my $W; # GUI window $W = MainWindow->new; $W->title("Select Job"); $W->iconname('select job'); my $file_selected; # Read the directory contents - Put in a path were you have files plac +ed my @dirContents = readDir ("c:/public"); my $job_path = 'c:\\public\\'.$file_selected; print "$job_path\n"; my $TOP = $W->Toplevel; $TOP->title("data contents"); $TOP->geometry("+70+120"); $TOP->configure(-background => lc("aquamarine2")); my $tFrame = $TOP->Frame; my $bFrame = $TOP->Frame; $tFrame->configure(-background => lc("PaleTurquoise")); $bFrame->configure(-background => lc("PaleTurquoise")); # Create the label for editing the file my $lab = $tFrame->Label(-text => "Double click to edit file: ", -background => "PaleTurquoise", -anchor => 'e'); # Create a listbox with the contents of the directory. + my $ent = $tFrame->Scrolled(qw/Listbox -setgrid 1 -height 16 -width 40 + -scrollbars e -selectmode single/); for(@{dirContents}) { $ent->insert(0, "$_"); } $ent->bind('<Double-Button-1>', sub { $file_selected = $ent->get('active'); # In case of Excel files ############### if ($file_selected =~ m/\.xls/) { my $excel; print "$job_path\n"; use Win32API::Registry qw( :ALL ); my ( $key, $type, $excel_path ); #Microsoft Office 95 RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Office\\9.0\ +\excel\\InstallRoot", 0, KEY_READ, $key ); #"$software has registry key\n" : "$software seems to be missing ".r +egLastError()."\n"; if ($key == 0) #Microsoft Office 97 { RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Office\\8. +0\\excel\\InstallRoot", 0, KEY_READ, $key ); } RegQueryValueEx($key, "Path", [], $type, $excel_path, [] ); Win32::Process::Create($excel, $excel_path.'\excel.exe',"excel $job_pa +th",0,CREATE_NEW_CONSOLE,".")|| die ErrorReport(); } elsif ($file_selected =~ m/\.pdf/) { my $pdf; print "$job_path\n"; use Win32API::Registry qw( :ALL ); my ( $key, $type, $pdf_path ); RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Adobe\\Acrobat Reader\\ +5.0\\InstallPath", 0, KEY_READ, $key ); regLastError(); RegQueryValueEx( $key, "(Default)", [], $type, $pdf_path, [] ); print "$pdf_path\n\n\n\n"; Win32::Process::Create($pdf, $pdf_path.'\acrord32.exe',"acrord32 $job_ +path",0,CREATE_NEW_CONSOLE,".")|| die ErrorReport(); } else { my $Notepad; Win32::Process::Create($Notepad,'c:\\program files\\windows NT\\ac +cessories\\wordpad.exe',"wordpad $job_path",0,CREATE_NEW_CONSOLE,".") +|| die ErrorReport(); } }); # Quit the edit directory contents popup my $quitButton = $bFrame->Button(-text => "Quit", -width => 12, -background => "PaleTurquoise", -activebackground => "PaleTurquoise", -command => sub { $TOP->destroy; # strictly not necessary }); # Instead of pack, using grid to place more precisely. Tk::grid($tFrame, -row => 0, -column => 0, -sticky => 'w', -padx => 10, -pady => 10, ); Tk::grid($bFrame, -row => 1, -column => 0, -sticky => 's', -padx => 10, -pady => 10, ); Tk::grid($quitButton, -row => 0, -column => 0, -sticky => 'w', -padx => 10, -pady => 10, ); Tk::grid($lab, -row => 1, -column => 0, -sticky => 'w', -padx => 10, -pady => 10, ); Tk::grid($ent, -row => 1, -column => 1, -sticky => 'w', -padx => 10, -pady => 10, ); MainLoop; sub readDir { my ($DirName) = @_; opendir (INDIR,$DirName) or die "\nCannot open $DirName: $!\n"; my @DirContents = grep (!/^\.\.?$/ && -f "$DirName/$_" , readdir(INDIR +)); close (INDIR); return @DirContents; }

Replies are listed 'Best First'.
Re: How to look for application path
by BrowserUk (Patriarch) on Sep 30, 2002 at 10:24 UTC

    Try this. It will run the associated application (if it has one) for any file you selected from the list and load that file.

    It avoids having to do any registry lookups for install paths by simply starting cmd.exe passing the name of the file you wish to edit as a parameter.

    It relies on CMD's smarts to work out which application to run in the same way as when type just the name of a file on the command line and hit enter.This greatly simplifies the code for your application.

    I've tested it on .doc (WORD), .pdf (ACROBAT), .html (Opera on my system), .jpg (ACDSee), .zip (WinZip), .mpg (WinAmp) and they all worked with the code below. It should work for any file for which you have an association.

    In fact, with a minor change, it even works for .pl file starting perl and leaving the command shell window open even after the script completes, but I intend writing that up seperately.

    I've hacked your code around a lot getting this to work, so if you have any questions about what or why I did it, feek free to ask.

    # !perl -sw use Tk; use strict; use Win32::Process; local $|=0; my $W = MainWindow->new; $W->title("Select Job"); $W->iconname('select job'); my $file_selected; # Read the directory contents - Put in a path were you have files plac +ed # use a ARG of . to select from the current directory. my @dirContents = readDir ($ARGV[0]||"C:\\public"); my $TOP = $W->Toplevel; $TOP->title("data contents"); $TOP->geometry("+70+120"); $TOP->configure(-background => lc("aquamarine2")); my $tFrame = $TOP->Frame; my $bFrame = $TOP->Frame; $tFrame->configure(-background => lc("PaleTurquoise")); $bFrame->configure(-background => lc("PaleTurquoise")); # Create the label for editing the file my $lab = $tFrame->Label(-text => "Double click to edit file: ", -background => "PaleTurquoise", -anchor => 'e'); # Create a listbox with the contents of the directory. my $ent = $tFrame->Scrolled(qw/Listbox -setgrid 1 -height 16 -width 40 + -scrollbars e -selectmode single/); for(@{dirContents}) { $ent->insert(0, "$_"); } $ent->bind( '<Double-Button-1>', sub { my $pid; $file_selected = $ent->get('active'); print .$/; Win32::Process::Create( $pid, $ENV{COMSPEC}, "/c \"$file_selected\"", 0, 0, "." )|| die ErrorReport(); } ); # Quit the edit directory contents popup my $quitButton = $bFrame->Button(-text => "Quit", -width => 12, -background => "PaleTurquoise", -activebackground => "PaleTurquoise", -command => sub { $TOP->destroy; } # strictly not nece +ssary ); # Instead of pack, using grid to place more precisely. Tk::grid($tFrame, -row => 0, -column => 0, -sticky => 'w', -padx => 10 +, -pady => 10, ); Tk::grid($bFrame, -row => 1, -column => 0, -sticky => 's', -padx => 10 +, -pady => 10, ); Tk::grid($quitButton, -row => 0, -column => 0, -sticky => 'w', -padx = +> 10, -pady => 10, ); Tk::grid($lab, -row => 1, -column => 0, -sticky => 'w', -padx => 10, - +pady => 10, ); Tk::grid($ent, -row => 1, -column => 1, -sticky => 'w', -padx => 10, - +pady => 10, ); MainLoop; sub readDir { my ($DirName) = @_; opendir (INDIR,$DirName) or die "\nCannot open $DirName: $!\n"; my @DirContents = grep{ !/^\.\.?$/ && -f $_ } map{ "$DirName\\$_" }readdir(INDIR); close (INDIR); return @DirContents; }

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

      This is working great. I didn't know we could get the application links from Windows parsed into Perl. I was going the though way while it could be done so easy. Thanks.

Re: How to look for application path
by juo (Curate) on Sep 30, 2002 at 08:18 UTC

    I have found the problem in the meantime. When you have a (Default) value in the registry you cannot use the "()". You just have to say Default and then it works fine. Of course any better suggestion to get easy installation paths of applications (version independent - adobe 4,5 / office 95,97,..) then using the registry is welcome.

Re: How to look for application path
by juo (Curate) on Sep 30, 2002 at 09:14 UTC

    Below a simplified sample. Still problems to read the default value

    #!/perl/bin -w ################################################################### # # Purpose: Declaration of Modules to use in this script ################################################################### use strict; use Win32::Process; use Win32API::Registry 0.21 qw( :ALL ); my ( $key, $type, $data ); RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Adobe\\Acrobat Reader\ +\5.0\\InstallPath", 0, KEY_READ, $key ) or die "Can't open SOFTWARE\\Adobe\\Acrobat Reader\\5.0\\Install +Path: ", regLastError(),"\n"; RegQueryValueEx( $key, "(Default)", [], $type, $data, [] ) or die "Can't read SOFTWARE\\Adobe\\Acrobat Reader\\5.0\\Install +Path\\(Default): ", regLastError(),"\n"; RegCloseKey( $key ) or die "Can't close HKEY_LOCAL_MACHINE\\SYSTEM\\Disk: ", regLastEr +ror(),"\n";
Re: How to look for application path
by jsprat (Curate) on Sep 30, 2002 at 17:10 UTC
    What you need is the ShellExecute function from the Win32 API. ShellExecute reads a file's extension and starts the associated application that handles that file type, just as if someone had double clicked on the file in explorer.

    #!/usr/bin/perl use strict; use warnings; use Win32::API; my $ShellExecute = new Win32::API("shell32", "ShellExecute", [qw(N P P + P P N)], 'N'); my $hWnd = 0; my $filename = 'c:/public/test.pdf'; $ShellExecute->Call($hWnd, 'open', $filename, '', '', 1);

    I didn't munge it into your example, but it should be pretty straightforward to do.