索引为[-1]的数组

时间:2019-08-07 10:21:54

标签: powershell

我有一个函数可以给我一些Get-WinEvent的结果,效果很好。使用它作为另一个函数的输入并尝试迭代该数组,我注意到,该数组的构建方式如下:

-1
   ProviderName: Microsoft-Windows-FailoverClustering

TimeCreated                     Id LevelDisplayName Message
-----------                     -- ---------------- -------
07.08.2019 01:14:23           1538 Information      The backup operation for the cluster configuration data completed successfully. The snapshot ID is '47cda23b-c446-43dc-9b5d-dfdbaca2be8c'.

很显然,我不想拥有“ -1”和“ ProviderName:Microsoft-Windows-FailoverClustering”。

如何正确处理?

function Get-ClusterLogEntries {
    Param(
        [Parameter(Position=0, Mandatory=$true)]
        [int] $server_id,
        [Parameter(Position=1, Mandatory=$true)]
        [string] $clusterName
    )

    $conn = New-Object System.Data.SqlClient.SqlConnection
    $conn.ConnectionString = "Server=xxxx\yyyy;Database=zzzz;Integrated Security=True"
    $conn.Open() | Out-Null
    $cmd = New-Object System.Data.SqlClient.SqlCommand("extern.xxxx", $conn)

    $cmd.CommandType = [System.Data.CommandType]::StoredProcedure

    $cmd.Parameters.Add("@server_id", [System.Data.SqlDbType]::int) | Out-Null
    $cmd.Parameters['@server_id'].Direction = [System.Data.ParameterDirection]::Input
    $cmd.Parameters['@server_id'].Value = $server_id #local server

    $cmd.Parameters.Add("@clusterName", [System.Data.SqlDbType]::VarChar, 10) | Out-Null
    $cmd.Parameters['@clusterName'].Direction = [System.Data.ParameterDirection]::Input
    $cmd.Parameters['@clusterName'].Value = $clusterName

    $cmd.Parameters.Add("@timeCreated", [System.Data.SqlDbType]::DateTime) | Out-Null
    $cmd.Parameters['@timeCreated'].Direction = [System.Data.ParameterDirection]::Output

    $cmd.ExecuteNonQuery()
    $conn.Close()
    $conn.Dispose()

    $timeCreated = $cmd.Parameters["@timeCreated"].Value
    $startdatum = $timeCreated
    return [array]$clusterLogEntries = Get-WinEvent -FilterHashTable @{
        logname   = 'Microsoft-Windows-FailoverClustering/Operational';
        starttime = $startdatum
    }
}

和使用功能:

function Write-ClusterLog {
    Param(
        [Parameter(Position=0, Mandatory=$true)]
        [int] $server_id,
        [Parameter(Position=1, Mandatory=$true)]
        [string] $computer,
        [Parameter(Position=2, Mandatory=$true)]
        [string] $clusterName,
        [Parameter(Position=3, Mandatory=$true)]
        [array] $clusterLogs
    )

    $conn = New-Object System.Data.SqlClient.SqlConnection
    $conn.ConnectionString = "Server=xxxx;Database=yyyyy;Integrated Security=True"
    $conn.Open() | Out-Null
    $cmd = New-Object System.Data.SqlClient.SqlCommand("extern.zzzzzz", $conn)

    $cmd.CommandType = [System.Data.CommandType]::StoredProcedure

    foreach ($clusterLog in $clusterLogs) {
        $cmd.Parameters.Add("@server_id", [System.Data.SqlDbType]::int) | Out-Null
        $cmd.Parameters['@server_id'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@server_id'].Value = $server_id

        $cmd.Parameters.Add("@servername", [System.Data.SqlDbType]::VarChar, 10) | Out-Null
        $cmd.Parameters['@servername'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@servername'].Value = $computer #local server

        $cmd.Parameters.Add("@clustername", [System.Data.SqlDbType]::VarChar, 10) | Out-Null
        $cmd.Parameters['@clustername'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@clustername'].Value = $clusterName

        $cmd.Parameters.Add("@timecreated", [System.Data.SqlDbType]::DateTime) | Out-Null
        $cmd.Parameters['@timecreated'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@timecreated'].Value = $clusterLog.TimeCreated

        $cmd.Parameters.Add("@eventID", [System.Data.SqlDbType]::int) | Out-Null
        $cmd.Parameters['@eventID'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@eventID'].Value = $clusterLog.ID

        $cmd.Parameters.Add("@levelDisplayName", [System.Data.SqlDbType]::varchar, 50) | Out-Null
        $cmd.Parameters['@levelDisplayName'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@levelDisplayName'].Value = $clusterLog.LevelDisplayName

        $cmd.Parameters.Add("@message", [System.Data.SqlDbType]::VarChar, 4000) | Out-Null
        $cmd.Parameters['@message'].Direction = [System.Data.ParameterDirection]::Input
        $cmd.Parameters['@message'].Value = $clusterLog.Message

        $cmd.ExecuteNonQuery()
        $cmd.Parameters.Clear()
    }
    $conn.Close()
    $conn.Dispose()
}

2 个答案:

答案 0 :(得分:2)

此声明:

$cmd.ExecuteNonQuery()

return an integer将指示受INSERT或UPDATE操作影响的行数-对于非修改操作,它将返回 -1

将其更改为:

[void]$cmd.ExecuteNonQuery()
# or
$cmd.ExecuteNonQuery() |Out-Null

答案 1 :(得分:2)

@ MathiasR.Jessen的答案对于-1的来源是正确的。

“提供者名称:Microsoft-Windows-FailoverClustering”来自Get-WinEvent返回(EventLogRecord)类型的对象的默认输出格式。这与输出Get-ChildItem时看到“目录:X:\ foo”的原因相同。

要修复此问题,您需要选择字段而不是返回整个对象:

Get-WinEvent -FilterHashTable @{
        logname   = 'Microsoft-Windows-FailoverClustering/Operational';
        starttime = $startdatum
} | Select-Object TimeCreated, Id, LevelDisplayName, Message

如果需要所有属性,可以改为指定Select-Object *,但是由于要显示的属性数量,您将获得列表输出。

如果您需要EventLogRecord类上的方法,则不能这样做,因为带有Select-Object参数的-Property会将对象类型更改为PSCustomObject。您正在从对象的基类中展开对象。如果需要方法,并且需要不显示提供程序名称,则必须修改Types.ps1xml文件,以描述EventLogRecord类型的对象的格式。您几乎可以肯定不想这样做。参见Get-Help about_Types.ps1xml