【问题标题】:powershell : pipe get-content to ps1 file with parameterspowershell:管道获取内容到带有参数的ps1文件
【发布时间】:2020-11-20 21:00:59
【问题描述】:

我正在尝试编写一个脚本,该脚本使用 powershell cmdlet get-content tail 并将新行插入到 sql server 表中。我无法获得将尾部通过管道传递到处理表插入的 sqlinsert.ps1 文件的语法。

我正在寻找有关如何将“get-content tail”通过管道传输到 sqlinsert.ps1 文件以执行 sql 数据库插入语句的帮助:

$startTime = get-date
Write-Host "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt"
get-content "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt" -tail 1 -wait  |  & "sqlinsert.ps1" -stmp $("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error" -msg $_
# %  { "$_ read at $(Get-Date -Format "hh:mm:ss")" }

在 sqlinsert.ps1 中:

param ([string]$stmp, [string]$method, [string]$msg ) 
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$serverName';database='$databaseName';User ID = $uid; Password = $pwd;"
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection

$sql = "insert into [tbl_iiserrors] (errstamp, method, msg) values (@stmp , @method, @msg)  " 

。 . .

我得到的错误:

& : 术语“sqlinsert.ps1”未被识别为 cmdlet、函数、脚本文件或可运行的程序。检查拼写 的名称,或者如果包含路径,请验证该路径是 正确并重试。在 C:\Temp\ob\iislog\tst_tail.ps1:3 char:95

  • ... Mdd}" -f (get-date)).txt" -tail 1 -wait | & "sqlinsert.ps1" -stmp $ ...
  •                                               ~~~~~~~~~~~~~~~
    
    • CategoryInfo : ObjectNotFound: (sqlinsert.ps1:String) [], CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException

建议[3,General]:找不到命令sqlinsert.ps1,但是 确实存在于当前位置。 Windows PowerShell 不加载 默认情况下来自当前位置的命令。如果你相信这个 命令,而是键入:“.\sqlinsert.ps1”。请参阅“获取帮助 about_Command_Precedence”了解更多详情。

当我从 powershell 命令运行 sqlinsert.ps1 时,它可以工作: PS c:\temp> .\sqlinsert -stmp 2020-11-20 00:00:00 -method 'eek' -msg 'uh hello'

【问题讨论】:

  • 错误提示在当前目录下找不到文件。尝试使用完整路径:& 'C:\temp\sqlinsert.ps1'
  • 在管道之后,我将其更改为 .\sqlinsert.ps1 -stmp $("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date) ) -method "Error" -msg $_ 它看起来像是在运行,但看起来不像是正确通过?我没有看到任何插入。

标签: powershell


【解决方案1】:

为了将管道输入绑定到参数,您需要用[Parameter] 属性装饰它并指定它接受管道输入,如下所示:

param (
  [string]$stmp,
  [string]$method, 
  [Parameter(ValueFromPipeline = $true)]
  [string]$msg
)

有关如何修改参数行为的更多详细信息,请参阅about_Functions_Advanced_Parameters help file

【讨论】:

  • C:\sqlinsert.ps1 :输入对象不能绑定到命令的任何参数,因为命令不接受管道输入,或者输入及其属性与任何参数不匹配接受管道输入。 + ... 1 - 等待 | .\sqlinsert.ps1 -stmp '2020-11-20 00:00:00' -method '错误...~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (2020-11-20 16:2... s 200 text/html:PSObject) [sqlinsert.ps1], 参数 BindingException + FullyQualifiedErrorId : InputObjectNotBound,sqlinsert.ps1
【解决方案2】:
  • 根据设计,出于安全原因,PowerShell 要求您使用 path - .\sqlinsert.ps1 - 而不是 明确地表明执行位于当前目录中的脚本的意图文件名 - sqlinsert.ps1;这就是错误消息后面的建议试图告诉您的内容。

    • 请注意,如果脚本路径被引用和/或包含变量引用,您只需要 &call operator - 并且 .\sqlinsert.ps1 不需要引用。
  • 您只能使用自动$_ 变量,它表示来自script block ({ ... }) 内管道的当前输入对象,例如传递给ForEach-Object cmdlet 的对象,它调用该块通过管道接收到的每个对象。

  • 关于你的脚本内容:在expandable strings"...")内部,你不能使用@来引用要扩展(插值)的变量;使用正则,$-前缀变量引用或$(...),子表达式运算符来嵌入表达式;此外,您似乎正在将 string 值插入 SQL 表,因此您必须将扩展的变量值包含在嵌入的 '...'

$startTime = get-date
Get-Content "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt" -Tail 1 -Wait |  
 ForEach-Object {
   .\sqlinsert.ps1 -stmp ("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error" -msg $_
 }

使用ForEach-Object 调用的替代方法是将您的脚本修改为直接 从管道接收其-msg 参数,如Mathias' answer 所示,在这种情况下您必须省略脚本调用中的 -msg $_ 参数:

Get-Content ... |
  .\sqlinsert.ps1 -stmp ("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error"

【讨论】:

    猜你喜欢
    • 2010-09-09
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多