Odd -replace issue...

This topic contains 5 replies, has 4 voices, and was last updated by Profile photo of Marco Nice Marco Nice 2 years, 2 months ago.

  • Author
    Posts
  • #19240
    Profile photo of Marco Nice
    Marco Nice
    Participant

    Hi all.

    I have a simple function which returns a value which then in turn updates an AD attribute but I am getting an error and I am not sure why:

    [i]Function Is_Remote {

    $RemoteMenuArray = ,@[1,"Yes"]
    $RemoteMenuArray +=,@[2,"No"]

    cls
    Write-Host "————-"
    foreach [$a in $RemoteMenuArray ] {Write-Host $a}
    Write-Host "————-"

    $x = Read-Host "Is the user Remote?"
    Switch [$x]
    {
    1 {return "Yes"}
    2 {return "No"}
    default {"You have not selected a valid option"; $Is_Remote = ""; Is_Remote}
    }
    }

    $Is_Remote = Is_Remote
    $ComputerName = "testPSscript"

    Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$Is_Remote}[/i]

    The error I get is as follows:

    [b]Set-ADComputer : Invalid type 'System.Management.Automation.PSObject'.Parameter name: extensionAttribute5
    At C:\Temp\Test.ps1:24 char:15
    + Set-ADComputer <<<< -Identity $ComputerName -replace @{extensionAttribute5=$ Is_Remote} + CategoryInfo : InvalidArgument: [testPSscript:ADComputer] [Set-ADComputer], ArgumentException + FullyQualifiedErrorId : Invalid type 'System.Management.Automation.PSObject'. Parameter name: extensionAttribute5,Microsoft.ActiveDirectory.Management.Commands.SetADComputer[/b] If I replace the function with just setting the variable, it works fine: [i]$Is_Remote = "Yes" $ComputerName = "testPSscript" Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$Is_Remote}[/i] Anyone?

  • #19250
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    I think you are over complicating it:

    function Is-Remote {
        param(
            $UserResponse    
        )
        begin{}
        process{
            switch ($UserResponse) {
                1 {"Yes"}
                2 {"No"}
                default{$null}
            }
        }
        end{}
    }    
    
    Is-Remote -UserResponse 1
    Is-Remote -UserResponse 2
    
    #you would implement something like this...
    $remote = Is-Remote -UserResponse 4
    If ($remote) {
        "Set-AdUser with {0}" -f $remote
    }
    else {
        "Bad response"
    }
    
  • #19252
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Well... writing this kind of forced user interaction is generally frowned on whenever you can avoid it, but assuming that this is what you need, there's only one bug that I see in your code right now:

    default {"You have not selected a valid option"; $Is_Remote = ""; Is_Remote}
    

    In your default block, you're outputting the string "You have not selected a valid option" to the pipeline, then calling Is_Remote recursively (eventually returning "Yes" or "No"). If you look at the value of $Is_Remote after the function returns, you'll find one instance of the string "You have not selected a valid option" for every bad option that the user entered, followed by the eventual "Yes" or "No". Now, you could avoid polluting the pipeline with that message by making it a call to Write-Host instead of just outputting the string, but since you're clearing the screen as soon as Is_Remote is called anyway, no one's going to get a chance to read that "You have not selected a valid option" message anyway, so you may as well just get rid of it:

    Function Is_Remote {
     
        $RemoteMenuArray = ,@(1,"Yes")
        $RemoteMenuArray +=,@(2,"No")
     
        cls
        Write-Host "————-"
        foreach ($a in $RemoteMenuArray) {Write-Host $a}
        Write-Host "————-"
     
        $x = Read-Host "Is the user Remote?"
        Switch ($x)
        {
            1 {return "Yes"}
            2 {return "No"}
            default { return Is_Remote }
        }
    }
    
  • #19253
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    On a side note, this is not the greatest use of recursion. You could accomplish the same result with a loop, and not wind up consuming extra resources for the call stack (possibly resulting in whatever PowerShell's equivalent of a stack overflow is.)

    Function Is_Remote {
     
        $RemoteMenuArray = ,@(1,"Yes")
        $RemoteMenuArray +=,@(2,"No")
        
        while ($true)
        {
            cls
            Write-Host "————-"
            foreach ($a in $RemoteMenuArray) {Write-Host $a}
            Write-Host "————-"
     
            $x = Read-Host "Is the user Remote?"
            Switch ($x)
            {
                1 {return "Yes"}
                2 {return "No"}
            }
        }
    }
    
  • #19254
    Profile photo of Mike F Robbins
    Mike F Robbins
    Participant

    You code works without issue for me:

    function Is_Remote {
    
        $RemoteMenuArray = ,@(1,"Yes")
        $RemoteMenuArray += ,@(2,"No")
    
        cls
        Write-Host "————-"
        foreach ($a in $RemoteMenuArray) {
            Write-Host $a
        }
    
        Write-Host "————-"
    
        $x = Read-Host "Is the user Remote?"
        Switch ($x) {
            1 {return "Yes"}
            2 {return "No"}
            default {"You have not selected a valid option"; $Is_Remote = ""; Is_Remote}
        }
    }
    
    $Is_Remote = Is_Remote
    $ComputerName = "testPSscript"
    
    Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$Is_Remote}
    

    I would write it more like this though:

    #Requires -Modules ActiveDirectory
    function Set-IsRemote {
    
        [CmdletBinding()]
        param (
    
            [ValidateNotNullOrEmpty()]
            [string]$ComputerName = 'testPSscript',
    
            [Parameter(Mandatory=$true)]
            [boolean]$IsRemote
    
        )
    
        Switch ($IsRemote) {
            $true {$remote = 'Yes'}
            $false {$remote = 'No'}
        }
    
        Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$remote}
    
    }
    
    Set-IsRemote -ComputerName 'testPSscript' -IsRemote $true
    
  • #19259
    Profile photo of Marco Nice
    Marco Nice
    Participant

    Thanks for all your reply's.

    TBH, this is the worst script I have ever written (it gets a lot worse if you were to see all of it 🙂 ) but I needed something quick and dirty.

    I have resolved the issue now with some help from the Microsoft forum.

    I change the following line from this:

    Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$Is_Remote}
    

    to this:

    Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5="$Is_Remote"}
    

    and now it works.

    Not sure why though when this works fine:

    $Is_Remote = "Yes"
    $ComputerName = "testPSscript"
    Set-ADComputer -Identity $ComputerName -replace @{extensionAttribute5=$Is_Remote}
    

    As I said, very odd.

You must be logged in to reply to this topic.