The mystery of why Cisco AnyConnect stopped working

A while back I tried to update my Intel Centrino Ultimate 6300 Wifi NIC to the latest drivers, to test Intel MY wifi while I was out travelling, but I never got it to work, it said it could not detect a suitable adaptor.. So I did not think more of that, until I had to connect to our corporate network, using Cisco AnyConnect, and I got through both primary and secondary authentication fine, but then the connection crapped out with “unable to establish vpn”.. So after a few reboots and troubleshooting I ended up uninstalling the new driver, and reverting back to the old Lenovo one, I was running before.

Tonight I thought I would try again, to see if I could figure out what went wrong. So I installed the latest Intel drivers, and AnyConnect stopped working right away. So I went into Services to see what was “new” in there. I looked through all the Intel ones, and none of them looked “suspicious”, until I noticed that right below the Intel services, was “Internet Connnection Sharing (ICS)” and it was running. So I disabled it, and AnyConnected connected right away.

So if you have trouble connecting with AnyConnect, see if your connection has ICS enabled, or if you do not need it at all, just disable the service.

Read More

The (r)evolution of a script

As those of you who a following my blog know, I have been fortunate enough to become a Microsoft MVP in Powershell, and because of that I have been allowed on the Powershell MVP mailing list, an let me tell, there are some amazing people out there, doing some amazing stuff. Some of the stuff floating around I don’t even have a clue what does ;)

But people are also very helpful, and quick to jump in if someone has a problem or even if someone just posts a piece of code they find useful, people tend to jump in with suggestions/additions to make the script even better… Here is an example of a script that went from 14 lines of code to 334 in half a day.

Tome Tanasovski wrote a quick and dirty script that connects to the MVP site, and cycles through all the categories, and returns how many MVP’s there are in each. He ended off by saying, that the results where not entirely correct, since some MVP has hidden the profile from the public list, meaning you would have to be logged in to see them.

