Announcement

Collapse
No announcement yet.

Embedding a Dll

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Embedding a Dll

    I need to ship a single EXE, but that EXE requires a Dll (GRFXtools.Dll)

    Whats the common method for doing this?

    I can attach the Dll as a resource but then how do I get it
    installed on the HD before the program looks for it?


    ------------------
    Kind Regards
    Mike

  • #2
    PEBUNDLE *Might* be an option
    http://collakesoftware.com


    ------------------
    http://www.hellobasic.com
    hellobasic

    Comment


    • #3
      Bundled my exe with SQLT_Pro.DLL and it works !

      very useful !

      ------------------
      R Khan

      Comment


      • #4
        I've had great luck just using LoadResource, but other in these forum
        indicate you may run into issues.

        You would need to use LoadLibrary to avoid the need for the DLL to be there when the
        program starts


        ------------------


        [This message has been edited by John Schexnaydre (edited November 01, 2002).]

        Comment


        • #5
          John,

          How exactly?

          ------------------
          http://www.hellobasic.com
          hellobasic

          Comment


          • #6
            Here's what I used and I think it came from a post here. There are
            many post on LoadResource and LoadLibrary. Do a search and I'm sure
            you will find all you need on both.


            FUNCTION UnLoadRes(sPath AS STRING, ResId AS STRING) AS LONG

            ' sPath is name of output file - null means return in spath
            ' ResID is the name in the resource file

            DIM filehandle AS LONG
            DIM HRSRC AS LONG
            DIM HGLOBAL AS LONG
            DIM datasize AS LONG
            DIM pData AS LONG
            DIM buffer AS STRING


            HRSRC = FindResource(GetModuleHandle(""),BYVAL STRPTR( ResID ),BYVAL %RT_RCDATA)

            IF HRSRC THEN
            HGLOBAL = LoadResource(%NULL, HRSRC)
            IF HGLOBAL THEN
            datasize = SizeofResource(%NULL, HRSRC)
            pData = LockResource(HGLOBAL) 'Get a data pointer
            IF pdata THEN
            buffer = PEEK$(pdata, datasize)
            END IF
            END IF
            END IF

            closehandle HRSRC
            closehandle HGLOBAL

            IF datasize > 0 AND buffer <> "" THEN
            IF spath="" THEN
            sPath=buffer
            FUNCTION=%True
            ELSE
            filehandle = FREEFILE
            OPEN spath FOR BINARY AS filehandle BASE = 1
            PUT$ filehandle ,buffer
            CLOSE filehandle
            FUNCTION = %TRUE
            END IF
            ELSE
            FUNCTION = %false
            END IF
            END FUNCTION


            ------------------

            Comment


            • #7
              A save to disk that is.
              I was thinking a load directly from resource

              ------------------
              http://www.hellobasic.com
              hellobasic

              Comment


              • #8
                John,

                I love that idea. Im going to play with it this weekend.

                ------------------
                Kind Regards
                Mike

                Comment


                • #9
                  Hi John,
                  Ok Ive tried that but no luck. I call the function as the very
                  first thing in PBMAIN but i still get the error message
                  "a required DLL file (GRFXtools) was not found"
                  can I load the dll into memory before the app checks to see
                  if it is avaiable, and point to it?



                  ------------------
                  Kind Regards
                  Mike

                  Comment


                  • #10
                    Mike,

                    If you're getting that message, then somewhere in your code
                    there is still something that uses IMPLICIT loading to
                    call the DLL. To resolve it, you must use LoadLibrary/FreeLibrary
                    and CALL DWORD on ALL of the DLL's functions. Another thing that
                    can cause that message is the format that your EXE uses when it DECLARE's
                    the procedures in the DLL.

                    The following will cause the error message:

                    DECLARE MyFunction LIB "MYDLL.DLL" ALIAS "MyFunction" <blah, blah>

                    The following will avoid the error, and allow you to use LoadLibrary/
                    CALL DWORD instead:

                    DECLARE FUNCTION MyFunction (<args> ) AS <whatever>

                    Note that the key thing is that there are no "LIB "<dllname>"" verbs.

                    ADDED: I just read up on CALL DWORD in the IDE help, and it said
                    you should also not specify the "ALIAS" clause when DECLARE'ing
                    functions for use with CALL DWORD.

                    John,

                    Even MS discourages relying on SizeOfResource to return the size of
                    an embedded resource. According to win32.hlp <highly paraphrased, off
                    the top-of-my-head>: "...the returned value may or may not be the
                    actual size of the resource...because it might be aligned on a DWORD
                    boundary...therefore, programmers should not rely on this function
                    if they need to know the actual size of the resource..."

                    In Mike's case, since he is only embedding the one resource, the workaround
                    is quite simple - manually use a constant in his code that specifies the true
                    size of the DLL.


                    ------------------




                    [This message has been edited by Clay Clear (edited November 05, 2002).]

                    Comment


                    • #11
                      Mike, have you looked at Don's self extract utility?
                      Quote

                      C-SelfX is a program that creates self-extracting archives.
                      It is no longer being sold. I have decided to give it away.
                      Click here to download the package.
                      The password for the installer is: anikitty.
                      Source (requires both pbdll6+ and pbcc2+ to compile) is included

                      Unquote

                      Check http://www.basicguru.com and navigate through Don Dickinson's links.

                      It might just help.

                      David

                      ------------------

                      Comment


                      • #12
                        The direct link to Don's site is:

                        http://dickinson.basicguru.com/


                        ------------------

                        Comment


                        • #13
                          David,
                          Thx, but i dont want to do it that way. What I want to do is
                          Embed the dll and ship ONE app to the customer, but thx anyway ...

                          Clay,
                          I understand what you are saying in concept. I will have to play
                          with this a little. The first thing to do is rewrite the Declarations
                          that come with GRX tools, not a small task!


                          ------------------
                          Kind Regards
                          Mike

                          Comment


                          • #14
                            Mike,

                            Rather than "rewrite" what I assume are a lot of DECLARE's, why
                            not create a separate INC file with your OWN DECLARE's, and INCLUDE that
                            in the EXE instead of the original INC? CALL DWORD couldn't care
                            less what you call the DECLARE'd functions (but the compiler will choke
                            if the FUNCTION names are already declared, for example, in
                            win32api.inc)

                            In your new INC file, you could just do:

                            DECLARE FUNCTION I1 (<args> ) AS <type>
                            DECLARE FUNCTION I2 (<args> ) AS <type>

                            The only drawback to this is having to memorize which new function name
                            goes to which original function. Also, you MUST have the <args> and
                            the AS <type> declared the same as in the original INC file, otherwise
                            the DLL will GPF when you run the functions with CALL DWORD.

                            Just some ideas.


                            ------------------

                            Comment


                            • #15
                              mike, a few months back i posted an example of embedding files inside an exes resource
                              in the source code forum:
                              http://www.powerbasic.com/support/pb...ad.php?t=23527

                              but like they said, you will have to use the loadlib/call dword method instead of
                              implicit declares, since the dll will not exist during startup.

                              clay, are you saying that using the sizeofresource api will not work? because i have
                              been using this method for some time and never seen a problem. i have looked in both
                              the msdn (which my copy might be outdated) and the new sdk and cant find a reference to
                              the problem you mentioned. i did find a one liner in the win32.hlp that simply said that
                              the return value might be larger that the actual resource. but this would only add a
                              few bytes to the end of the new file. this doesnt seem to hurt exes, or dlls. will it?

                              do you think i should be using another method? (maybe storing a resource table that lists
                              the exact file sizes?)



                              ------------------
                              "i haven't lost my mind... its backed up on tape... i think??"
                              "I haven't lost my mind... its backed up on tape... I think??" :D

                              Comment


                              • #16
                                William,

                                That's why I said "...highly paraphrased...", as it's been a
                                LONG, LONG time since I initially researched the technique.
                                I cannot even be sure that it were win32.hlp where I read it.
                                It could very well have been an obscure article on the MSDN
                                site.

                                I myself never had a problem with that API, but, after I read it,
                                I decided "better safe than sorry." So, what I did was to write
                                some utilities that automated updating the RC file that my
                                distribution EXE used. Part of that automation was that, every time
                                utils were run, they'd determine the size of the resources, and write
                                them to the RC file. There was a one-to-one correlation between
                                the ID's of the resources (RCDATA's) themselves and the ID's
                                that contained the resources' sizes. The ID's that contained the
                                sizes were contained in STRINGTABLE's and were simply the sizes
                                in human readable text form. The EXE would convert them back to numeric
                                when doing the actual extracting/installation on the end users'
                                machines.


                                ------------------

                                Comment


                                • #17
                                  William,
                                  Thx for the example. As this is unraveling it seems it is pointless
                                  to write the DLL to the HD, so I am just going to try to use
                                  LOADLIBRARY and point to the function start address like this:

                                  edit
                                  hRes = FINDRESOURCE(BYVAL 0&, "GRFXDLL", BYVAL %RT_RCDATA)
                                  LRes = LOADRESOURCE(BYVAL 0&, hRes)
                                  hLib = LRes ' ???
                                  pAddr = GetProcAddress(hLib, "GfxFont")
                                  CALL DWORD pAddr SDECL (sFontName, a, b, c, d, e, f)

                                  I have not tried this yet beacuse I want to find out if there is a
                                  way that i can call the function without using variables specifically:

                                  CALL DWORD pAddr SDECL ("Arial Black", 20, 60, 1, %Black, %TEXT_ETCHED, 0)

                                  fails at compile time. I guess unlike calling functions without using
                                  CALL DWORD, you cannot use anything but variables? or is there a
                                  sneaky way around this that I have not thought of?
                                  This is a pain cos I will have to define a bunch of variables before
                                  each CALL DWORD, and then use them in the function call!


                                  [This message has been edited by Mike Trader (edited November 05, 2002).]

                                  Comment


                                  • #18
                                    The value returned may be larger than the actual resource because of alignment. An application should not rely upon this value for the exact size of a resource.
                                    William,

                                    The line above is a direct copy-and-paste from my copy of win32.hlp.


                                    However, it's very interesting to note that my PSDK (Nov 2001)
                                    does not make note of the shortcoming? Maybe it was an issue that was addressed
                                    by MS in OS's after Win95 & NT 4.0?

                                    Mike,

                                    Don't give up so easily. John's code will work fine, except that you
                                    should replace:

                                    datasize = SizeOf <etc.>

                                    with:

                                    datasize = 117113 (replace "117113" with the actual size, in bytes, of
                                    the DLL you are embedding)

                                    I am not aware of any CALL DWORD requirements that you use variables.
                                    I *think* (it's been a LONG time, so can't be sure), that I have
                                    used constants in CALL DWORD without any problems.

                                    What exactly are the errors/error messages that you're getting?
                                    I think the problem will most likely be inconsistencies between
                                    your DECLARE's and the CALL DWORD's implementation. Maybe you can post both
                                    the DECLARE and the CALL DWORD code from one of the functions that
                                    are generating the error(s)?


                                    ------------------


                                    [This message has been edited by Clay Clear (edited November 05, 2002).]

                                    Comment


                                    • #19
                                      William, Mike,

                                      I now have reason to believe that SizeOfResource may safely be
                                      used by PREDEFINED resource types (of which RCDATA is one, such as
                                      for Mike's DLL).

                                      I just did a search on the MSDN site for "sizeofresource"
                                      and read the first two hits that were obviously about it.

                                      The first one, which described the usage of the API itself,
                                      did not make any mention of "boundary aligning", nor did
                                      it say that "programmers should not rely on it for the actual resource size".

                                      The second one I read is the MAIN one: it specifically said
                                      (will have to paraphrase, as I didn't make a hardcopy of it):
                                      "...it should not be used on user defined resources..."

                                      So, Mike, I think it's pretty safe to assume that you may use John's
                                      original:

                                      datasize = SizeOf <etc.>

                                      line.

                                      John,

                                      Please accept my apologies for dissing your code.


                                      ------------------




                                      [This message has been edited by Clay Clear (edited November 05, 2002).]

                                      Comment


                                      • #20
                                        Mike,
                                        just an observation, but you left out the USING parm in your CALL DWORD.
                                        CALL DWORD pAddr SDECL ("Arial Black", 20, 60, 1, %Black, %TEXT_ETCHED, 0)
                                        I was under the opinion that if you had any parameters to pass you needed to use the
                                        USING clause to point the compiler to a declare that would define the type of each
                                        parameter. I may be wrong. But it is worth a try, because I have never seen a problem
                                        with using litterals in CALL DWORDs. Another thought is to use the literals with forced
                                        typing, by adding the type symbol to the values. (example 10& would be a long type)
                                        See the helpfile under data types for more info about forced types.

                                        Quote from PowerBasic help file:
                                        You can also force a literal value to be stored with a given precision by following the constant with one of the variable type-specifiers (%, &, &&, ?, ??, ???, !, #, ##, @, @@).
                                        Clay, thanks for looking up the info.


                                        ------------------
                                        "I haven't lost my mind... its backed up on tape... I think??"
                                        "I haven't lost my mind... its backed up on tape... I think??" :D

                                        Comment

                                        Working...
                                        X