Odd -replace issue...

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?

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"
}

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 }
    }
}

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"}
        }
    }
}

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

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 :slight_smile: ) 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.