[ps]
$web = New-Object System.Net.WebClient
$regex = [regex]'(?m)<a href=\"(\/communities\/mvp.aspx\?product=1&competency=(\S+))\"’
$objects = @()
$return = $web.DownloadString(‘http://mvp.support.microsoft.com/communities/mvp.aspx’)
$regex.Matches($return) |% {
$obj = New-Object psobject
$obj |Add-Member NoteProperty -Name ‘Group’ -Value ($_.Groups[2].Value -replace ‘\+’,’ ‘)
if ($web.DownloadString((‘http://mvp.support.microsoft.com’ + $_.Groups[1].Value)) -match ‘Results 1 \- \d+ of (\d+)’) {
$obj |Add-Member NoteProperty -Name ‘Count’ -Value ([int]$matches[1])
}
$objects += $obj
}

$objects |sort Count -Descending |ogv
[/ps]

So I decided to write some simple IE automation that would log you you on to the Microsoft passport site, and count all the MVP’s, including those who do not have a public profile.

[ps]
$URI = "https://login.live.com/ppsecure/secure.srf?lc=1033&sf=1&id=259214&ru=https://mvp.support.microsoft.com/communities/mvp.aspx&tw=0&fs=0&kv=0&cb=wizid%3df4502d34-3b8f-4a04-b741-289e08aa1782%26lcid%3d1033%26returnurl%3dhttps%253a%252f%252fmvp.support.microsoft.com%252fcommunities%252fmvp.aspx%26brand%3dMicrosoft&cbcxt=&wp=MCMBI&wa=wsignin1.0&wreply=https://mvp.support.microsoft.com/communities/mvp.aspx&wlsu=1"
$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $false
$ie.navigate($URI)
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
$doc = $ie.Document
$ie.Document.Body.InnerText.ToString()
$user = $doc.getElementByID("Login")
$user.value = "xxxxxxxxxx"
$pass = $doc.getElementByID("Passwd")
$pass.value = "xxxxxxxxxx"
$Logon = $doc.getElementByID("SI")
$Logon.click()
while ($ie.LocationURL -ne "https://mvp.support.microsoft.com/communities/mvp.aspx") { Start-Sleep -Milliseconds 1000; }
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
#$ie.Document.Body.InnerHTML.ToString()

$regex = [regex]'(?m)<A href=\"(\/communities\/mvp.aspx\?product=1&amp;competency=(\S+))\"’
$objects = @()

$return = $ie.Document.Body.InnerHTML.ToString()

$regex.Matches($return)|% {
$obj = New-Object psobject
$obj |Add-Member NoteProperty -Name ‘Group’ -Value ($_.Groups[2].Value -replace ‘\+’,’ ‘)
$URI = "https://mvp.support.microsoft.com$($_.Groups[1].Value -replace ‘amp;’,”)"
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
$ie.navigate($URI)
$URI
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
if (($ie.Document.Body.InnerText.ToString()) -match ‘Results 1 \- \d+ of (\d+)’) {
$MVPs=""; $MVPs = [int]$matches[1];$MVPs; $obj |Add-Member NoteProperty -Name ‘Count’ -Value ($MVPs)

}
$objects += $obj
}
$objects |sort Count -Descending |ogv
[/ps]

Then Michael B Smith jumped in on the thread, because he thought my script needed some error handling, which is completely right, and came up with his own version of the script.
[ps]
Param(
[switch]$gridview,
[string]$username,
[string]$password
)

[System.Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null

$ie = $null

try
{
if ($username)
{
$URI = "https://login.live.com/ppsecure/secure.srf?lc=1033&sf=1&id=259214&ru=https://mvp.support.microsoft.com/communities/mvp.aspx&tw=0&fs=0&kv=0&cb=wizid%3df4502d34-3b8f-4a04-b741-289e08aa1782%26lcid%3d1033%26returnurl%3dhttps%253a%252f%252fmvp.support.microsoft.com%252fcommunities%252fmvp.aspx%26brand%3dMicrosoft&cbcxt=&wp=MCMBI&wa=wsignin1.0&wreply=https://mvp.support.microsoft.com/communities/mvp.aspx&wlsu=1"
$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $false
$ie.navigate($URI)
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
$doc = $ie.Document
$ie.Document.Body.InnerText.ToString()

$user = $doc.getElementById( "i0116" ) ## login
if( $user )
{
$user.value = $username
}
else
{
"Document element named ‘Login’ not found"
}

$pass = $doc.getElementById( "i0118" ) ## passwd
if( $pass )
{
$pass.value = $password
}
else
{
"Document element named ‘Passwd’ not found"
}

$Logon = $doc.getElementById( "i0011" ) ## SI
if( $Logon )
{
$Logon.click()
}
else
{
"Document element named ‘SI’ not found"
}

$count = 0
while( $ie.LocationURL -ne "https://mvp.support.microsoft.com/communities/mvp.aspx" )
{
if( $ie.LocationURL -eq "https://mvp.support.microsoft.com/mvpinvalidsignin.aspx" )
{
write-error "Invalid username / password combination"
return
}

Start-Sleep -Milliseconds 1000
if( $count -gt 15 )
{
"Location URL is $($ie.LocationURL)"
}
$count++
}

$count = 0
while( $ie.Busy -eq $true )
{
Start-Sleep -Milliseconds 1000
if( $count -gt 15 )
{
"IE still busy after $count seconds"
}
$count++
}

#$ie.Document.Body.InnerHTML.ToString()
}

$regex = [regex]'(?m)<A href=\"(\/communities\/mvp.aspx\?product=1&amp;competency=(\S+))\"’
$objects = @()

$return = $ie.Document.Body.InnerHTML.ToString()
$regex.Matches($return)|% {
$obj = New-Object psobject
$obj |Add-Member NoteProperty -Name ‘Group’ -Value ([System.Web.HttpUtility]::UrlDecode( $_.Groups[2].Value ))

$URI = "https://mvp.support.microsoft.com$($_.Groups[1].Value -replace ‘amp;’,”)"
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
$ie.navigate($URI)
$URI
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 1000; }
if (($ie.Document.Body.InnerText.ToString()) -match ‘Results 1 \- \d+ of (\d+)’) {
$MVPs=""; $MVPs = [int]$matches[1];$MVPs; $obj |Add-Member NoteProperty -Name ‘Count’ -Value ($MVPs)
}
$objects += $obj
}

" "
"Total MVP Competencies $($objects.Count)"
if( $gridview )
{
$objects |sort Count -Descending |ogv
}
else
{
$objects |sort Count -Descending
}

}
finally
{
if( $ie )
{
$ie.Quit()
$ie = $null
}
}

[/ps]

Finally Kirk Munro decided to go “all in” and more or less rewrite the entire script into reusable functions, and using PSCredentials for more secure handling of the password, rewrote the logic to speed up the script, made it possible to only check a single MVP group and lots more.

[ps]
function Get-MvpCount {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$Competency = @(‘*’),

[Parameter(Mandatory=$false)]
[ValidateRange(0,60)]
[System.Int32]
$Timeout = 15,

[Parameter(Mandatory=$false)]
[ValidateNotNull()]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)

#region Initialize and load helper module.
$helperModule = New-Module -ScriptBlock {
#region Initialize local variables.
$ie = $null
#endregion

function Show-IEWindow {
#region Create a new hidden instance of Internet Explorer if one does not exist.
if (-not $script:ie) {
$script:ie = New-Object -ComObject ‘InternetExplorer.Application’
}
#endregion

#region Show the IE window.
$script:ie.Visible = $true
#endregion
}

function Hide-IEWindow {
#region Create a new hidden instance of Internet Explorer if one does not exist.
if (-not $script:ie) {
$script:ie = New-Object -ComObject ‘InternetExplorer.Application’
}
#endregion

#region Hide the IE window.
$script:ie.Visible = $false
#endregion
}

function Open-IEWebSite {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$Uri,

[Parameter(Position=1,Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$ErrorUri,

[Parameter(Mandatory=$false)]
[ValidateRange(0,60)]
[System.Int32]
$Timeout = 15
)
#region Create a new hidden instance of Internet Explorer if one does not exist.
if (-not $script:ie) {
$script:ie = New-Object -ComObject ‘InternetExplorer.Application’
$script:ie.Visible = $false
}
#endregion

try {
#region Navigate to the specified web site.
Write-Progress -Activity ‘Loading a web page’ -Status "Loading $Uri…"
$script:ie.Navigate($Uri)
#endregion

#region Wait until IE has finished loading the web site.
$count = 0
do {
if ($Timeout -and ($count -gt ($Timeout * 1000))) {
throw "The $Uri web page failed to load in $Timeout seconds."
}
if ((-not $script:ie.Busy) -and $ErrorUri) {
foreach ($failedLocationUrl in $ErrorUri) {
if ($script:ie.LocationURL -like $failedLocationUrl) {
throw "The $Uri web page failed to load ($($script:ie.LocationURL))."
}
}
}
Start-Sleep -Milliseconds 500
$count++
} while ($script:ie.Busy)
#endregion
}
finally {
if ($script:ie.Busy) {
$script:ie.Stop()
}
Write-Progress -Activity ‘Loading a web page’ -Status "Loading $Uri…" -Completed
}
}
function Test-IEWebSiteElement {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$Name
)
#region Raise an error if you haven’t opened a web site yet.
if (-not $script:ie.Document) {
throw ‘You must open a web site using Open-IEWebSite before you can invoke a button on the site.’
}
#endregion

#region Return true if the element exists; false otherwise.
[bool]$script:ie.Document.getElementById($Name)
#endregion
}

function Set-IEWebSiteFieldData {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.Collections.Hashtable]
$DataMap
)
#region Raise an error if you haven’t opened a web site yet.
if (-not $script:ie.Document) {
throw ‘You must open a web site using Open-IEWebSite before you can set field data.’
}
#endregion

#region Load the data into the appropriate fields.
foreach ($key in $DataMap.Keys) {
if ($field = $script:ie.Document.getElementById($key)) {
$field.Value = $DataMap[$key]
} else {
throw "Field element ‘$key’ was not found on $($script:ie.LocationURL)."
}
}
#endregion
}
function Invoke-IEWebSiteButton {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$Name,

[Parameter(Position=1,Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$ErrorUri,

[Parameter(Mandatory=$false)]
[ValidateRange(0,60)]
[System.Int32]
$Timeout = 15
)
#region Raise an error if you haven’t opened a web site yet.
if (-not $script:ie.Document) {
throw ‘You must open a web site using Open-IEWebSite before you can invoke a button on the site.’
}
#endregion

try {
#region Click on the specified button.
Write-Progress -Activity ‘Clicking a web site button’ -Status "Clicking on the $Name button on $($script:ie.LocationURL)…"
if ($button = $script:ie.Document.getElementById($Name)) {
$button.Click()
} else {
throw "Button ‘$Name’ was not found on $($script:ie.LocationURL)."
}
#endregion

#region Wait until IE has finished loading the web site.
$count = 0
do {
if ($Timeout -and ($count -gt ($Timeout * 1000))) {
throw "The web page failed to load in $Timeout seconds."
}
if ((-not $script:ie.Busy) -and $ErrorUri) {
foreach ($failedLocationUrl in $ErrorUri) {
if ($script:ie.LocationURL -like $failedLocationUrl) {
throw "An error occurred ($($script:ie.LocationURL))."
}
}
}
Start-Sleep -Milliseconds 500
$count++
} while ($script:ie.Busy)
#endregion
}
finally {
if ($script:ie.Busy) {
$script:ie.Stop()
}
Write-Progress -Activity ‘Clicking a web site button’ -Status "Clicking on the $Name button on $($script:ie.LocationURL)…" -Completed
}
}
function Get-IEWebSiteMatch {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.Text.RegularExpressions.Regex[]]
$Regex
)
#region Raise an error if you haven’t opened a web site yet.
if (-not $script:ie.Document) {
throw ‘You must open a web site using Open-IEWebSite before you can invoke a button on the site.’
}
#endregion

#region Return all matches for the specified regular expression.
$innerHtml = $script:ie.Document.Body.InnerHTML.ToString()
foreach ($value in $RegEx) {
$value.Matches($innerHtml)
}
#endregion
}
function ConvertFrom-EncodedUrl {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$InputObject
)
begin {
#region Load the System.Web assembly.
[System.Reflection.Assembly]::LoadWithPartialName(‘System.Web’) | Out-Null
#endregion
}
process {
#region Decode the values.
foreach ($value in $InputObject) {
[System.Web.HttpUtility]::UrlDecode($value)
}
#endregion
}
}

