So, with PowerShell 2.0 CTP’s arrival, and me finally having some time to mess around with some of the new features, here’s my previous (and first popular) post re-hashed for PowerShell 2.0 CTP. This will only work on machines with WS-Management installed, so it probably won’t work on most of your machines (unless you’ve deployed it), but it works well in my little test world. It utilizes two new features. These features are the [ADSISearcher] and Invoke-Expression. Instead of creating all of the Directory Service objects each time, you can just cast the ASDISearcher type and you’re done. Invoke-Expression allows you to use the -computer parameter and pass one, or many, computers to the cmdlet. I chose to use a single command here.


[adsisearcher]$searcher = “LDAP://dc=foo,dc=bar,dc=com”
$searcher.filter = “(objectclass=computer)”
foreach ($machine in ($searcher.findall()))
{
   invoke-expression -computer $machine.properties.cn -command ”c:\windows\`$NtUninstallKB917013`$\spuninst\spuninst.exe /q /norestart”
}

I haven’t had a chance to test it, but you could use mutiple computers. We could change the foreach loop to write to a text file, then read that file for the computer names.

...
foreach ($machine in ($searcher.findall())){ add-content c:\temp\machines.txt "$($machine.properties.cn)" }
invoke-expression -computer (get-content c:\temp\machines.txt) -command "c:\windows\`$NtUninstallKB917013`$\spuninst\spuninst.exe /q /norestart"

That’ll kick off on 50 machines at a time. You can adjust that via the -ThrottleLimit parameter, and make it more or less, depending on bandwidth, CPU power, etc.

As you can see, I tend to learn better by example or by practical application. You’ll never see me write a book :) More soon!!

 30 Oct 2007 @ 10:47 PM 

I don’t understand the big issue with the accidental release of WDS (Windows Desktop Search) via WSUS (here). It wasn’t like MS said “Muhuhahaha, let’s release WDS  to the masses via WSUS!” I mean…why? There’s no compelling reason for this besides a simple mistake. Now, the fact that the mistake was made is a little scary. I don’t want some blue-screen causing driver or security update released to 500 servers. That might wreck my month…no, year. Then again, how many critical servers are set to auto-update? Test and QA boxes, but never production, unless you’re load balanced (ie, IIS boxes), and can stagger update times. At least that’s how I see it…

Removal was pretty easy, too. Altiris works wonders. But, let’s say you don’t have Altiris. You could use (ready for this?) PowerShell. They provide the removal instructions on the WDS blog entry. Using another handy utility, PSEXEC, you could very easily run a script to remove WDS. It might take a while, depending on the number of machines, but it’ll work…and without much effort.

For the sake of argument (and typing), let’s say it went to every box on your domain, server and desktop. This will only return 1,000 objects, so you’ll need to break it out by OU or some other method if you have more than that. Here’s my remove wds script (excuse the formatting…)


$root = new-object DirectoryServices.DirectoryEntry
$searcher = new-object DirectoryServices.DirectorySearcher
$searcher.SearchRoot = $root
$searcher.Filter = "(samaccounttype=805306369)"
$machines = $searcher.FindAll()
foreach ($machine in $machines)
{
  psexec.exe "\\$($machine.properties.cn)" -d - c:\windows\`$NtUninstallKB917013`$\spuninst\spuninst.exe /q /norestart
  #run PSEXEC, execute sp uninstaller quietly, with no restart. PSEXEC will not wait for app to finish
  #and will only wait 5 seconds before timing out when attempting to run the remote command
}

Now, you’ve kicked off the task to remove the update from all of your machines…or 1,000 of them.

 28 Sep 2007 @ 8:14 PM 

Here’s the script I metioned a few days ago. I wrote this a while back (Pre-RC0, I think).

 Anyway, if you’ve got a bunch of servers that you need to perform a common task on (copy files, check event logs, etc), this is handy…however, it only works if you’ve got the Managed By field set in AD. Otherwise, you’re SOL. First, it makes sure the account name given exists in AD, then searches AD for and computer objects managed by that account. It uses write-output to return the list of servers. It outputs strings, not objects, since that’s all I needed out of it.

Syntax is: .\get-servernames.ps1 <samaccountname>
$root = new-object DirectoryServices.DirectoryEntry 'LDAP://dc=foo,dc=bar,dc=com'
$searcher = new-object DirectoryServices.DirectorySearcher
$searcher.SearchRoot = $root
$searcher.Filter = "(samaccountname=$($args[0]))”
$results = $searcher.findOne()
if ($results -eq $null) {
 write-host -fore ‘blue’ -back ‘white’ “`”$($args[0])`” not found”
 exit(1)
}
else {
 $dn = $results.GetDirectoryEntry().distinguishedname
 $searcher.Filter = “(&(samaccounttype=805306369)(managedby=$($dn)))”
 $servers = $searcher.FindAll()
  if ($($servers.count) -gt 0) {
   foreach ($server in $servers) { write-output “$($server.GetDirectoryEntry().cn)” }
 }
}

As I mentioned, this is pretty handy for copying files to groups of servers, checking error logs via psloglist, doing inventory, and more.

Tags Tags: , ,
Categories: Active Directory, PowerShell, Server Management
Posted By: Tom
Last Edit: 28 Nov 2007 @ 11 54 PM

E-mailPermalinkComments (0)
\/ More Options ...
Change Theme...
  • Users » 2
  • Posts/Pages » 22
  • Comments » 20
Change Theme...
  • VoidVoid
  • LifeLife « Default
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LiteLight
  • No Child Pages.