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::
Я не рекомендую файловые ресурсы в решениях автоматизации... но у меня не было выбора. Надеюсь, поможет.