You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Import-Csv调用Set-LogonHours函数报错的问题排查

解决Set-LogonHours参数验证错误

问题场景

尝试通过Import-Csv调用Set-LogonHours设置AD用户登录时间,执行脚本如下:

Import-Csv .\data.csv | % {
    Set-LogonHours -Identity $_.user -TimeIn24Format @($_.time) -Monday -Tuesday -Wednesday -Thursday -NonSelectedDaysare NonWorkingDays
}

错误信息

Set-LogonHours : Cannot validate argument on parameter 'TimeIn24Format'. The 1234567 argument is greater than the maximum allowed range of 23. Supply an
argument that is less than or equal to 23 and then try the command again.

CSV数据

"user","TimeIn24Format"
"testvpn","1,2,3"

Set-LogonHours函数代码

Function Set-LogonHours {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $True)]
        [ValidateRange(0, 23)]
        $TimeIn24Format,
        [Parameter(Mandatory = $True,
            ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True, 
            Position = 0)]$Identity,
        [Parameter(Mandatory = $False)]
        [ValidateSet("WorkingDays", "NonWorkingDays")]$NonSelectedDaysare = "NonWorkingDays",
        [Parameter(Mandatory = $false)][switch]$Sunday,
        [Parameter(Mandatory = $false)][switch]$Monday,
        [Parameter(Mandatory = $false)][switch]$Tuesday,
        [Parameter(Mandatory = $false)][switch]$Wednesday,
        [Parameter(Mandatory = $false)][switch]$Thursday,
        [Parameter(Mandatory = $false)][switch]$Friday,
        [Parameter(Mandatory = $false)][switch]$Saturday
    )

    Process {
        $FullByte = New-Object "byte[]" 21
        $FullDay = [ordered]@{}
        0..23 | foreach { $FullDay.Add($_, "0") }
        $TimeIn24Format.ForEach({ $FullDay[$_] = 1 })
        $Working = -join ($FullDay.values)
        Switch ($PSBoundParameters["NonSelectedDaysare"]) {
            'NonWorkingDays' { $SundayValue = $MondayValue = $TuesdayValue = $WednesdayValue = $ThursdayValue = $FridayValue = $SaturdayValue = "000000000000000000000000" }
            'WorkingDays' { $SundayValue = $MondayValue = $TuesdayValue = $WednesdayValue = $ThursdayValue = $FridayValue = $SaturdayValue = "111111111111111111111111" }
        }
        Switch ($PSBoundParameters.Keys) {
            'Sunday' { $SundayValue = $Working }
            'Monday' { $MondayValue = $Working }
            'Tuesday' { $TuesdayValue = $Working }
            'Wednesday' { $WednesdayValue = $Working }
            'Thursday' { $ThursdayValue = $Working }
            'Friday' { $FridayValue = $Working }
            'Saturday' { $SaturdayValue = $Working }
        }
        $AllTheWeek = "{0}{1}{2}{3}{4}{5}{6}" -f $SundayValue, $MondayValue, $TuesdayValue, $WednesdayValue, $ThursdayValue, $FridayValue, $SaturdayValue
        # Timezone Check
        if ((Get-TimeZone).baseutcoffset.hours -lt 0) {
            $TimeZoneOffset = $AllTheWeek.Substring(0, 168 + ((Get-TimeZone).baseutcoffset.hours))
            $TimeZoneOffset1 = $AllTheWeek.SubString(168 + ((Get-TimeZone).baseutcoffset.hours))
            $FixedTimeZoneOffSet = "$TimeZoneOffset1$TimeZoneOffset"
        }
        if ((Get-TimeZone).baseutcoffset.hours -gt 0) {
            $TimeZoneOffset = $AllTheWeek.Substring(0, ((Get-TimeZone).baseutcoffset.hours))
            $TimeZoneOffset1 = $AllTheWeek.SubString(((Get-TimeZone).baseutcoffset.hours))
            $FixedTimeZoneOffSet = "$TimeZoneOffset1$TimeZoneOffset"
        }
        if ((Get-TimeZone).baseutcoffset.hours -eq 0) {
            $FixedTimeZoneOffSet = $AllTheWeek
        }
        $i = 0
        $BinaryResult = $FixedTimeZoneOffSet -split '(\d{8})' | Where { $_ -match '(\d{8})' }
        Foreach ($singleByte in $BinaryResult) {
            $Tempvar = $singleByte.tochararray()
            [array]::Reverse($Tempvar)
            $Tempvar = -join $Tempvar
            $Byte = [Convert]::ToByte($Tempvar, 2)
            $FullByte[$i] = $Byte
            $i++
        }
        Set-ADUser  -Identity $Identity -Replace @{logonhours = $FullByte }                                   
    }
    
    end {
        Write-Output "All Done :)"
    }
}

问题原因

Import-Csv读取CSV中的TimeIn24Format字段时,会将其解析为字符串类型(如"1,2,3")。直接使用@($_.time)会把整个字符串作为数组的单个元素传入TimeIn24Format参数,PowerShell尝试将该字符串转换为数字时会忽略逗号,得到1234567,超出参数[ValidateRange(0,23)]的限制范围,触发验证错误。

解决方案

方法1:修改调用脚本

将CSV中读取的逗号分隔字符串拆分为整数数组后传入参数:

Import-Csv .\data.csv | % {
    $timeArray = $_.TimeIn24Format -split ',' | ForEach-Object { [int]$_ }
    Set-LogonHours -Identity $_.user -TimeIn24Format $timeArray -Monday -Tuesday -Wednesday -Thursday -NonSelectedDaysare NonWorkingDays
}

方法2:修改函数以支持直接处理逗号分隔字符串

如果希望函数能直接接受CSV中的字符串格式输入,可修改函数的参数定义和处理逻辑:

  1. 修改TimeIn24Format参数,添加自定义验证脚本:
[Parameter(Mandatory = $True)]
[ValidateScript({
    # 处理逗号分隔字符串或整数数组
    if ($_ -is [string]) {
        $splitValues = $_ -split ',' | ForEach-Object { [int]$_ }
        $splitValues | ForEach-Object { if ($_ -lt 0 -or $_ -gt 23) { throw "值必须在0-23之间" } }
        $true
    } elseif ($_ -is [array]) {
        $_ | ForEach-Object { if ($_ -lt 0 -or $_ -gt 23) { throw "值必须在0-23之间" } }
        $true
    } else {
        throw "参数必须是逗号分隔字符串或整数数组"
    }
})]
$TimeIn24Format,
  1. 在Process块开头添加字符串转换逻辑:
Process {
    # 处理逗号分隔字符串转为整数数组
    if ($TimeIn24Format -is [string]) {
        $TimeIn24Format = $TimeIn24Format -split ',' | ForEach-Object { [int]$_ }
    }
    # 原Process块剩余代码...
}

修改后,可直接使用原调用脚本,无需额外处理数组转换。

内容的提问来源于stack exchange,提问作者December Pandora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 23:24:57