Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Win32::API giving a program error

by Anonymous Monk
on Jun 03, 2004 at 09:39 UTC ( [id://360009]=perlquestion: print w/replies, xml ) Need Help??

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

Fellow Monks,
I am tring to use the Win32::API module, but without success. Here's the code:
#!usr/bin/perl use Win32::API; my $filename="C:/Program Files/America Online 9.0g/aol.exe"; my $ApiObject = new Win32::API("C:/Documents and Settings/Mdaviesie/De +sktop/dver_1.3/fileversion.dll", "GetFileVersionTxt", 'PP','I'); #Set some memory aside for the returned value my $String="\x00" x 1024; #Call the function in the dll $ApiObject->Call($filename,$output); #Remove the unused padding in the string my $final = ($String =~/(.*?)\x00/); print "\$final - $final";
I am using activestate perl (v5.8.3) on windows 2000, when I try to run this script from the command line I get the message:
Program Error Perl.exe has generated errors and will be closed by Windows. You will +need to restart the program. An error log is being created.
Any pointers as to what I'm doing wrong here would be greatly appreciated.
Thanks in advance,
Jonathan

Replies are listed 'Best First'.
Re: Win32::API giving a program error
by BrowserUk (Patriarch) on Jun 03, 2004 at 10:06 UTC

    It will be difficult for anyone to help you with this unless they also have a copy of the DLL in question. However, the first thing you should do is add some error checking to your code. You should check that $ApiObject (aweful name!) does actually aquire a value and print out $^E if it fails so that you have a clue as to why.

    my $ApiObject = new Win32::API( "C:/Documents and Settings/Mdaviesie/Desktop/dver_1.3/fileversion. +dll", "GetFileVersionTxt", 'PP','I' ) or die "Failed to acquire API: $^E";

    Similarly, assuming that the ->Call(...) is returning, then you should be doing a similar check on the return code.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
Re: Win32::API giving a program error
by dave_the_m (Monsignor) on Jun 03, 2004 at 11:16 UTC
    I don't know anything about the win32 API, but a quick glance at the code shows that you set $string, but then do nothing with it and instead call ApiObject->Call() with $output, a variable you have neither delcared nor use subsequently.

    Dave.

      Hi there,
      Thanks to you both for the quick response. yes, the $output variable was a typo. As for the naming convention, I got that from an exceprt in "Win32 Perl Programming", here's the code again:
      #!usr/bin/perl use Win32::API; my $filename="C:/Program Files/America Online 9.0g/aol.exe"; my $apiobject = new Win32::API("C:/Documents and Settings/Mdaviesie/De +sktop/dver_1.3/fileversion.dll", "GetFileVersionTxt", 'PP','I') or di +e "Failed to acquire API: $^E"; #Set some memory aside for the returned value my $string="\x00" x 1024; #Call the function in the dll $apiobject->Call($filename,$string); #Remove the unused padding in the string my $final = ($string =~/(.*?)\x00/); print "\$final - $final";
      A bit of background, all the dll is supposed to return is the version number of the named file. The function I want to call looks like this:
      INT GetFileVersionTxt(STRING sFile, out STRING sVersion)
      The dll returns a version number (I was using the fileversion modules before, but their output is slightly different to what this dll returns - which is why I have to try to work with it). If anybody could provide me with a pointer as to why this is returning the error message,
      Thanks again,
      Jonathan
        Hi,

        A couple of notes. First, the line:

        my $final = ($string =~/(.*?)\x00/);

        probably should be:

        my ($final) = $string =~/(.*?)\x00/;

        otherwise $final would be a the success of the match, not the first capture block.


        Second, you may want to check the file path you are using. Many MS libraries need Windows file paths, not Perl-esque (or Unix like) ones. I have had this problem with Win32::COM a lot. I would want to give it a Perl-esque and I would get odd COM errors.

        So, instead of:

        my $filename="C:/Program Files/America Online 9.0g/aol.exe";

        try:

        my $filename="C:\\Program Files\\America Online 9.0g\\aol.exe";

        I can't explain why it would give you the error you are getting (and it may have nothing to do with it), but it is something you might want to check on.

        Ted
Re: Win32::API giving a program error
by Ven'Tatsu (Deacon) on Jun 03, 2004 at 14:43 UTC
    My guess would be a buffer overflow or similar issue, you are passing a string to your DLL that it is suposed to modify, but you are not telling it how long the string is.
    Is there any documentation stateing how long the of a string it expects?
    Having played around with some Windows system API calls in perl I've found that some will crash if the string passed to them is either too long or too small, you need to find what range you can pass in that is safe. Given that your passing a 1K buffer I'd guess your on the large size. How long is the expected result string? I'd guess that size times about 2 or 3 should be good, but if there is any documentation to lead you in the right direction that that over my wild guess work.

    disclaimer: I doubt my advice will cause any problems, but were talking about calles into C, especaly calls modifing stings, any thing can happen, don't hold me responsible if any advice causes your computer to spontaniously explode or other catestrophic results.
      Hi again,
      again, thanks to you both for your suggestions, I tried a good few variations on the buffer size, but without success. The same error message appeared... I also tried using windows style file paths, and included the change of my ($final) = $string =~/(.*?)\x00/;. But this also had no effect. The code now appears like this:
      #!usr/bin/perl use Win32::API; my $filename="C:\\Program Files\\America Online 9.0g\\aol.exe"; my $apiobject = new Win32::API("C:\\Documents and Settings\\Mdaviesie\ +\Desktop\\dver_1.3\\fileversion.dll", "GetFileVersionTxt", 'PP','I') +or die "Failed to acquire API: $^E"; #Set some memory aside for the returned value my $string="\x00" x 1024; #Call the function in the dll $apiobject->Call($filename,$string)| die "died at line 16"; #Remove the unused padding in the string my ($final) = $string =~/(.*?)\x00/; print "\$final - $final";
      I'm still no closer to figuring this one out, so if anybody out there could help me it would be greatly appreciated.
      Thanks in advance,
      Jonathan
        I know this a not really an awnser to your question, but depending on what you are doing it may offer a solution.
        Are you totally commited to using the Win32::API?
        You can get the information you require using OLE as well, and it is much simpler.
        use Win32::OLE; $file = "M:\\poledit.exe"; $fso = Win32::OLE->new('Scripting.FileSystemObject') or die "Cannot op +en File System Object"; $companyname = $fso->GetFileName ($file); $version = $fso->GetFileVersion ($file); print $companyname, "\t", $version;
        Of course if you are looking to do more with the Win32:API then this doesn't really help you. :-)
        You have your output parameter set as an Integer. That can't be good...

        Should probably be N or P, no?

        At this point I would start trying different versions of the software involved to see if it is some obscure bug that was recently introduced or fixed. For example, I might:

        1. Make sure I have the latest Win32::API. If not, use PPM to install the latest version. You can also check search.cpan.org to see if there is an bug report, or a note in the change log describing your problem. There may also be something in the Win32::API documentation (Note: I am not implying the Win32::API is the cause of the problem, but it can hurt to look).
        2. Are there other versions of your DLL you can try?
        3. Try a different version of ActivateState perl. I have had good success installing different versions of ActivateState Perl side by side on Win2K Systems. Just keep an eye on your PATH.

        It may seem extream to try different versions of your software, especially Perl. But, it seems like there is little information pointing to the exact cause of the error. By trying some of these points above, you might find a combination that works. I know, I don't like poking at a problem with a stick, but there isn't much to go on here. :-)

        Your error message said that a log file was generated. Any info in there?

        Ted

        Disclamer: I am quite braindead at times and so cannot be held responsible for damage caused by following my advice. That, I am a lowsy speler.

Re: Win32::API giving a program error
by bibo (Pilgrim) on Jun 03, 2004 at 21:55 UTC
    I see that the DLL you are calling is part of the MS Win2K resource kits. Have you perhaps seen this knowledgebase article about Fileversion.PL to do the same sort of stuff?

    Can you show the formal arguments and return type for the DLL function you are calling ("GetFileVersionTxt")? Like at least one other monk, I wonder if you have the types right. Also, the author of Win32::API indicates that if C structures are passed or returned, you must do some pack()ing or unpack()ing to make them right. Getting the args wrong in this manner will most certainly get you a visit from Doctor Watson (the windows exception handler) but the logs are not usually helpful. --b

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://360009]
Approved by martymart
Front-paged by been42
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-25 16:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found