5

希望你们都有美好的一天!

对于过去三天我一直在思考的事情,我需要你的建议。我有一个用非托管平台编写的 COM 组件。该组件有一个返回某种敏感数据的方法,我需要在获得该值后立即存储它。

我需要的是调用 UDF 来访问 COM 对象并获取值。到目前为止我已经尝试过了,我得到了这个例外:

消息 6522,级别 16,状态 2,第 1
行在执行用户定义的例程或聚合“GetRate”期间发生 .NET Framework 错误:System.Runtime.InteropServices.COMException:检索具有 CLSID {D039A99F- 的组件的 COM 类工厂5D45-42C7-A53C-507913D8C6D6} 由于以下错误而失败:80040154。System.Runtime.InteropServices.COMException

在 System.RuntimeTypeHandle.CreateInstance(RuntimeType 类型,Boolean publicOnly,Boolean noCheck,Boolean& canBeCached,RuntimeMethodHandle&ctor,Boolean& bNeedSecurityCheck)
在 System.RuntimeType.CreateInstanceSlow(布尔 publicOnly,布尔 fillCache)
在 System.RuntimeType.CreateInstanceImpl(布尔 publicOnly,布尔 skipVisibilityChecks,布尔 fillCache)
在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
at UserDefinedFunctions.GetRate(SqlString Source_Currency_Name, SqlString Destination_Currency_Name, SqlMoney Amount, SqlBoolean Mode)

该函数似乎看不到已注册的 COM 组件(80040154)。clr 程序集注册为不受限制。我尝试使用“sa”或 Windows 集成模式调用 UDF。没有区别。

这是初始化 COM 组件的代码,代码在 SQL 之外运行良好

Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("D039A99F-5D45-42C7-A53C-507913D8C6D6"), true))

反正有没有让这个工作人员?一种或另一种方式,我需要一个 UDF 调用这个 COM 对象,或者至少通过这个 UDF 使用 .NET 远程访问一些 Windows 服务。每一个建议都可以引导我完成这种方式,我们将不胜感激。

谢谢你们。

4

3 回答 3

5

一般来说,我不建议使用 SQL CLR 对象作为 COM 和 SQL 之间的桥梁。从安全性开始,到非常繁琐的发布过程结束,有很多潜在的警告,需要物理访问生产 sql 框,这可能很容易获得,也可能不容易获得。

我还注意到您正在使用 Activator.CreateInstance 然后向它​​提供 clsid。在您的原始帖子中,您暗示它是一个 COM clsid。我不确定在 SQL CLR 中创建的 AppDomain 中工作的 Activator 是否真的可以找到 com clsid 的对象。

我会尝试的方式:

  • 为您的 com 创建托管代理
  • 确保已签名并放入 gac
  • 尝试从 SQL CLR 访问该托管代理

但我严重怀疑它会起作用。任何远程解决方案 WCF/WebServices/Remoting 甚至 SQL Broker 似乎都是更好的选择。

简而言之,如果没有看到实际的 .net 和 sql codez,就很难说出更多信息。

于 2012-11-29T17:06:04.937 回答
4

我猜你正在将 CLR 程序集导入 SQL Server?如果是这样,这可能是平台/架构问题。当您构建 DLL 时,您的目标平台是什么?

确保您正在针对正确的平台(即 x86、x64)构建 DLL。

我建议您在 Visual Studio 中的 Project Properties、Build/Platform's Target 中修改项目"Any CPU"平台"X86"

然后使用"DROP ASSEMBLY", 后跟"CREATE ASSEMBLY", 重新导入正确构建的 dll。

您可能还需要确保已进行以下更改:

  1. 在 HKey_Classes_Root/Wow6432Node/CLSID 下找到您的 COM 对象 GUID。
  2. 找到后,添加一个新的 REG_SZ(字符串)值。名称应为 AppID,数据应与您刚刚搜索的 COM 对象 GUID 相同。
  3. 在 HKey_Classes_Root/Wow6432Node/AppID 下添加一个新密钥。新键的名称应与 COM 对象 GUID 相同。
  4. 在您刚刚添加的新键下,添加一个新的 REG_SZ(字符串)值,并将其命名为 DllSurrogate。将该值留空。
  5. 在 HKey_Local_Machine/Software/Classes/AppID 下创建一个新密钥(如果它尚不存在)。
  6. 同样,新键的名称应与 COM 对象的 GUID 相同。无需在此键下添加任何值。

另一种解决方案是使用 SQL clr 调用 WCF 服务。有关如何执行此操作,请参阅以下指南:

http://www.codeproject.com/Articles/21149/Invoking-a-WCF-Service-from-a-CLR-Trigger

于 2012-11-26T15:26:46.203 回答
0

如果您的 COM 应用程序的网络版本非常好,则在 sql select * from sys.dm_clr_properties 上运行此 cmd 仅当网络版本小于或等于时才有效!!!

于 2013-03-14T10:34:15.483 回答