I have created a SQL CLR that references the Windows DLL, WindowsBase. For the most part my CLR works just fine but if WindowsBase gets updated in the GAC then I get the error "
Assembly in host store has a different signature than assembly in GAC.".
To address this I built my CLR to reference a version of WindowsBase that is not in the GAC. Now when I run my CLR i get the error "
Could not load file or assembly 'WindowsBase, Version=188.8.131.52, ...' or one of its dependencies. The system cannot find the file specified."
I set up FusLogVw to see what's going on and get the following output
The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Running under executable C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn\sqlservr.exe --- A detailed error log follows. === Pre-bind state information === LOG: DisplayName = WindowsBase, Version=184.108.40.206 LOG: Appbase = file:///C:/Program Files/Microsoft SQL Server/MSSQL11.MSSQLSERVER/MSSQL/Binn/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = sqlservr.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. LOG: Post-policy reference: WindowsBase, Version=220.127.116.11 LOG: The same bind was seen before, and was failed with hr = 0x80070002. ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).
It would appear that the assembly loader is using the machine.config file to determine where it should look for the assembly. Based on this assumption I updated the machine.config with
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="WindowsBase"... /> <codBase version="18.104.22.168" href="./AdditionalAssemblies/WindowsBase.dll"/> </dependentAssembly> </assemblyBinding> </runtime>
I have tried with a relative path (relative to SQlservr.exe) and an absolute path but continue to get the same error mentioned above. Any suggestions on how to set up the SQL CLR so that it refereneces a copy of WindowsBase that is outside the GAC without getting the above errors would be greatly appreciated.
What you are attempting to do is not supported by SQL Server's CLR host. The CLR within SQL Server is highly restricted to prevent destabilizing SQL Server since it works differently than apps running on the OS. So, there is a very limited set of DLLs that are supported (i.e. verified to work and guaranteed to stay working across updates to .NET). WindowsBase is not one of them so you would need to load it manually as
UNSAFE into SQL Server. But that leaves you with either the problem that you ran into of the version in the main GAC changing (DLLs that are common between the GAC and SQL Server's CLR host must be the same version), or worse, if the DLL becomes "mixed" (both unmanaged C++ and managed code) and is no longer "pure". In that case the new version will not load and the old version gets the "wrong version" error so you have some work to do.
For more detailed information, please see the following articles / documentation:
That set of links is taken from the "Additional Reading" section of an article I wrote: Stairway to SQLCLR Level 5: Development (Using .NET within SQL Server).
For more information on working with SQLCLR in general, please visit my site: SQLCLR Info
User contributions licensed under CC BY-SA 3.0