Sql-Server

在 T-SQL 中使用帶有參數的 xp_cmdshell 呼叫 powershell 腳本

  • December 23, 2021

對於來自 T_SQL的 Calling powershell 函式,我一直在使用以下參考資料。這是在 SQL Server 2016 上

我需要幫助的元素是在 SQL 中呼叫傳遞參數(文件路徑/文件名/文件副檔名)的 powershell 腳本的格式。ps 腳本對已用於批量上傳的文件進行簡單的重命名和移動。

ps 腳本包含在問題的底部,但我已經獨立於 SQL 測試了該文件,並且它按預期執行

我正在開發的 T-SQL 是

   --Turn on cmd shell may need a sysadmin account
EXEC master.dbo.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE

EXEC master.dbo.sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE

Declare @sqlFilePath nvarchar(255)='"C:\BPA Exports\Change Point 1\Processing\"'
Declare @sqlfilename nvarchar(255)='ExportCP1Data'
Declare @sqlfilext nvarchar(20)='.csv'
Declare @PScmd nvarchar (255)
Set @PScmd='powershell -command "C:\SQL_Powershell\General\MoveFile.ps1" "'+ @sqlFilePath +'" "'+@sqlfilename+'" "'+@sqlfilext+'"'
Print @PScmd
EXEC xp_cmdshell @PScmd


--Turn off cmdshell for safety
EXEC master.dbo.sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE


EXEC master.dbo.sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE

我收到的錯誤資訊

The string is missing the terminator: ".
   + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordEx 
  ception
   + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

NULL

由於這有望最終以遠端呼叫的 usp 結束,因此有人還可以確認 db 使用者的推薦權限。

我正在考慮使用對 ps 腳本的本地位置和文件將從/移到的文件夾具有文件讀/寫權限的 AD 使用者。我目前對 SQL usp 的構想是使用類似的東西

CREATE PROCEDURE Utility.DoSomethingPotentiallyScary
WITH EXECUTE AS OWNER
AS

除非有更好的方法?

為此的powershell腳本如下

param
(
[String] $location,
[String] $filename,
[String] $filext

) 


Function RenameMoveFile($locationPath, $fileName, $extension, $archiveFolder)
{
   $date =Get-Date -Format "yyyyMMdd_HHmmss"
   $old = $locationPath + $fileName + $extension
   $new = $locationPath + $fileName + "_" + $date + $extension
   $archiveFolder = $locationPath + $archiveFolder + "\"
   Rename-Item $old $new
   Move-Item $new $archiveFolder
}
## This is the only part that we'd edit  
RenameMoveFile -locationPath $location  -fileName "ExportCP1Data" -extension ".csv" -archiveFolder "Archive"

更新我已經做了一些測試,我相信是文件路徑中的空白導致了問題。我已將其放入 ISE 進行測試,如果我在 ps 文件中硬編碼文件路徑,則該命令有效。但是,當我在 ISE 中嘗試此操作時, powershell "C:\SQL_Powershell\General\MoveFile.ps1" "C:\BPA Exports\ChangePoint1\Processing" 我得到以下消息(注意 \ 定位)

‘C:\BPA\Exports\ChangePoint1\Processing’ 不存在。

任何人都可以建議轉義此文件路徑的方法嗎?

謝謝

行。原來這既不是 CMD.EXE 解析也不是 PowerShell 解析。相反,它是從作業系統解析命令行參數的規則,記錄在這裡。

前面有反斜杠 (") 的雙引號被解釋為文字雙引號 (")。

主函式和命令行參數

這在此處的 Powershell 停靠點中進行了解釋:about_Parsing:傳遞包含引號字元的參數

因此,powershell 腳本的第一個參數變為:

C:\BPA Exports\Change Point 1\Processing" -filename ExportCP1Data -filext .csv 

其他兩個為空。所以當傳遞一個以你結尾的命令行參數時,\"你必須加倍\或省略它。所以像:

Declare @sqlFilePath nvarchar(255)='C:\BPA Exports\Change Point 1\Processing'
Declare @sqlfilename nvarchar(255)='ExportCP1Data'
Declare @sqlfilext nvarchar(20)='.csv'
Declare @PScmd nvarchar (255)
Set @PScmd='powershell -File "C:\SQL_Powershell\General\MoveFile.ps1" -location "'+@sqlFilePath+'" -filename "'+@sqlfilename+'" -filext "'+@sqlfilext+'" '

Print @PScmd
EXEC xp_cmdshell @PScmd

引用自:https://dba.stackexchange.com/questions/305284