none
unreferencing 'DLLImport' at runtime? Can this happen.... RRS feed

  • Question

  •  

    Can this happen?....

     

    In my code, I do use DLLImport & as we know it loads the external dll's......

    just I do know upto that.... How I can know where it loads all of those imported dlls at runtime....if I do want to

    unreference one of those externally imported dlls at runtime.... Can I?

     

    with regards

    Kalyan

    Thursday, February 7, 2008 12:52 AM

Answers

  •  

    Right now, I need to work on .Net Framework 1.1 .....VS 2003

     

    Marshal.GetDelegateForFunctionPointer is not available in 1.0.... so. I cann't marshal it as delegate for now....

     

    Do I have any other methods to change that in 1.1?

     

    with regards,

    Kalyan

    Friday, February 8, 2008 12:29 AM
  • You can load the native DLLs dynamically using LoadLibrary API and call the functions at runtime in the loaded dll.

    And you can check out this article: Late binding on native DLLs with C# which has implemented this idea.

    Thanks!
    Sunday, February 10, 2008 7:54 AM

All replies

  • Why would you do that?

     

    If you could, you would break the application, since the code would presumably have a reference to an unmanaged dll because it needs to use it?

     

    It would be easier to comment it out.

     

    Perhaps if you could explain what you want to do, then perhaps I could give you some ideas of how to solve the problem?

     

    Thanks,

     

    Martin Platt.

    Thursday, February 7, 2008 2:43 AM
  • There are tools out there that can tell you where the DLL references are originating from, one good one is Process Explorer (procexp) from Sysinternals. I'm not sure how it can be done from inside your application but I'd guess there is some way to do it.

    As for having detachable/overridable references to external libraries, yes it is possible but to do so you need to use delegates and LoadLibraryEx rather than DLLImport.

    The first bits you'll need are the Win32 API calls needed to find the library, release it, and possibly set the DLLs working directory if that's important:

            [DllImport( "kernel32.dll", SetLastError=true )]
            static extern IntPtr LoadLibraryEx( string lpFileName, IntPtr hFile, uint dwFlags );
            [DllImport( "kernel32.dll", SetLastError = true )]
            static extern bool SetDllDirectory( string lpPathName );

            [DllImport( "kernel32.dll" )]
            public static extern IntPtr GetProcAddress( IntPtr hModule, string procedureName );

            [DllImport( "kernel32.dll" )]
            public static extern bool FreeLibrary( IntPtr hModule );


    You'll need an IntPtr to hold a reference to the DLL you want to load up.

            private IntPtr _pDLL = IntPtr.Zero; // Pointer to the DLL.

    Define delegates for the functions in the DLL that you want to call. Here's an example:

            [UnmanagedFunctionPointer( CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true )]
            private delegate void EP_SetTempFolder(
                StringBuilder szTempFolder );

    To establish the link to the DLL:

                    string dllPath = "c:\TestDLLs\SomeDll.dll"; // Example

                    bool result = SetDllDirectory( Path.GetDirectoryName( dllPath ) );
                    if ( !result )
                    {
                        throw new Exception( "Library was not found." );
                    }
                    _pDLL = LoadLibraryEx( Path.GetFileName( dllPath ), IntPtr.Zero, 0 );
                    if ( _pDLL == IntPtr.Zero )
                    {
                        throw new Exception( "Library could not be loaded." );
                    }
                    result = SetDllDirectory( null );

    Then calling the method:
                IntPtr pAddressOfFunctionToCall = GetProcAddress( _pDLL, "EP_SetPhysicalStreamStatus" );
                if ( pAddressOfFunctionToCall == IntPtr.Zero )
                    throw new Exception( "Print engine could not be initialized." );
                   // Initialize the delegate.
                        EP_SetTempFolder setTempFolder = (EP_SetTempFolder)Marshal.GetDelegateForFunctionPointer(
                                                                               pAddressOfFunctionToCall,
                                                                               typeof (EP_SetTempFolder) );
                  // Call it.
                        setTempFolder( tempFolder );


    And finally to release the DLL reference:

                    if ( _pDLL != IntPtr.Zero )
                    {
                        FreeLibrary( _pDLL );
                    }
                    _pDLL = IntPtr.Zero;

    Be sure that the release code is called in your Dispose/cleanup.


    Freeing the reference and loading a DLL in a different directory should work fine, however Freeing the reference, replacing the DLL, and re-loading it likely will not work. (As it was explained to me, Windows will do some caching with the file referenced in memory.)
    Thursday, February 7, 2008 5:38 AM
  • Tnxs Steve & Martin for ur replies...

     

    Hi Steve Py , tnxs for your reply... for sure I will try what you have explained to me........... 

     

     

    Freeing the reference and loading a DLL in a different directory should work fine, however Freeing the reference, replacing the DLL, and re-loading it likely will not work. (As it was explained to me, Windows will do some caching with the file referenced in memory.)

     

      "Freeing the reference and loading a DLL in a different directory should work fine" ------>

     

     I am using 3 dll's in this way.... Problem is they have same name and input arguments. But, they are located in different folders & all those 3 dlls are not the same...

     

    Code Snippet

    namespace Test

    {

      public class StartClass

     {

        // I want to create instances for Class1, 2 or 3 and call its methods over here.

     }

    }

     

    namespace Test

    {

      public class Class1

     {   

    [DllImport(C:\Documents and Settings\test\Desktop\Class1dlls\apgtestone.dll)]

    static extern int OpenChannel(string deviceName, string channelName);

     }

    }

     

    namespace Test

    {

      public class Class2

     {   

    [DllImport(C:\Documents and Settings\test\Desktop\Class2dlls\apgtestone.dll)]

    static extern int OpenChannel(string deviceName, string channelName);

     }

    }

     

    namespace Test

    {

      public class Class3

     {   

    [DllImport(C:\Documents and Settings\test\Desktop\Class3dlls\apgtestone.dll)]

    static extern int OpenChannel(string deviceName, string channelName);

     }

    }

     

     

     

    " Freeing the reference, replacing the DLL, and re-loading it likely will not work. (As it was explained to me, Windows will do some caching with the file referenced in memory.)"

     

    I can understand that we cann't replace or unreference any of  those dll's with the same one's again in windows.

     

    tnxs....

    Kalyan..

    Thursday, February 7, 2008 6:02 PM
  • This kind of things smells a little...

    I'm not saying that it won't work, it just seems a little like a workaround to a proper implementation?

     

    I wonder if instead, you should have a strategy / provider pattern, using a configuration to create instances of classes so that you can control that sort of functionality more predictably?  I mean you could use the pattern to load an assembly, and create an instance of the class, then when you're finished with it, unload it.

     

    Whilst I can see that you might want to change dlls around, I wouldn't be doing it like that personally, and if you can actually tell me what you're trying to do, perhaps I can help further with other ideas on neater ways to achieve what you're after?

     

    I hope that helps,

     

    Martin Platt.

    Friday, February 8, 2008 12:26 AM
  •  

    Right now, I need to work on .Net Framework 1.1 .....VS 2003

     

    Marshal.GetDelegateForFunctionPointer is not available in 1.0.... so. I cann't marshal it as delegate for now....

     

    Do I have any other methods to change that in 1.1?

     

    with regards,

    Kalyan

    Friday, February 8, 2008 12:29 AM
  •  

    I want to load dlls for only 1 of  4 different projects at runtime where they all have dlls with same name but with different functionality and in different folders. Actually, dlls vary with the project... so, I need to load only one set of dlls at runtime

     

    I am working with VS2003 & 1.1.. so, hope you can get me with some ideas...

     

     

    Friday, February 8, 2008 7:28 AM
  • You can load the native DLLs dynamically using LoadLibrary API and call the functions at runtime in the loaded dll.

    And you can check out this article: Late binding on native DLLs with C# which has implemented this idea.

    Thanks!
    Sunday, February 10, 2008 7:54 AM