AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79573358
Accepted
9072997
9072997
Asked: 2025-04-14 22:19:21 +0800 CST2025-04-14 22:19:21 +0800 CST 2025-04-14 22:19:21 +0800 CST

Qual é o tempo de vida de um ValidateScript no PowerShell?

  • 772

O PowerShell oferece suporte a scripts de validação para variáveis. Isso é mais comumente usado para validar parâmetros de função, mas pode ser aplicado a qualquer variável. Esses scripts de validação são executados sempre que o valor da variável é alterado.

# create a variable with a validation script
[ValidateScript({
    if (-not ($_.Length -in @(8, 16, 24))) {
        Write-Host 'Validate Failed'
        throw "Value '$_' has invalid length: $($_.Length)"
    } else {
        Write-Host 'Validate Success'
    }
    $true
})][System.String]$MyValidatedArg = "a" * 8 # prints "Validate Success"

# Each one of these will trigger the validation script
Write-Host "Several valid assignments..."
$MyValidatedArg = "b" * 8 # prints "Validate Success"
$MyValidatedArg = "b" * 8 # prints "Validate Success"
$MyValidatedArg = "b" * 16 # prints "Validate Success"
$MyValidatedArg = "b" * 24 # prints "Validate Success"

Se eu atribuísse um valor inválido à variável, isso geraria uma exceção

$MyValidatedArg = "foo" # throws an exception

Estranhamente, consigo ignorar o script de validação se eu especificar novamente a restrição de tipo durante a atribuição. Sei que "simplesmente não faça isso" é uma opção, mas o ponto principal da minha pergunta é: por que isso funciona?

[System.String]$MyValidatedArg = "123456789" # works even though this value is invalid

A princípio, pensei que fosse apenas um sombreamento de variáveis. Tipo, talvez eu estivesse criando uma segunda variável, objeto ou algo assim, especificando a restrição de tipo uma segunda vez. Tentei capturar uma referência à variável para ver se ela manteria o script de validação. Não mantém, mas não estou muito familiarizado com os detalhes internos do PowerShell para saber se este é um teste válido.

# create a reference and assign through the reference
Write-Host "Assigning through reference..."
$refToParameter = [ref] $MyValidatedArg
$refToParameter.Value = "c" * 24 # prints "Validate Success"
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"

# the reference and the variable are linked
# Assignments to either trigger the validation script
Write-Host "Assigning through normal variable again..."
$MyValidatedArg = "d" * 24 # prints "Validate Success"
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"

# This works, which is odd
Write-Host "Assigning with [System.String]..."
[System.String]$MyValidatedArg = "123456789" # invalid, nothing printed
Write-Host " No exceptions yet!"

# I thought this was some sort of variable shadowing thing, but the reference shows the new value too
Write-Host "The link between the variable and the reference is still there..."
$MyValidatedArg = "e" * 8 # valid, nothing printed
Write-Host " Read via variable: $MyValidatedArg"
Write-Host " Read via reference: $($refToParameter.Value)"

# and now we appear to have killed the validation script
Write-Host "Regular invalid assignment..."
$MyValidatedArg = "123456789" # invalid, nothing printed
Write-Host " It works now for some reason"
powershell
  • 1 1 respostas
  • 53 Views

1 respostas

  • Voted
  1. Best Answer
    Santiago Squarzon
    2025-04-15T00:15:17+08:002025-04-15T00:15:17+08:00

    Da perspectiva interna, quando você cria uma nova variável, isso significa que um PSVariableobjeto é adicionado ao Variable:provedor , pequeno exemplo:

    $myvar = 123
    # `Get-Variable myVar` also works here and yields the same output
    Get-Item Variable:myVar | Select-Object *
    

    O PSVariableobjeto pode conter .Attributeselementos que determinarão seu comportamento, por exemplo, na atribuição, pode ser transformação e validação . Se você quiser ver uma lista dos atributos existentes que podem ser adicionados, você pode fazer isso (observe que esta lista não está completa, você pode criar seus próprios atributos por herança):

    [psobject].Assembly.GetTypes() | Where-Object {
        -not $_.IsAbstract -and $_.IsPublic -and
        $_.IsSubclassOf([System.Management.Automation.Internal.CmdletMetadataAttribute]) -and
        $_.GetConstructors()
    }
    

    Com essas informações básicas, agora podemos dizer que o motivo pelo qual você pode ignorar a validação é porque a atribuição de restrição de tipo está removendo o ValidateScriptfrom PSVariableobject , e podemos provar que esse é o caso seguindo estas etapas:

    # New var is added to the Provider
    [ValidateScript({ $true })] [string] $MyValidatedArg = 1
    # Get the PSVariable object
    $psVar = Get-Variable MyValidatedArg
    # We can see that the attribute is added to the Attributes collection
    $psVar.Attributes | Where-Object { $_ -is [ValidateScript] }
    # After a new constraint assignment
    [string] $MyValidatedArg = 1
    # We can see that the attribute was removed from the original object
    $psVar.Attributes | Where-Object { $_ -is [ValidateScript] }
    

    Observe que a atribuição de restrição de tipo é apenas um dos muitos métodos para remover o atributo; por exemplo, isso também funcionaria!

    [ValidateScript({ if ($_ -gt 1) { return $false }; $true })] [int] $MyValidatedArg = 1
    # Check if validation works (Should fail on assignment)
    $MyValidatedArg = 2
    # Get the PSVariable object
    $psVar = Get-Variable MyValidatedArg
    # Get the Attribute to Remove
    $attrib = $psVar.Attributes | Where-Object { $_ -is [ValidateScript] }
    # Remove it
    $psVar.Attributes.Remove($attrib)
    # Then assignment should work
    $MyValidatedArg = 2
    
    • 5

relate perguntas

  • Como faço para obter o identificador de processo de um trabalho?

  • One-liner do PowerShell - Como

  • Powershell 5.1: descrições de alias estão faltando no meu módulo

  • Import-CSV: adiciona linhas (membros) ao objeto resultante no loop foreach

  • Use e modifique minha variável em todo powershell startthreadjob

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve