PowerShell 与 CMD 相同的命令有不同的结果

PowerShell vs CMD same command having different results

Get-WinEvent 命令的以下命令有效:

PowerShell:

Get-WinEvent -FilterHashtable @{Logname=’application’;StartTime="2018-04-20 00:00:00";EndTime="2018-04-20 23:59:59"}

命令:

powershell.exe -noprofile -command "Get-WinEvent -FilterHashtable @{Logname=\"application\";StartTime=\"2018-04-18 17:42:56\";EndTime=\"2018-04-19 17:43:01\"}"

我面临的问题是,当我尝试通过管道传输结果以获得特定的 RecordID 时,它在 PowerShell 中有效:

Get-WinEvent -FilterHashtable @{Logname=’application’;StartTime="2018-04-20 00:00:00";EndTime="2018-04-20 23:59:59"} | ? {$_.RecordId -eq 293116} | Select Message

当我尝试将相同的内容添加到我的 cmd 调用时,returns 没有结果:

powershell.exe -noprofile -command "Get-WinEvent -FilterHashtable @{Logname=\"application\";StartTime=\"2018-04-18 17:42:56\";EndTime=\"2018-04-19 17:43:01\"} | ? {$RecordId -eq 293116} | Select Message"

我已经尝试用 Where-Object-property 替换 ? 以排除 CMD 字符被误解的问题。我觉得我在这里遗漏了一些明显的东西。

不要转义所有内部双引号,而是使用单引号:

powershell.exe -nop -c "Get-WinEvent -FilterHashtable @{Logname=’application’;StartTime=’2018-04-18 17:42:56’;EndTime=’2018-04-19 17:43:01’} | ? {$RecordId -eq 293116} | Select Message"

除了这里不存在的 RecordId,它有效。

我能够解决这个问题。

因为我从 SQL 转到 CMD 再到 PowerShell,所以有些字符的解释方式出乎我的意料,因此没有返回任何消息。最终我能够编写这个存储过程,它将使用 xp_cmdshell 从 SQL 主机调用特定机器,这将为您提供特定时间范围内的事件查看器日志。

我还覆盖了记录数以避免它 运行 很长一段时间。这是存储过程的内容:

        if object_id('tempdb..#result') IS NOT NULL
        drop table #result
    create table #result
        ([ID] int
        ,[Timegenerated] datetime
        ,[EntryType] varchar(max)
        ,[Source] varchar(max)
        ,[Message] nvarchar(max)
        )

    if object_id('tempdb..#temp') IS NOT NULL
        drop table #temp
    create table #temp
        ([output] nvarchar(max))

    Declare @command nvarchar(1000)
    Set @command = 'powershell.exe -noprofile -command "Get-WinEvent -FilterHashtable @{Logname=''application'';StartTime='''+@StartTime+''';EndTime='''+@EndTime+'''} -MaxEvents ' + @topEvents + '| % {\"$($_.RecordId)`t$($_.TimeCreated)`t$($_.ProviderName)`t$($_.LevelDisplayName)\"}"'

    Insert Into #temp
        exec xp_cmdshell @command

    Delete from #temp where [output] is null

    Declare @fullstring nvarchar(max)
    While (Select COUNT(*) from #temp) > 0
    BEGIN
        Select TOP 1 @fullstring = [output] from #temp
        Insert Into #result
        SELECT TOP 1 dbo.F_ExtractSubString([output], 1, '    ') AS ID,
                dbo.F_ExtractSubString([output], 2, '    ') AS TimeGenerated,
                dbo.F_ExtractSubString([output], 3, '    ') AS EntryType,
                dbo.F_ExtractSubString([output], 4, '    ') AS Source,
                Null
        FROM   #temp
        Delete From #temp where [output] = @fullstring
    END

    Declare @IDSearch nvarchar(100), @messageString NVARCHAR(MAX)
    While (Select COUNT(*) from #result Where #result.[Message] is null) > 0
    BEGIN
        Select Top 1 @IDSearch = ID from #result Where #result.[Message] is null

        Set @command = 'powershell.exe -noprofile -command "Get-WinEvent -FilterHashtable @{Logname=''application'';StartTime='''+@StartTime+''';EndTime='''+@EndTime+'''} | ? {$_.RecordId -eq ' + @IDSearch + '} | % {\"$($_.Message)`r`n\"}'

        Insert Into #temp
            exec xp_cmdshell @command

        Set @messageString = STUFF(
                            (   SELECT ',' + CONVERT(NVARCHAR(Max), [output])
                                FROM #temp
                                FOR xml path('')
                            )
                            , 1
                            , 1
                            , '')

        Update #result Set [Message] = @messageString Where ID = @IDSearch

        TRUNCATE TABLE #temp
    END

    Select * from #result