gpt4 book ai didi

sql-server - Receive-Job返回的意外变量类型

转载 作者:行者123 更新时间:2023-12-02 23:07:21 25 4
gpt4 key购买 nike

我正在尝试执行Invoke-Sqlcmd命令(来自SqlServer module)以另一个AD用户身份运行查询。我知道有-Credential参数,但这似乎不起作用。

因此,我认为使用Start-Job可能是一个选择,如下面的代码片段所示。

$username = 'dummy_domain\dummy_user'
$userpassword = 'dummy_pwd' | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential ($username, $password)

$job = Start-Job -ScriptBlock {Import-Module SqlServer; Invoke-Sqlcmd -query "exec sp_who" -ServerInstance 'dummy_mssql_server' -As DataSet} -Credential $credential

$data = Receive-Job -Job $job -Wait -AutoRemoveJob

但是,查看作业返回的变量类型时,这不是我期望的。
> $data.GetType().FullName
System.Management.Automation.PSObject

> $data.Tables[0].GetType().FullName
System.Collections.ArrayList

如果直接在 ScriptBlock中运行代码,则这些是PS返回的变量类型:
> $data.GetType().FullName
System.Data.DataSet

> $data.Tables[0].GetType().FullName
System.Data.DataTable

我尝试将 $data变量转换为 [System.Data.DataSet],这导致以下错误消息:
Cannot convert value "System.Data.DataSet" to type "System.Data.DataSet". 
Error: "Cannot convert the "System.Data.DataSet" value of type
"Deserialized.System.Data.DataSet" to type "System.Data.DataSet"."

问题:
  • 是否存在使用Invoke-Sqlcmd命令在其他AD帐户下运行SQL查询的更好方法?
  • 是否有办法在调用Receive-Job时获取要返回的正确/预期变量类型?

  • 更新

    当我运行 $data.Tables | Get-Member时,返回的属性之一是:
    Tables  Property  Deserialized.System.Data.DataTableCollection {get;set;}    

    最佳答案

    1. Is there a way to get the correct/expected variable type to be returned when calling Receive-Job?


    由于使用后台作业,您将失去类型保真度:返回的对象是原始类型的无方法仿真。

    手动重新创建原始类型是不值得的,甚至可能无法实现,尽管使用仿真可能就足够了。

    更新:作为 per your own answer,从使用 System.DataSet切换到 System.DataTable可以为您提供可服务的仿真。[1]

    有关更多信息,请参见底部。

    1. Is there a better way to run SQL queries under a different AD account, using the Invoke-Sqlcmd command?


    您需要一个进程内调用方法来保持类型保真,但是如果您要模拟另一个用户,我认为使用任意命令是不可能的。

    例如, Start-Job的进程内(基于线程)替代方法 Start-ThreadJob-没有 -Credential参数。

    因此,最好的选择是尝试使 Invoke-SqlCmd -Credential参数为您工作,或者找到使用给定用户凭据运行查询的另一种进程内方式。

    后台作业/远程处理/迷你 shell 中对象的序列化和反序列化:

    只要PowerShell跨进程边界封送对象 ,它就会在源头使用基于XML的序列化,并在目标上使用反序列化。

    这是在 PowerShell远程处理的情况下发生的(例如,使用Invoke-Command参数)以及后台作业( -ComputerName )和所谓的小型 shell (当您从PowerShell本身内部通过脚本块调用PowerShell CLI时隐式使用),例如Start-Job

    此反序列化仅针对 powershell.exe { Get-Item / } 中指定的一组有限的已知类型保持类型保真度。即,仅将一组固定类型的实例反序列化为其原始类型。

    模拟所有其他类型的实例:类列表类型变为[System.Collections.ArrayList]实例,字典类型变为[hasthable]实例,其他类型变为无方法(仅属性)自定义对象([pscustomobject]实例),其.pstypenames属性包含odt带有Deserialized.的原始类型名称(例如Deserialized.System.Data.DataTable),以及该类型的基本类型的同等名称(继承体系)。

    此外,非[pscustomobject]实例的对象图的递归深度限于1级别:即,如果输入对象的属性不是字符串或.NET基本类型本身的实例(诸如[int]的类型是单个值本身而不是属性),它们会被其.ToString()表示形式取代(例如,System.IO.DirectoryInfo类型的.Parent属性是另一个System.IO.DirectoryInfo实例,这意味着.Parent属性值会序列化为该实例的.ToString()表示形式,即它的全路径字符串);简而言之:非定制对象使用其立即属性进行序列化,用其.ToString()表示形式替换非字符串和非原始值。
    相比之下,通过 MS-PSRP, the PowerShell Remoting Protocol Specification对CLI XML序列化的明确使用默认为Export-Clixml 的深度。

    根据原始类型,您可能可以手动重建原始类型的实例,但是不能保证。
    (您可以通过在给定的自定义对象上调用2来获得原始类型的全名。)

    但是,根据您的处理需求,原始对象的仿真可能就足够了。

    [1]使用.pstypenames[0] -replace 'Deserialized\.'会生成可用的模拟对象,因为您会得到一个模拟该表的System.DataTable实例,并获得具有System.Collections.ArrayList实例原始属性值的自定义对象。之所以起作用,是因为PowerShell具有内置逻辑,可以将System.DataRow隐式地视为其数据行的数组,而System.DataTable则不适用。

    关于sql-server - Receive-Job返回的意外变量类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59174799/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com