Calling unmanaged C/C++ DLL functions from SQL Server 2008 - sql-server-2008

I have a vast library of C/C++ functions, which needs to be called from SQL Server 2008.
I have written a C# adapter class which loads these functions from Win32 DLL with DllImport and exposes them to .Net code. This works perfectly fine in most .Net applications.
Now, I was trying to use the same technique with SQL Server CLR. I create a set of CLR functions and stored procedures, which call the adapter class. This does not work as an attempts to load unmanaged DLL results in System.BadImageFormatException.
I can do this with extended stored procedures, but that method is deprecated and may be discontinued in any new release of SQL Server.
What would be the proper way of calling unmanaged functions from CLR stored procedure? My guess that this should be done out-of-process.
I am trying to make my stored proc call a Web service which exposes these functions. This sounds like a good idea, but so far I am having a problem deploying the SQLCLR assembly which makes Web service call. I cannot load System.ServiceModel.dll assembly version=3.0.0.0, which has dependency on System.Web.dll assembly version 2.0.0.0.
Loading System.Web assembly gives me the following error:
Assembly 'System.Web' references assembly 'system.web, version=2.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.', which is not present in the current database. SQL Server attempted to locate and automatically load the referenced assembly from the same location where referring assembly came from, but that operation has failed (reason: version, culture or public key mismatch). Please load the referenced assembly into the current database and retry your request.
I have found the solution for the problem of deploying System.Web assembly. Instead of deploying it from C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll, it should be deployed from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll. Then all other required assemblies get deployed too.
The list of assemblies in the order of deployment:
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMdiagnostics.dll
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll
C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Messaging.dll
C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.dll
C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.IdentityModel.Selectors.dll
C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\Microsoft.Transactions.Bridge.dll

Interesing discussion here : MSDN - Unmanaged code in SQL CLR. I suspect it's due to how the DLL's are loaded by the engine. They present a series of options including hosting the code outside the sql server in another service and accessing the code using WCF or perhaps COM. The Final option is to perhaps recompile your code to pure managed C++ but this may not be an option for legacy code.
Understanding CLR Integration in SQL Server 2005 presents more information on how the process works.
To further restrict the code that is allowed to exist and execute
inside SQL Server each assembly must be registered with a set of
permissions. Three pre-defined sets are available to use; SAFE,
EXTERNAL_ACCESS and UNSAFE
...
You should also review CLR Integration Security, and detemrine the trust levels need for the code you're executing and whether you will be able to access use the code within the CLR process anyway.

Related

How to use a SQL Server Integration Services (SSIS) custom Connection Manager programmatically?

