1

使用 invoke-sqlcmd 将行插入表时发生了一个奇怪的错误。如果执行一次,整个脚本可以完美运行,但如果我再次运行它,它会失败并显示错误消息:Get-ChildItem:无法调用方法。提供者不支持使用过滤器。我测试了代码并注释掉了invoke-sqlcmd行,并且可以多次运行它而没有任何错误。我将invoke-sqlcmd放在一个函数中,它仍然出错,第一次成功运行后,它也会在PS命令行失败。

Clear-Host
$ErrorActionPreference = 'Stop'

function Update-SQL
{
    invoke-sqlcmd -query $strSQLInsert -server SXLSV-LEAPDBD1 -database DTCS_DV
}

$files = Get-ChildItem '\\pcslog1011\dtcs\ContractEmailNotes\' -Filter '*.txt' | Where-Object {$_.LastWriteTime -ge '08/22/2016 00:00:00' -and $_.LastWriteTime -le '08/22/2016 23:59:59'} | sort-object -Descending

for ($i=0; $i -lt $files.Count; $i++) 
{
    $SNAC_CNTR_ID = $files[$i].BaseName.Substring(0,6)
    $SNAC_MODIFIED = '{0:yyyy-MM-dd HH:mm:ss}' -f ($files[$i].LastWriteTime)

    $reader = [System.IO.File]::OpenText($files[$i].FullName)
    $lineCnt = 0
    $SNAC_ACTION = ''
    for() 
    {
        $lineCnt += 1 
        $line = $reader.ReadLine()
        if ($line -eq $null) {break}
        if ($lineCnt -eq 4)
        {
            if ($line.Contains('AMENDED') -eq $True)
            {
                $SNAC_ACTION = 'AMENDED'
            }
            elseif ($line.Contains('DEAL CHANGED') -eq $True)
            {
                $SNAC_ACTION = 'CHANGED'
            }
            else
            {
                $SNAC_ACTION = 'NEW'
            }
        }
    }
    $reader.Close()

    write-host $SNAC_CNTR_ID $SNAC_MODIFIED $SNAC_ACTION

    $strSQLInsert = "INSERT INTO CQT_CONTRACT_SOX_NAC_LIST (SNAC_CNTR_ID, SNAC_MODIFIED, SNAC_ACTION, SNAC_UPDATED_BY, SNAC_UPDATED_ON) VALUES ('" + $SNAC_CNTR_ID + "', '" + $SNAC_MODIFIED + "', '" + $SNAC_ACTION + "', Default, Default)"

    Update-SQL $strSQLInsert
}

exit
4

3 回答 3

5

我知道这是一个相当古老的线程,但我遇到了一个类似的问题,导致我访问了这个页面。以下是为我解释和解决问题的链接。

PowerShell Invoke-Sqlcmd 切换到 sqlps 会话
卡在 Powershell sqlserver 中

简短的回答

默认情况下,SQLPS 提供程序不识别 UNC 路径。您可以使用特定文件系统提供程序为 UNC 路径添加前缀:

Get-ChildItem Microsoft.PowerShell.Core\FileSystem::\\pcslog1011\dtcs\ContractEmailNotes\
-Filter '*.txt'

或在加载 SQLPS 模块后将工作目录切换回默认值,方法是将其添加到脚本顶部:

Push-Location
Import-Module SQLPS -DisableNameChecking
Pop-Location

长答案

似乎这个问题是由于 PowerShell 将工作目录从默认切换到 SQLPS 提供程序的工作目录以及 SQLPS 提供程序无法识别 UNC 路径(没有一些鼓励)。

因此,正常的 PowerShell 提示符看起来像这样:

PS C:\Users\foobar>

当您在 SQLPS 提供程序的目录结构中工作时,它将看起来像下面的提示(更多关于这意味着什么

PS SQLSERVER:\>

无论如何,脚本第一次调用 Get-ChildItem 很可能是从默认 PowerShell 工作目录的上下文(理解 UNC 路径的地方)中完成的。但是,调用 Invoke-Sqlcmd 会加载 SQLPS 模块,该模块会将工作目录更改为无法识别 UNC 路径的提供程序的工作目录。因此,下次调用 Get-ChildItem 时,它是从提供程序的目录结构中完成的,从而引发错误。这个问题实际上与过滤器支持没有任何关系。

其他人发现的两种方法是在 UNC 路径前加上文件系统提供程序,以便 SQLPS 可以解析它(source):

Get-ChildItem Microsoft.PowerShell.Core\FileSystem::\\pcslog1011\dtcs\ContractEmailNotes\ -Filter '*.txt'

或者在 SQLPS 模块加载后切换回默认工作目录。这可能最好通过在脚本开头显式加载 SQLPS 提供程序并在前后添加 Push/Pop-Location cmdlet 来完成(无需对原始脚本进行其他更改)。

Push-Location
Import-Module SQLPS -DisableNameChecking
Pop-Location

最后要注意的两件事。首先,我在不同的操作系统版本、补丁级别和 PowerShell 版本上针对大约 100 台服务器运行了我的代码。我只在一些运行 PowerShell 5.1 的服务器上看到过这个问题。其他 5.1 服务器都很好。

其次,这整个事件显然可以通过简单地使用应该替换 SQLPS 的更新的 SQLServer 提供程序来避免。

于 2018-05-10T22:16:28.780 回答
0

发布的答案帮助我理解了问题,但不够具体,无法提供适用于我的环境的解决方案。这就是为我解决问题的方法:

$latestFile = Get-ChildItem Microsoft.PowerShell.Core\FileSystem::$dir | where-Object {$_.Name.ToString() -like $databasePattern} | 排序对象 LastAccessTime -降序 | 选择对象-First 1

ToString() 是成功所必需的。完整的问题陈述、调试和解决方案发布在https://social.msdn.microsoft.com/Forums/sqlserver/en-US/f28d9276-7aad-464c-823e-b9b4637856e1/powershell-script-using-getchilditem- works-with-invokesqlcmd-when-called-from-visual-studio-code?forum=sqlkjmanageability&prof=required我提供的链接仅用于研究和归属目的。根据 StackOverflow 想要完整解决方案而不是链接的惯例,我发布的是针对我的环境中所表现的问题的完整解决方案。

于 2019-06-15T21:01:47.647 回答
0

这可能对您有帮助,也可能对您没有帮助。尝试在 SQL 代理作业中运行我的脚本时,我遇到了同样的错误。它适用于我的帐户和代理正在运行的服务帐户,但在我为其读取的 UNC 文件路径添加前缀之前拒绝作为工作工作

Microsoft.PowerShell.Core\FileSystem::

我不推荐自动化解决方案中的文件共享......但别无选择。希望能帮助到你。

于 2017-01-18T17:22:39.770 回答