<div dir="ltr">Hi Ross,<br><br><br>It might work.  sounds plausible and is easy enough to test to make sure.  But it seems crude and inefficient.  You said yourself that in any one customer (site?) only 2 or 3 of the 30 DLL&#39;s are actually used.<div><br></div><div>I don&#39;t know how the two apps involved are used, but you are adding 30x the DLL delay to an app that doesn&#39;t use any of the DLL&#39;s and if the app that does use the DLL(s) is started at the same time and the 1 DLL it needs is the 30th one to be loaded then it could still be the 2nd app which suffers the delay if it happens to load it&#39;s DLL before the &quot;loader&quot; app has gotten around to loading that particular one.</div><div><br></div><div>And then even assuming that DLL loading does work the way you expect/hope, this isn&#39;t guaranteed to always be the case - you are relying on a behaviour in the OS which, however unlikely you may think it is, may change.  Even if the OS behaviour never changes, if the first app is unloaded for any reason, you suddenly lose your &quot;pre-loaded&quot; DLL&#39;s and the only way to get them back is to via some operating procedure that instructs the user to start this other app that doesn&#39;t even use the DLL&#39;s.</div><div><br></div><div>Also, is there a use case where a new DLL might be installed while these apps are running ?  If so, this won&#39;t get the benefit of the pre-loading by the application unless and until that pre-loader app is restarted.</div><div><br></div><div>Or, replace a DLL ?  In which case, after closing the application which uses those DLL&#39;s, the user must now also close the other application which does not.  If they only shut down the application which uses the DLL, then replace a DLL, after restarting the application it will continue to be using the older version of that DLL previously (and still) loaded by the loader app.</div><div><br></div><div><br></div><div>It all seems very messy.  Which is why fundamentally I am wary of solutions that involve putting the &quot;fix&quot; at a remove from the problem, and which do not solve the problem directly but rely on side effects to achieve the desired outcome.  :)</div><div><div><br></div><div>So, if by &quot;leave loaded permanently&quot; you mean &quot;load when first needed and retain for when needed again, switching between the loaded DLL&#39;s as required&quot;, then yes, that is what I mean.  :)<br></div><div><br></div><div>I don&#39;t see that it should be that tricky.</div><div><br></div><div>Even if you currently have all your DLL entry points in simple variables and don&#39;t currently have a facade, you presumably still have some function point at which a DLL is loaded (and any current DLL &#39;closed&#39;) which sets the entry point variables ?  So all you need to do is introduce the facade to manage the persisted function pointers and then fix-up your simple variables from the current &quot;in context&quot; library, before returning from your &quot;Load&quot; routine.<br><br>e.g. if you have a LoadDLL procedure which perhaps currently looks something like this (no error checking and not all declarations shown etc, for brevity/clarity):</div><div><br></div><div><div>    procedure LoadDLL( filename );</div><div>    begin</div><div>       if hDLL &lt;&gt; 0 then</div><div>          FreeLibrary(hDLL);</div><div><br></div><div>       hDLL := LoadLibrary(filename);</div><div><br></div><div>       fnFoo := GetProcAddress(hDLL, &#39;foo&#39;);</div><div>       fnBar := GetProcAddress(hDLL, &#39;bar&#39;);</div><div>    end;<br><br></div></div><div>then it becomes:<br><br>    procedure LoadDLL( filename );</div><div>    begin</div><div>       DLLManager.Load(filename);</div><div><br></div><div>       fnFoo := DLLManager.Foo;</div><div><div>       fnBar := DLLManager.Bar;</div></div><div>    end;<br><br>DLLManager is an instance of some class (which you need to code, obviously) which keeps all the ProcAddress-es for each DLL filename in some associative list and exposes only the &quot;active&quot; (i.e. most recently Load()-ed) function entry points via properties which you can then assign to your variables.<br><br>The DLLManager.Load() method loads the specified DLL file if required (the code for which is essentially already written in your current LoadDLL() method, as illustrated above).  The only difference being that the entry points are assigned to members of some record associated with that specific DLL filename, perhaps in a record type:<br><br></div><div>   PLoadedDLL = ^TLoadedDLL; <br></div><div>   TLoadedDLL = record</div><div>      Handle: HMODULE;</div><div>      Filename: String;</div><div>      fnFoo: TFooFn;</div><div>      fnBar: TBarFn;</div><div>    end;</div><div><br></div><div>    fLoaded: array of TLoadedDLL;</div><div>    fActive: PLoadedDLL;</div><div><br></div><div>When loading a specific DLL filename, DLLManager iterates over the array looking for that filename.  If found, then make fActive reference that entry.  Otherwise extend the array by one, load the DLL, set the entry point and other members of the new TLoadedDLL record and make that new entry the fActive reference.</div><div><br></div><div>The entry point properties then use getters to simply return the current active entry points:<br><br>   function TDLLManager.get_Foo: TFooProc;</div><div>   begin</div><div>      result := fActive.fnFoo;</div><div>   end;</div><div><br>You could make the DLLManager set any existing function entry point variables directly, but I see this as the job of the existing &quot;LoadDLL&quot; method, since this is the connective &quot;glue&quot; that binds the self contained job of the DLLManager to the needs of your current application code.<br><br></div><div>However you go about updating those entry point variables, all the existing code that uses these variables to call the DLL entry points is blissfully oblivious to the more sophisticated DLL management going on - all they know (and need to know) is that there is a currently active DLL they can call.  All the work is neatly encapsulated within the DLLManager object.</div><div><br></div><div>Add some cleanup code to FreeLibrary() all entries in the fLoaded array when the app closes and job done: a clean, reliable solution applied directly where the problem lies.  :)</div><div><br></div></div><div>hth<br></div><div><br></div><div>--</div><div>Jolyon</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 22 September 2015 at 16:45, Ross Levis <span dir="ltr">&lt;<a href="mailto:ross@stationplaylist.com" target="_blank">ross@stationplaylist.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div lang="EN-NZ" link="blue" vlink="purple"><div><p class="MsoNormal"><span style="font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d">You mean leave the DLL loaded permanently and switch to it when required?  I thought of that but the code is quite tricky as it is in that app.  I was hoping to not modify that app and just load the DLL’s in another one.  I take it my original plan would work?<u></u><u></u></span></p><p class="MsoNormal"><span style="font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1f497d"><u></u> <u></u></span></p><div style="border:none;border-top:solid #b5c4df 1.0pt;padding:3.0pt 0cm 0cm 0cm"><p class="MsoNormal"><b><span lang="EN-US" style="font-size:10.0pt;font-family:&quot;Tahoma&quot;,&quot;sans-serif&quot;">From:</span></b><span lang="EN-US" style="font-size:10.0pt;font-family:&quot;Tahoma&quot;,&quot;sans-serif&quot;"> <a href="mailto:delphi-bounces@listserver.123.net.nz" target="_blank">delphi-bounces@listserver.123.net.nz</a> [mailto:<a href="mailto:delphi-bounces@listserver.123.net.nz" target="_blank">delphi-bounces@listserver.123.net.nz</a>] <b>On Behalf Of </b>Jolyon Direnko-Smith<br><b>Sent:</b> Tuesday, 22 September 2015 3:24 p.m.<br><b>To:</b> NZ Borland Developers Group - Delphi List<br><b>Subject:</b> Re: [DUG] DLL loading slowed by anti-virus<u></u><u></u></span></p></div><div><div class="h5"><p class="MsoNormal"><u></u> <u></u></p><div><p class="MsoNormal">Hi Ross,<br><br>Rather than have an application load 30 DLLS (none of which it uses) for the sake of another application which might use as few as just 2 of those 30 and only ever one at a time, why not simply cache each loaded DLL in the application that is actually using them ?<u></u><u></u></p><div><p class="MsoNormal"><u></u> <u></u></p></div><div><p class="MsoNormal">I would hope that your function references to the DLL exports are already maintained in a record or even behind a class facade, which would make a cache simplicity itself to implement.  If not, introducing such a facade should be straightforward enough.<br><br>With such a cache you still get the initial delay but only for the first use and only for the DLL&#39;s actually being used and it eliminates any question about (or possible future variance in) the module loading behaviour of the OS or any problems arising as a result of your &quot;loader&quot; application failing to have loaded at/by the required or expected time etc.<u></u><u></u></p></div><div><p class="MsoNormal"><u></u> <u></u></p></div><div><p class="MsoNormal">--<u></u><u></u></p></div><div><p class="MsoNormal">Jolyon<u></u><u></u></p></div></div><div><p class="MsoNormal"><u></u> <u></u></p><div><p class="MsoNormal">On 22 September 2015 at 14:42, Ross Levis &lt;<a href="mailto:ross@stationplaylist.com" target="_blank">ross@stationplaylist.com</a>&gt; wrote:<u></u><u></u></p><div><div><p class="MsoNormal"><span style="color:#1f497d">My automation app loads 1 of perhaps 30 different 3<sup>rd</sup> party DLL’s depending on the job required.  It only has to do 1 job at a time and if the job changes (automatically), the current DLL is unloaded and the relevant one is loaded using LoadLibrary.  All the DLL’s have the same interface/functions.</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d"> </span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">It seems in recent times that the loading of a DLL is taking much too long for many customers, sometimes several seconds, which isn’t acceptable, and it appears to be related to anti-virus software scanning the DLL every time it loads, or at least the first time it has loaded on that day.  That seems to vary in different anti-virus software.</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d"> </span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">I need to remove that delay.  I would rather the main app not load every single DLL at startup as that would take a long time to load, and often only 2 or 3 of the DLL’s will ever be used by a customer.</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d"> </span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">There are 2 apps loaded at the same time and rather than altering the app that loads the DLL’s and does all the work, my thought was to have this 2<sup>nd</sup> app load all the DLL’s in the folder using a thread.</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d"> </span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">Am I correct that a 2<sup>nd</sup> app loading the same DLL will not actually load the DLL from the hard drive but just access it from RAM, so it should load very quickly?</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d"> </span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">Cheers,</span><u></u><u></u></p><p class="MsoNormal"><span style="color:#1f497d">Ross.</span><u></u><u></u></p></div></div><p class="MsoNormal"><br>_______________________________________________<br>NZ Borland Developers Group - Delphi mailing list<br>Post: <a href="mailto:delphi@listserver.123.net.nz" target="_blank">delphi@listserver.123.net.nz</a><br>Admin: <a href="http://delphi.org.nz/mailman/listinfo/delphi" target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>Unsubscribe: send an email to <a href="mailto:delphi-request@listserver.123.net.nz" target="_blank">delphi-request@listserver.123.net.nz</a> with Subject: unsubscribe<u></u><u></u></p></div><p class="MsoNormal"><u></u> <u></u></p></div></div></div></div></div><br>_______________________________________________<br>
NZ Borland Developers Group - Delphi mailing list<br>
Post: <a href="mailto:delphi@listserver.123.net.nz">delphi@listserver.123.net.nz</a><br>
Admin: <a href="http://delphi.org.nz/mailman/listinfo/delphi" rel="noreferrer" target="_blank">http://delphi.org.nz/mailman/listinfo/delphi</a><br>
Unsubscribe: send an email to <a href="mailto:delphi-request@listserver.123.net.nz">delphi-request@listserver.123.net.nz</a> with Subject: unsubscribe<br></blockquote></div><br></div>