Microsoft.SqlServer.Types.dll in the Global Assembly Cache?

Xharlie picture Xharlie · Mar 19, 2015 · Viewed 19.5k times · Source

I am currently struggling with deployment problems caused by Microsoft.SqlServer.Types and its associated unmanaged library, SqlServerSpatial110.dll - both for Microsoft SQL Server 2012. The problems are trivially easy to solve, just typical missing DLL issues, but I am trying to decide on the perfect way to handle these dependencies.

Firstly, I must declare that I do not agree with the popular opinion that manually deploying either library (usually by copying them into your project's output directory or, horrifically, into System32 itself) is correct. Microsoft provide redistributable MSI installers for these files and those installers put the files into system locations. It seems obvious that they want us to depend on those redistributables being installed separately or as part of the tried and tested dependency mechanisms built into MSI itself.

At the time of posting, the latest version of these redistributables could be downloaded from: http://www.microsoft.com/en-gb/download/details.aspx?id=43339

For SqlServerSpatial110.dll, there does not appear to be any problem. The MSI installers (platform specific) drop the file into either Windows\System32 or Windows\SysWOW64 as is appropriate and all is well.

The managed wrapper library, Microsoft.SqlServer.Types.dll, is more confusing.

It seems to me that the file is dropped into the Global Assembly Cache - after running the MSIs, on my machine, I can see it located at C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Types\11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Types.dll and that file has the correct version and modified-date.

Oddly, I can't see it in Visual Studio's reference browser or in Windows Explorer directly - only in my very old fashioned file-system search tool by Mythicsoft. Why can't I see it?

Since the file is almost in the GAC, I would guess that projects referencing it should not make a local copy of it - they should rely on it being there on the target system. I tested this assumption and it worked:

  1. Manually copy Microsoft.SqlServer.Types.dll from its location in C:\Windows\assembly\GAC_MSIL
  2. Add a reference to the copy.
  3. Ensure that the reference has Copy Local set to False
  4. Build the project and ensure that Microsoft.SqlServer.Types.dll is definitely not present in the output.
  5. Test project... no problems!

So, if the assembly can be resolved from the GAC at runtime to satisfy this dependency, why isn't it shown in the reference browser when adding a reference? Why do I have to copy it out of the GAC and reference the copy?

In my mind, the ideal work-flow would be this:

  1. Install redistributable MSIs on development machines.
  2. Ensure redistributable is installed on target machines by listing it as an MSI dependency if your product is deployed via MSI or manually installing it if you're using 'xcopy' deployment.
  3. Reference Microsoft.SqlServer.Types from the GAC using the reference browser just like any framework library. (Copy Local will be set to False by default.)
  4. At runtime, Microsoft.SqlServer.Types (platform agnostic) will be resolved from the GAC and the appropriate copy of the unmanaged library will be loaded from the system location depending on the process architecture.
  5. No worries!

Clearly, step 3 doesn't happen. Am I missing something? Perhaps I am misunderstanding the GAC itself - it wouldn't be the first time. Why has Microsoft done it this way? Can I get closer to my ideal work-flow?

Perhaps there is an entirely different way of managing this dependency - something I have clearly not thought of. If so, what is it? How do you handle it?

Answer

Ross Bush picture Ross Bush · May 25, 2016

If this is a one click deployment then go to the Project|Properties|Publish tab and click the "Application Files..." button. You should then select the dependent file and make sure The "Include(Auto)" is selected for the "Publish Status" value. The reason being is that is appears that VS is smart enough to determine if the file is part of a known redistributable and this giving you the option to depend on the external package during install as a dependency or manage the file yourself. If you depend on the package then the end user can uninstall via add remove programs and your app is busted :/