1

我已经阅读了一些关于 PS 和类型转换的类似问答,但据我所知,它们的情况并不相同。

我正在尝试在 Powershell 脚本中使用 RMO 类,但由于某种原因,它认为必须转换为相同的类型,但没有这样做。

有问题的代码基本上是:

$conn = New-Object "Microsoft.SqlServer.Management.Common.ServerConnection" @($server, $dbUsernm, $dbPasswd);

$publicationDb = New-Object "Microsoft.SqlServer.Replication.ReplicationDatabase"
$publicationDb.Name = $dbName;
$publicationDb.ConnectionContext = $conn;

(如果我尝试使用双参数构造函数,则会发生类似的类型错误。)

错误是:

Exception setting "ConnectionContext": "Cannot convert the "(..snip..)" value of type
"Microsoft.SqlServer.Management.Common.ServerConnection" to type "Microsoft.SqlServer.Management.Common.ServerConnection"."

那么这里发生了什么?它显然是在尝试转换为相同的数据类型。这些没有在 PowerShell 脚本中定义,所以它不应该能够跟踪类型吗?我还尝试[Microsoft.SqlServer.Management.Common.ServerConnection]在其声明和/或调用/成员集中将变量强制转换为,但无济于事。

如果它是相关的,我正在以这种方式加载 RMO 类(这似乎是唯一的工作方法,即使据我所知LoadWithPartialName已被弃用):

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.RMO")

其中说:

GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SqlServer.RMO\v4.0_14.0.0.0__89845dcd8080cc91\...

这是否意味着它是该类的 v4.x,或者它是一个 .NET 4.x 类?如果它是一个 .NET 4.x 类,这是否相关,即这对 Powershell 来说是个问题吗?

4

1 回答 1

1

TLDR:故障排除摘要:@KeilaronImport-Module SqlServer早些时候在 PowerShell 会话中执行了导致奇怪行为的操作。

就我个人而言,我对简单重启 PowerShell 会话解决了这个问题并不满意,因为这种错误不应该发生。当我进一步挖掘时,我想我找到了根本原因,并发现这是一个很容易被忽略的更大问题。

首先,复制已发现行为的代码:

Import-Module SqlServer

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.RMO")

$server = 'MyServer'
$dbuser = 'sa'
$dbPasswd = '1234'
$conn = New-Object "Microsoft.SqlServer.Management.Common.ServerConnection" @($server, $dbUser, $dbPasswd);
$publicationDb = New-Object "Microsoft.SqlServer.Replication.ReplicationDatabase"
$publicationDb.Name = 'RandomDatabase'
$publicationDb.ConnectionContext = $conn;

发生了两件关键的事情:

  1. 加载模块中包含的Import-Module SqlServerSqlServer ,而不是GAC 安装的模块。这是设计使然,因为该模块不依赖于正在安装的 SQL Server。.dll
  2. Microsoft.SqlServer.Rmo.dll不是 SqlServer 模块的一部分,也不是随 SqlServer 模块一起加载的,因为 SqlServer 模块中没有复制命令。所以要使用复制命令,我们必须自己手动加载.dll

.dll我们关心的是透明导入的两个是来自 SqlServer PowerShell 模块位置Import-Module SqlServer的两个连接依赖:.dll

[System.Reflection.Assembly]::LoadFile('C:\Windows\System32\WindowsPowerShell\v1.0\Modules\SqlServer\Microsoft.SqlServer.ConnectionInfo.dll')
[System.Reflection.Assembly]::LoadFile('C:\Windows\System32\WindowsPowerShell\v1.0\Modules\SqlServer\Microsoft.SqlServer.SqlClrProvider.dll')

-->注意:这些是作为64 位.dll导入的。 .dll

我们必须手动导入的 RMO.dll来自 GAC,但本质上来自:

"C:\Program Files (x86)\Microsoft SQL Server\140\SDK\Assemblies\Microsoft.SqlServer.Rmo.dll"

注意:这是一个32 位 .dll的. 这就是我们无法将 a 转换"Microsoft.SqlServer.Management.Common.ServerConnection"为 type的原因"Microsoft.SqlServer.Management.Common.ServerConnection"。即使它们是相同的“类型”,正如名称一样,它们的不同位数导致它们不兼容。

于 2019-05-31T16:15:15.193 回答