Monday, April 14, 2008

Read groupmembers from AD

A friend of mine asked how he could read from his local AD, in order to create a script for verifying group membership against a saved list. Here is a small piece of code that helped him:

$users = [adsi]"LDAP://cn=groupName,ou=ouName,dc=MyDomain,dc=MyDomain2"

foreach ($user in $users.Member) {
    Write-Host (([adsi]"LDAP://$user").displayname)
}

New-RemoteProcess

It is possible to initiate a process on a remote machine through PowerShell, but only through WMI.
Unfortunately there are certain limitations to this functionality in WMI:
1.) The process will never be visible to a user logged on to the remote server.
2.) The process will only be initialized - no return values are passed back through WMI.

Limitation #2 can be circumvented by directing the output to a file, and then accessing the file after the process has completed.

Here is a quick example:

Function New-RemoteProcess {
## The function returns two values.
## A returncode (0 = success) and the ProcessID on the target server.
    Param ($target, $command, $path="c:\")
    $p = [WMIClass]"\\$target\ROOT\CIMV2:Win32_Process"
    $inParams = $p.psbase.GetMethodParameters("Create")
    $inparams.commandline = $command
    $inparams.currentdirectory = $path
    $result = $p.psbase.invokemethod("Create", $inparams, $null)
    Write-Output $result.ReturnValue
    Write-Output $result.ProcessID
}

New-RemoteProcess "MyServer.something.com" "Calc.exe"

Creating arrays

In PowerShell an array can be contructed in a number of ways:

$a = 1, 2, 3, 4, 5
$a = 1..5

The "1..5" notation builds a range of numbers starting with 1 and ending with 5. It is also possible to create a decrementing list:

$a = 5..1
$a
5
4
3
2
1

As a server/network/database administrator one will often have to deal with servers/databases/tables/etc. that share the same name, except for some sort of numbering scheme:

WebServer001_HQ
WebServer002_HQ
..
WebServer064_HQ


If the above range is needed in PowerShell, it can easily be constructed:

1..64 | ForEach-Object{"WebServer{0:000}" -f $_ + "_HQ"}


What if there are "holes" in the number ranges? Well, ranges can easily be constructed using
"+". Lets make a server list including servers numbered from 4 to 30, but say the servers numbered 19-21 have been decommissioned, and two servers additional servers have been added, numbered 117 and 666:

4..18 + 22..30 + 117,666 | ForEach-Object{"WebServer{0:000}" -f $_ + "_HQ"}

WebServer004_HQ
WebServer005_HQ
WebServer006_HQ
WebServer007_HQ
WebServer008_HQ
WebServer009_HQ
WebServer010_HQ
WebServer011_HQ
WebServer012_HQ
WebServer013_HQ
WebServer014_HQ
WebServer015_HQ
WebServer016_HQ
WebServer017_HQ
WebServer018_HQ
WebServer022_HQ
WebServer023_HQ
WebServer024_HQ
WebServer025_HQ
WebServer026_HQ
WebServer027_HQ
WebServer028_HQ
WebServer029_HQ
WebServer030_HQ
WebServer117_HQ
WebServer666_HQ