I am trying to programmatically create an SSIS package from a C# console application that uses a 3rd party Custom Connection Manager for Kafka like so:
static void Main(string[] args)
{
Application app = new Application();
Package pkg = new Package();
ConnectionManager cmKafka = pkg.Connections.Add("KAFKACS");
...
which fails with:
Microsoft.SqlServer.Dts.Runtime.DtsRuntimeException
The connection type "KAFKACS" specified for connection manager ... is not
recognized as a valid connection manager type.
Adding this manager to an Integration Services Project from Visual Studio 2017 works just fine, however.
I am new to SSIS, C# and Windows development. Here's what I've tried so far:
Add GAC references to KAFKACS assemblies to my console application.
Force 64bit execution which results in Microsoft.SqlServer.DTSRuntimeWrap not found.
Use reflection to try to figure out what architecture and for what .NET framework version the Kafka DLLs I reference target (looks like MSIL).
Create versions of the same application using previous versions of .NET target framework.
Try to manually create an instance of the Kafka manager as shown here:
var rawKafka = new KafkaConnectionManager();
ConnectionManager cmKafka = (???) rawKafka;
pkg.Connections.Join(cmKafka);
Do I need to register the KAFKACS component in order for the call to Connections.Add to succeed?
Are the error messages misleading and I am missing other, perhaps Kafka specific assemblies I need to reference?
Can I manually create a instance of the KafkaConnectionManager and use it with Connections.Join?
To answer my question, the issue had been that the 3rd party Connection Manager was build for SQL Server 2017 (v14) but the console application referenced the ManagedDTS assembly for 2016 (v13).
The call to pkg.Connections.Add("KAFKACS") could not find the DLLs since the 3rd Party installer had installed them in C:\Program Files (x86)\Microsoft SQL Server\140\DTS\Connections (where 140 corresponds to v14) and not in \130\DTS\Connections where v13 of ManagedDTS would expect to find them.

Problem: Could not load file or assembly 'CrystalDecisions.Web, Version=13.0.3500.0

Using Visual Studio 2010, I am reporting on my local computer vith SAP Crystal Reports. Everything works on the local computer very well.
However, when I upload my project to highh security remote hosting after publishing the project, I get the specified warning as mentioned below.
In this case, I would like to ask; am I making a mistake in the coding or my Crystal Report versions is wrong? or this is the hosting server's company problem?
Thank you.
Configuration Error
Parser Error Message: Could not load file or assembly 'CrystalDecisions.Web, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' or one of its dependencies. The system cannot find the file specified.
Source Error:
An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
Source File: D:\IISDIRS\web.config Line: 29
Assembly Load Trace: The following information can be helpful to determine why the assembly 'CrystalDecisions.Web, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304' could not be loaded.
The machine has a Crystal runtime engine that is incompatible with the way your application was built (the Crystal references in your application).
Reference/Version=13.0.2000.0 works with Crystal runtimes 0 to 24
Reference/Version=13.0.3500.0 works with Crystal runtimes 21 to 25
Reference/Version=13.0.4000.0 works with Crystal runtimes 26 and later (for now)
For example, if your Crystal references in your project show 13.0.2000.0, then you need to install Crystal runtime engine SP20.
If you need to remove a Crystal runtime engine service pack and install another, this link has great instructions for cleaning it up:
https://help.jeff-net.com/knowledgebase/article/uninstalling-a-crystal-runtime-service-pack-manually-removing-the-crystal-runtime-engine
Please be careful removing Crystal runtime engines, too. OTHER software may be dependent on a specific version. For example, SAGE apps only work with SP21 currently.

How to run SSIS packages from an external application?

I have an application I am writing that accepts files of various formats. Then I write code for each format (csv, excel, xml) to convert it and enter it into a SQL Server database. This is fine but I was just looking into SSIS and wondering if this would help.
The main question though is how do I run these packages within my own code? Is it easy to pass parameters? If I move this web app to another server does it depend on other components being on that server (maybe SQL Server 2012 installed)? Or is it just some DLLs I can reference from my web app?
All the demos I see are about using the SSIS tool but I am more interested in how difficult it is to call packages with parameters from my code.
The BIDS/SSDT installation includes a complete client SDK that makes it pretty simple to run SSIS packages via code.
This MSDN article explains how to load and run a package via C# in detail but the actual code boils down to:
using Microsoft.SqlServer.Dts.Runtime;
.
.
.
Application app = new Application();
Package pkg = app.LoadPackage(PKG_FILE_NAME, null);
DTSExecResult pkgResults = pkg.Execute();
The Package object has a lot of properties and methods you can look into, in particular there is a Parameters collection that allows you to pass parameters into your SSIS package before execution.
There is a very cool library called EzAPI where you can generate your own packages and call them from within C#. It gives you a lot of flexibility to generate SSIS on the fly and execute.
http://sqlsrvintegrationsrv.codeplex.com/releases/view/21238
I built a couple console apps inside this project to test some of these methods and you might find the examples useful:
https://github.com/thevinnie/SyncDatabases
Look at "BuildingAPackage" and "BuildALookupPackage"
You can programmatically build SSIS packages using C# or VB.NET and then run the packages. You can also load an existing package programmatically to execute it. I have little experience with building packages this way since most of the packages can be built easily using the following tools.
Read the article Building Packages Programmatically on MSDN for more details.
I feel that it is easier to build the packages through these IDEs depending on which version of SSIS you are targeting. You can also create initial packages through SQL Server Import and Export Wizard and save the SSIS packages to the local disk, which you can later modify according to your needs.
SSIS Version Development IDE Visual Studio Shell
------------------- ----------------------------------------------- -------------------
SSIS 2005 Business Intelligence Development Studio (BIDS) Visual Studio 2005
SSIS 2008 - 2008 R2 Business Intelligence Development Studio (BIDS) Visual Studio 2008
SSIS 2012 SQL Server Data Tools (SSDT) Visual Studio 2010
You need to reference the appropriate SSIS specific DLLs in your code to create/load SSIS packages.
However, you will need a SQL Server Integration Services license to run the package. You cannot simply reference the DLLs alone. The license is usually part of your SQL Server license, if you already have one.
Response to your comment:
We will have SQL 2012 or 2008R2 on a separate server.. So I just need to paste the needed DLLs on my web server and reference them. correct ?
The packages will execute on that server. You are just remotely invoking to execute them and you should reference the appropriate DLLs in the code within your web/other form of external application. I usually schedule the packages to run on the database servers under SQL Server Agent Job. You can try that if that is an option for you.
Package parameters are read-only from an external application. You'll need to pass them in as variables (which I have done). If you are dealing with an existing package with parameters, you may consider writing a script task that populates the parameters from the variables (which I have not done).

Unable to Deploy SQLCLR Project

My first SQLCLR project is resisting all attempts to deploy...
I get the error
The following error might appear if you deploy a SQL CLR project that
was built for a version of the .NET Framework that is incompatible
with the target instance of SQL Server: "Deploy error SQL01268: CREATE
ASSEMBLY for assembly failed because assembly failed verification". To
resolve this issue, open the properties for the project, and change
the .NET Framework version.
C:...\SqlClr.dll : Deploy error : Could
not create a type for parameter MyModel.Customer customer
The command
select * from sys.dm_clr_properties
returns
directory C:\Windows\Microsoft.NET\Framework64\v2.0.50727\
version v2.0.50727
state CLR is initialized
The Target framework for the project is .NET Framework 2.0
The object referenced in the error message MyModel.Customer is included in the SqlClr project via a Link (Add Existing Item / Add as Link) from another project that is using .NET Framework 4.0, but my understanding is the other project's .NET version should have no bearing.
What might I be missing?
If you are referencing an assembly that is dependent upon .NET 4.0, you're likely in for trouble. My understanding is that SQLCLR assemblies must be based on .NET versions 2.0 through 3.5, because versions 2.x and later prior to 4.0 are really just extensions based on 2.0. That tends to coincide with some information I read recently about an explicit decision for the SQLCLR not to support Framework 4.0.

How to add reference to an external DLL from within script task?

How can I add reference to an external assembly from within a script task and deploy the package to a server along with the newly added external assembly?
If this is in reference to your other recent question, then the only proper way to get the correct version of a Word DLL on the server where you want to deploy to is to install the proper product onto the server. Most DLL's (especially from products like Microsoft Office) are not redistributable (meaning you are not legally allowed to copy them from machine to machine without the underlying product installed). If a DLL from Microsoft is redistributable, then there will be a document accompanying the DLL that tells which DLL's are allowed to be copied from machine to machine and what the correct process for doing so is.
If this is not in reference to that question, then can you provide more detail about what it is you are trying to do so that we can help you more.
Assuming you are using SSIS 2008 (it was a bit different for SSIS 2005) -
the referenced assembly needs to be installed into GAC (Global Assembly Cache)
on target machine where you run the package.