问题
I have a strange error occurring when using the invoke-sqlcmd to insert rows into a table. The entire script works perfectly if executed one time, but if I run it a second time, it fails with the error message: Get-ChildItem : Cannot call method. The provider does not support the use of filters. I tested the code and commented out the invoke-sqlcmd line, and can run it multiple times without any errors. I put the invoke-sqlcmd in a function and it still errors, and after the first successful run it will fail at the PS command line too.
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
回答1:
I know this is a rather old thread, but I ran into a similar issue which led me to this page. Here are the links that explained and resolved the issue for me.
PowerShell Invoke-Sqlcmd switches into sqlps session
Stuck in Powershell sqlserver
Short answer
The SQLPS provider does not recognize UNC paths by default. You can either prefix the UNC path with a specific file system provider:
Get-ChildItem Microsoft.PowerShell.Core\FileSystem::\\pcslog1011\dtcs\ContractEmailNotes\
-Filter '*.txt'
or switch your working directory back to the default after the SQLPS module is loaded by adding this to the top of your script:
Push-Location
Import-Module SQLPS -DisableNameChecking
Pop-Location
Long Answer
It seems the issue is due to a combination of PowerShell switching the working directory from the default to that of the SQLPS provider in addition to the fact that the SQLPS provider doesn't recognize UNC paths (without some encouragement).
So where the normal PowerShell prompt looks something like this:
PS C:\Users\foobar>
It will instead look like the prompt below when you are working in the directory structure of the SQLPS provider (more on what this means here):
PS SQLSERVER:\>
In any event, the first time the script calls Get-ChildItem it is likely done so from the context of the default PowerShell working directory (where UNC paths are understood). However, calling Invoke-Sqlcmd loads the SQLPS module which changes the working directory to that of the provider which does not recognize UNC paths. So the next time Get-ChildItem is called, it is done so from within the directory structure of the provider, raising an error. The issue doesn't actually have anything to do with filter support.
Two ways others have found around this are to either prefix the UNC path with a file system provider so that SQLPS can parse it (source):
Get-ChildItem Microsoft.PowerShell.Core\FileSystem::\\pcslog1011\dtcs\ContractEmailNotes\ -Filter '*.txt'
Or switch back to the default working directory after the the SQLPS module loads. This is perhaps best done by explicitly loading the SQLPS provider at the beginning of your script and adding the Push/Pop-Location cmdlets before and after (no other changes required to the original script).
Push-Location
Import-Module SQLPS -DisableNameChecking
Pop-Location
Two final things to note. First, I've run my code against about 100 servers on different OS versions, patch levels and PowerShell versions. I've only seen this issue on some servers running PowerShell 5.1. Other 5.1 servers were fine.
Second, this whole affair can apparently be avoided by simply by using the newer SQLServer provider that is supposed to replace SQLPS.
回答2:
This may or may not help you. I had the same error when trying to run my script in a SQL Agent job. It would work fine for my account and the service account the agent was running under but refused to work as a job until I prefixed the UNC file path it was reading with
Microsoft.PowerShell.Core\FileSystem::
I don't recommend file shares in automation solutions... but had no choice. Hope it helps.
回答3:
The answers posted helped me to understand the problem but were not specific enough to provide a solution that worked in my environment. This is what solved the problem for me:
$latestFile = Get-ChildItem Microsoft.PowerShell.Core\FileSystem::$dir | where-Object {$_.Name.ToString() -like $databasePattern} | Sort-Object LastAccessTime -Descending | Select-Object -First 1
The ToString() was required for success. The complete problem statement, debugging, and solution were posted at 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 I provided the link only for research and attribution purposes. In accordance with StackOverflow's convention of wanting complete solutions instead of links, what I posted was the complete solution to the problem as manifested in my environment.
来源:https://stackoverflow.com/questions/39102234/powershell-invoke-sqlcmd-get-childitem-cannot-call-method-the-provider-does-n