Your have a syntax problem:
FindInAD($nameOfDeviceInput.Text).Count # WRONG
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:
(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.
- However, you do need
-
Separate arguments with whitespace (at least one space), 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 offoo 'bar'
, you can callfoo 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.
-
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
.