function ConvertTo-EncodedUrl {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[System.String[]]
$InputObject
)
begin {
#region Load the System.Web assembly.
[System.Reflection.Assembly]::LoadWithPartialName(‘System.Web’) | Out-Null
#endregion
}
process {
#region Encode the values.
foreach ($value in $InputObject) {
[System.Web.HttpUtility]::UrlEncode($value)
}
#endregion
}
}

$ExecutionContext.SessionState.Module.OnRemove = {
if ($script:ie) {
try {
$script:ie.Quit()
}
finally {
$script:ie = $null
}
}
}
}
#endregion

#region Load the helper module.
$helperModule | Import-Module
#endregion

try {
#region Open the MVP website, using credentials if they were provided.
if ($Credential -and ($Credential -ne [System.Management.Automation.PSCredential]::Empty)) {
#region If the caller provided credentials, use Passport login before retrieving competency data.
Open-IEWebSite -Uri ‘https://login.live.com/ppsecure/secure.srf?lc=1033&sf=1&id=259214&ru=https://mvp.support.microsoft.com/communities/mvp.aspx&tw=0&fs=0&kv=0&cb=wizid%3df4502d34-3b8f-4a04-b741-289e08aa1782%26lcid%3d1033%26returnurl%3dhttps%253a%252f%252fmvp.support.microsoft.com%252fcommunities%252fmvp.aspx%26brand%3dMicrosoft&cbcxt=&wp=MCMBI&wa=wsignin1.0&wreply=https://mvp.support.microsoft.com/communities/mvp.aspx&wlsu=1′
if (Test-IEWebSiteElement -Name ‘i0011′) {
Set-IEWebSiteFieldData -DataMap @{
‘i0116′ = $Credential.UserName.Trim([Char[]]’ \’)
‘i0118′ = $Credential.GetNetworkCredential().Password
}
Invoke-IEWebSiteButton -Name ‘i0011′ -ErrorUri ‘https://mvp.support.microsoft.com/mvpinvalidsignin.aspx’
}
#endregion
} else {
#region Otherwise, simply open the MVP website.
Open-IEWebSite -Uri ‘https://mvp.support.microsoft.com/communities/mvp.aspx’
#endregion
}
#endregion

#region Process the compentencies that were requested.
Get-IEWebSiteMatch -Regex ‘(?m)<A href=\"(\/communities\/mvp.aspx\?product=1&amp;competency=(\S+))\"’
| Add-Member -MemberType ScriptProperty -Name DecodedUrl -Value {$this.Groups[2].Value | ConvertFrom-EncodedUrl} -PassThru

| Sort-Object -Property DecodedUrl
| ForEach-Object {
foreach ($value in $Competency) {
if ($_.DecodedUrl -like $value) {
Open-IEWebSite -Uri "https://mvp.support.microsoft.com$($_.Groups[1].Value -replace 'amp;','')"
if ($matches = Get-IEWebSiteMatch -Regex 'Results 1 \- \d+ of (\d+)') {
$competencyRecord = New-Object -TypeName System.Management.Automation.PSObject

| Add-Member -MemberType NoteProperty -Name Competency -Value $_.DecodedUrl -PassThru `
| Add-Member -MemberType NoteProperty -Name Count -Value $matches[0].Groups[1].Value -PassThru
$competencyRecord.PSTypeNames.Insert(0,’MVPCompetencyRecord’)
$competencyRecord
}
break
}
}
}
#endregion
}
finally {
$helperModule | Remove-Module
}
}
[/ps]

Remember this is not thoroughly tested code, this is just examples of different ways of doing things…

Read More

Output a sortable HTML table

A while back I posted a script that would take whatever input it got, into a sortable HTML table in a file.

Last night my family was here, and they wanted to see the Eurovision song contest thing, so I had some time to rewrite the script into a PowerShell V2 Advanced function, that supports pipeline input.

There are some examples in the code on how to use the function

I do not know what has happened to code highlighter, but it has suddenly decided to mess up the code, so it is not working on the site, so here is a link to the file.

Out-HTMLTable

Example of output:

Out-HTMLTable example

download | new post

Read More

Remoting examples from my presentation

Example #1

[ps]
#Sessions

#Single Session
$Session = New-PSSession -ComputerName "computername"

#Multiple Sessions

$Session = New-PSSession -ComputerName "comp1","comp2"…..

#Remove all Sessions

Remove-PSSession *

#Remove Named Session

Remove-PSSession $Session

#Using $session
Invoke-Command {ipconfig} -Session $Session

Enter-PSSession -Session $session
[/sourcecode]

Example #2

[sourcecode lang="PosH"]
$session = New-PSSession -ComputerName "compname"

Invoke-Command {Import-Module ActiveDirectory} -Session $session

Import-PSSession -Session $session -Module ActiveDirectory -Prefix "ctn"

notepad (Get-Module).path

Get-Command *ctn*

[/ps]

Read More

Gotten back from Minasi conference

I got back from Virgina Beach this past Saturday, after attending a very good conference, where I learned a lot of new an exciting stuff… And of course it was very good to meet up with the “gang” again.

This year I did a presentation on Powershell (wow 1 hour and 20 min goes past fast, when you are having fun)
As the presenter rookie I am, I was not able to time my presentation, so when time was up, even went 10 min over time, I still missed about a third of the presentation. So to make up for that, I will post all the scripts and the prensentation in its entirety, so hope you will find it usefull.

Read More

Powershell as a webservice

Seems as if Quest has been doing some really cool things with Powershell,  from what I can read, they have “rolled” it up as a webservice, meaning that you can now run your Powershell scripts over HTTPS from either you local machine, your phone,  anything that supports a newer web browser.

From what I can gather from the manual, you install it on a server running IIS, you set up the site, security etc. Then you can connect to the site from a webbrowser, and you will get a PowerShell commandline in your browser.  Combined with Powershell v.2’s remoting features this has the potential of becoming an awesome tool. One of the nice features is that you can save “favourites” in your web sessions,  here favourites should be seen as snippets of Powershell code, that you can just click on the run.

So imagine, you have a Powershell script that runs and checks if a particular service is running, if not it does “Something”. You  are sitting by the pool drinking a nice cold beer, when you get a call that there is trouble in the office. You pick up you android phone, open up a browser connects to www.whereIWork.com/MyPowerShell, login.. click your Powershell favourite/snippet, and your are done..

If you figure out that did not solve the problem, you just do

Enter-PsSession -Computername <Problematic Servername>, you are now running a Powershell session on the remote server, where you can look around the system, and try to fix the problem, as if you were sitting in front the server, with a Powershell console open.

Can’t wait to I can find some time to get it tested, even thoug it still is in Beta.

Read More

Finding Powershell V2

Joel Bennet made a good point about it can be difficult to find Powershell V2 on the MS site. I am not going to rewrite Joels post, so I will just “quote” it.

For some reason, people are having trouble finding links to the release version of Windows PowerShell 2.0 … I suspect it’s because while it was in CTP, a lot of us bloggers wrote about it and linked to the various CTP downloads … but there aren’t nearly as many posts announcing the release of Windows PowerShell 2.0 as you would expect.

Of course, most of the fault is Microsoft’s, because they buried PowerShell 2 in a knowledge base article with a title that exceeds nondescript, even for Microsoft: Description of the Windows Management Framework on Windows XP, Windows Server 2003, Windows Vista, and Windows Server 2008. What? Even the Microsoft PowerShell Team Blog never actually wrote a post announcing the PowerShell 2.0 release is available for download but instead wrote about the Windows Management Framework being released.

But in any case, I’m calling on the blogging community to fix the search engines by linking Windows PowerShell and particularly “Windows PowerShell 2.0”: http://support.microsoft.com/kb/968929 to either the Knowledge base article 968929 which has the download links for PowerShell 2.0 for Windows XP, Vista, and Server 2003 and 2008 … or to Microsoft.com/PowerShell which has the latest download links in the side-column on the right hand side. :)

I can’t fix the search engines on my own, but what was that slogan? Together we can!

Read More

ADMGS (Active Directory Management Gateway Service)

There has been some speculation on the web regarding the ADMGS for Server 2008 and 2003, if it would be possible to use it, in an environment without at least one Server 2008 R2.

So I decided to test it, I built a Server 2003 Domain, comprised of a single 2003 R2 Domain Controller, and 1 Windows 7 Enterprise workstation.
I installed Server 2003 into a VM, installed all updates inlcuding SP2, I then ran DCpromo to setup the new domain. When that was complete I downloaded the 2 required patches for 2003, to be able to run ADMGS.
(NDP35SP1-KB969166-x86.exe and 376193_ENU_i386_zip.exe), where the last of the two patches requires registration to download.

When they were installed, I downloaded the ADMGS setup file (Windows5.2-KB968934-x86.exe).
I created a few users, and everything worked fine.

I then built a Windows 7 client, downloaded the RSAT for Win 7 and joined it to the domain. I then ran my Powershell script to enable all RSAT tools on the machine.

The first thing I tried out was the new Active Directory Administrative Center, the new AD manament GUI built on Powershell, it connected to the DC, and I searched for the users I had created, and they showed up **SUCCESS**
I played around with it some more, creating/deleting some users, and everything seemed to work fine, so I tried out the “Active Directory Module for PowerShell”, pulling down some information about users and computers which also worked.

So all in all it seems as if it is not required to have a Server 2008 R2 in you domain/forest in order to use ADWS (Active Directory Web services) in your domain.

So there you have it folks, there are now a full live competitor to the Quest AD cmdlets, which have been around for a while and have let you manage you 2003 AD… Let the fight begin :)

Read More

Finding that Hyper-V machine

Yesterday I was doing some maintenance on a machine at work, and when I looked in device manager, i saw that it was a Hyper-V guest machine, and I asked a few colleagues about it, because I was pretty sure that we didn’t have any machines running Hyper-V.. So I needed to find out which machine, so I wrote a quick and dirty PowerShell script to find it.

First off I knew that it had to be a Windows 2008 machine, that boiled down the possible machines quite a lot.

Here is what I did
[ps]
Get-QADComputer | Where {$_.OSname -match "2008"} | % { Get-Service -ComputerName $_.Name} | where {$_.Displayname -match "hyper"} | select Machinename, Displayname
[/ps]

I get all computers that are Windows server 2008, and for each server 2008, I look for services containing the word “hyper”.
This is not a very efficient search, but a quick and dirty way to find the info that I needed.

—-EDIT—–

Kirk Munro pointed out to me that Hyper-V actually registers a SCP (Service Connection Point) in AD, so instead of querying all the machines, you can just query the list of SCP’s in AD instead, which is much more efficient.

[ps]
Get-QADObject -Name ‘Microsoft Hyper-V’ -Type serviceConnectionPoint | Get-QADComputer -Identity {$_.ParentContainerDN}
[/ps]

Read More