PowerShell invoke-sqlcmd Get-ChildItem: Невозможно вызвать метод. Поставщик не поддерживает использование фильтров

У меня странная ошибка, возникающая при использовании 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

2 ответа

Я знаю, что это довольно старая тема, но я столкнулся с похожей проблемой, которая привела меня на эту страницу. Вот ссылки, которые объяснили и решили проблему для меня.

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 мог его проанализировать ( источник):

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

Или переключитесь обратно в рабочий каталог по умолчанию после загрузки модуля SQLPS. Это, возможно, лучше всего сделать путем явной загрузки поставщика SQLPS в начале сценария и добавления командлетов Push/Pop-Location до и после (никаких других изменений в исходном сценарии не требуется).

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

Две последние вещи, которые стоит отметить. Во-первых, я запустил свой код для примерно 100 серверов на разных версиях ОС, уровнях исправлений и версиях PowerShell. Я видел эту проблему только на некоторых серверах под управлением PowerShell 5.1. Другие серверы 5.1 были в порядке.

Во-вторых, всего этого можно избежать, просто используя новый поставщик SQLServer, который должен заменить SQLPS.

Опубликованные ответы помогли мне понять проблему, но не были достаточно конкретными, чтобы предложить решение, работающее в моей среде. Вот что решило для меня проблему:

$latestFile = Get-ChildItem Microsoft.PowerShell.Core\FileSystem::$dir | где-Object {$_.Name.ToString() -like $databasePattern} | Sort-Object LastAccessTime -Descending | Select-Object -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 Я предоставил ссылку только в целях исследования и установления авторства. В соответствии с соглашением Stackru о желании получить полные решения вместо ссылок, то, что я опубликовал, было полным решением проблемы, проявленной в моей среде.

Это может или не может помочь вам. У меня была та же ошибка при попытке запустить мой скрипт в задании агента SQL. Это будет нормально работать для моей учетной записи и учетной записи службы, под которой работал агент, но отказывался работать как задание, пока я не поставил префикс пути к файлу UNC, с которым он читал

Microsoft.PowerShell.Core\FileSystem::

Я не рекомендую файловые ресурсы в решениях автоматизации... но у меня не было выбора. Надеюсь, поможет.

Другие вопросы по тегам