1

So I am using the kind of buggy Sapien powershell studio to make a powershell driven GUI application, and I am attempting to perform an ADSI query.

$nameOfDeviceInput is a System.Windows.Forms.TextBox

On one form, I have the following function:

$buttonPerformAction_Click={
    if (FindInAD($nameOfDeviceInput.Text).Count -gt 0)
    {
        $buttonPerformAction.BackColor = 'Red'
        $buttonPerformAction.Text = "System already exists in AD with that name. Try another name"
        return
    }
.....
}

On the "main" form, I have the function FindInAD

function FindInAd($nameOfSystem)
{
    Write-Host "seeking system" $nameOfSystem
    ([adsisearcher]"(CN=$nameOfSystem)").FindAll()
}

FindInAd() is failing because for whatever reason, $nameOfSystem is set to 1, and if I don't explicitly cast it as a string, it gets implicitly cast to Int32 (obviously)

I have tried the following:

Fully qualifying the textbox input by notating the form it belongs to ( $adObjectModifier )

 $buttonPerformAction_Click={
        if (FindInAD($adObjectModifier.$nameOfDeviceInput.Text).Count -gt 0)
        {
            $buttonPerformAction.BackColor = 'Red'
            $buttonPerformAction.Text = "System already exists in AD with that name. Try another name"
            return
        }
    .....
    }

Explicitly casting the $nameOfSystem parameter as a type of [string]

function FindInAd([string]$nameOfSystem)
{
    Write-Host "seeking system" $nameOfSystem
    ([adsisearcher]"(CN=$nameOfSystem)").FindAll()
}

Passing a raw string into FindInAD from the AdObjectModifier form.

.... 

if (FindInAD("Test").Count -gt 0)

....

There is nothing else on the output pipeline at the time, (at least not from me) in between the method invocation. It is EventHandler > Function Call with String parameter

Why are the strings I'm passing getting changed to a digit???

EDIT: I think my passed parameter is being automatically replaced with the resulting boolean somehow, but this doesn't make any sense to me....

1 Answer 1

4

Your have a syntax problem:

# !! WRONG
FindInAD($nameOfDeviceInput.Text).Count 

Note: Wrong in this context means: the syntax is formally valid, but doesn't do what you expect - see the bottom section.

It should be:

# OK
(FindInAD $nameOfDeviceInput.Text).Count

PowerShell commands - functions, cmdlets, scripts and external programs - are invoked like shell commands - foo arg1 arg2 - and not like C# methods - foo('arg1', 'arg2').

That is:

  • Do not put (...) around the list of arguments.

    • However, you do need (...) around the call as a whole if you want a command call to participate in an expression, as shown above with the access to property .Count - see this answer for more information.
  • Separate arguments with spaces, both from each other and from the command name - do not use ,

    • , between arguments functions differently: It constructs an array that is passed as a single argument - see below.
  • You may pass simple strings (ones that contain neither spaces nor PowerShell metacharacters such as ; or &) as barewords; that is, quoting them is optional; e.g., instead of foo 'bar', you can call foo bar - see this answer for how PowerShell parses unquoted command arguments.

  • Also, if a target function or script has explicitly declared parameters (which binary cmdlets invariably do), such as -bar and -baz, you can pass your values as named arguments, i.e. by prepending them with the target parameter name; doing so is good practice in scripts: foo -bar arg1 -baz arg2

By contrast, calling methods of objects uses the syntax familiar from regular programming languages such as C# ($obj.foo('arg1', 'arg2'))

This difference relates two PowerShell's two fundamental parsing modes, explained in detail in this answer:

  • Commands are parsed in argument mode - as in shells.

  • Method calls and operator-based expressions are parsed in expression mode - as in regular programming languages.

These modes are required in order to allow PowerShell serve double duty: as a shell on the one hand, and as a scripting (programming) language on the other.


PowerShell can help you avoid this syntax problem:

Note that the problem isn't that using method syntax to call a command is invalid syntax, but that it doesn't work as intended, which can be difficult to diagnose.

In short: When you call command foo as foo('foo', 'bar'), ('foo', 'bar')is a 2-element array, which is then passed to foo as a single argument.

To prevent the problem to begin with, you can set Set-StrictMode to -Version 2 or higher, which makes PowerShell report an error if you accidentally use method syntax when calling a command:

# Turn on the check for accidental method syntax.
# Note: This also turns on ADDITIONAL checks - see below.
Set-StrictMode -Version 2

# This call now produces an ERROR, because the proper syntax would be:
#    foo 'a' 'b'
foo('a', 'b')

Caveats:

  • Set-StrictMode -Version 2 comprises additional strictness checks that you must then also conform to, notably:

    • You must not reference non-existent variables.
    • You must not reference non-existent properties; see GitHub issue #2798 for an associated pitfall in connection with PowerShell's unified handling of scalars and collections via its intrinsic members.
  • An error is reported only for pseudo method calls with multiple arguments (e.g.,
    foo('bar', 'baz')), not with only one; e.g., foo('bar') is accepted, because the single-argument case generally still (accidentally) works.

  • The errors reported for strictness violations are statement-terminating errors: that is, they only terminate the statement at hand, but by default the script continues; to ensure that overall execution aborts - on any type of error - you'd have to set
    $ErrorActionPreference = 'Stop' at the start of your code. See this answer for more information.


As for what you tried:

FindInAD($nameOfDeviceInput.Text).Count

is the same as:

FindInAD ($nameOfDeviceInput.Text).Count

That is, the result of expression ($nameOfDeviceInput.Text).Count is passed as an argument to function FindInAD.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.