Posts RSS Comments RSS 253 Posts and 411 Comments till now

Tracing LDAP calls with Powershell

Spat had an eerily coincidental blog post the other day (HERE). The reason I say eerily is because the night before I was fighting trying to get a LDAP trace, this trace was to help figure out EXACTLY how SDS.ActiveDirectory got replication cursors from a Domain Controller (another joe Richards discussion.) Anyway, I digress, I found the blog entry EXTREMELY useful as it allowed me to get what I needed. I proceeded to leave a comment suggesting that this looked like a good job for Powershell as the resulting file from the tool is a CSV. This has led to a “challenge” from Spat and this is my response. I hope I did it justice.

Useful Links about Tracelog.exe
———–
Details about TraceLog.exe
LDAP tracing with TraceLog
ADSI tracing with TraceLog

Details about Script

Here are the functions in the script

Trace-Log
-flag: Hex value for the flags you want to pass (Default Value = “0x1FFFDFF3”)
-guid: GUID or File for tracing (Default Value = “LDAP”)
-SessionName: Unique Name for the actual trace (Default Value = “mytrace”)
-exe: The full name with extension of the EXE to add to registry to enable tracing. This only has to be done the first time you want to trace for an EXE.
[switch]Start: If set it enables logging. If not set, logging is disabled.
[switch]ADSI: If set it passes the ADSI GUID for tracing
[switch]LDAP: If set it passes the ADSI GUID for tracing

Convert-TraceLog
-Source: Trace (etl) file to convert to csv (Default Value = “.\ldap.etl”)
-file: File to set the results to (Default Value = “TraceResults.csv”)
[switch]$import: If set it will return a custom object with results

Below is a video that shows a demo of the script in use. I hope to do another one of these showing how to trace ADSI as well as LDAP. Make sure to read the Comments in Green. I tried to allow enough time. You can click to pause.

Download Tracelog Transcript (right click | Save Target As…)
Best Viewed Full Screen

Get the Flash Player to see this content.

Code
Download Trace Log Functions (right click | Save Target As…)

function Trace-Log {
    Param($file = ".\ldap.etl",
        $flag = 0x1FFFDFF3,
        $guid = "LDAP",
        $SessionName = "mytrace",
        $exe,
        [switch]$start,
        [switch]$ADSI,
        [switch]$LDAP
    )
    if($ADSI){$guid = "ADSI"}
    switch -exact ($guid)
    {
        "LDAP"  {$myguid = ‘#099614a5-5dd7-4788-8bc9-e29f43db28fc’}
        "ADSI"  {$myguid = ‘#7288c9f8-d63c-4932-a345-89d6b060174d’}
        Default {$myguid = "’$_’"}
    }
   
    Write-Host
   
    if($start)
    {
        Write-Host " Action: Start" -fore Yellow
        Write-Host " GUID:   $GUID" -fore Yellow
        Write-Host " File:   $file" -fore Yellow
        Write-Host " Flag:   $flag" -fore Yellow
        if($exe){Write-Host " Exe:    $exe" -fore Yellow}
       
    }
    else
    {
        Write-Host " State: Disabled" -fore Red
    }
   
    Write-Host
   
    if(!(test-Path "HKLM:\System\CurrentControlSet\Services\ldap\tracing\$exe") -and $exe)
    {
        new-Item -path "HKLM:\System\CurrentControlSet\Services\ldap\tracing" -name $exe | out-Null
    }
   
    if($start)
    {
        $cmd = "Tracelog.exe -start ‘$SessionName’ -f ‘$file’ -flag ‘$flag’ -guid ‘$myguid’"
    }
    else
    {
        $cmd = "tracelog -stop $SessionName"
    }
   
    Write-Host
    Write-Host "==========================" -fore White -back black
    write-Host "Running Command:" -fore White
    Write-Host " ==> $cmd" -fore Yellow
    invoke-Expression $cmd
    Write-Host "==========================" -fore White -back black
    Write-Host
}
function Convert-TraceFile{
    Param($Source=".\ldap.etl",$file="TraceResults.csv",[switch]$import)
   
    $cmd = "tracerpt.exe $Source -o $file -of CSV -y"
   
    invoke-Expression $cmd
   
    if($import)
    {
        import-Csv $file
    }
}

Test-Host (WMI Ping -or Port Check)

I often find (specifically when using WMI) the need to ping the machine first before performing any queries. WMI takes FOREVER to timeout. I decided that I should use a script/function to test a host before passing it down the pipe.

There are a couple of problems with this approach that I had to consider.
1) How do I know what to test without corrupting the pipe or using foreach?
– For this I added a “-property” parameter that would allow the user to pick what property to check against, but still output the entire object that was inputted.

2) What about firewalls that block ping?
– Added TestPort function that does a TCP connect and returns $true or $false

3) What if I want a conditional port check.
– Added the ability to Change the Default Port for TCP Connection Test

Here is the script that I came up with and some of things it does.
Parameters
$property: The Property to Ping or Test (Default is none.)
$tport: The Port to test against (Default is 135. Used with -port)
$timeout: The timeout for the connection (Default is 1000 ms, Used with -port)
[switch]$port: Switch to Test a port instead of Ping
[switch]$verbose: Provides Verbose Output.
Features
– Will Ping ‘$_’ by default
– Can pass the property that contains the Host to test using -property
– Can use -port to test a port instead of ping. (Uses TCP)
– Maintains the Object that is tested and passes it down the pipe if connection is passed.

A Demo of the script in action

Best Viewed Full Screen

Get the Flash Player to see this content.


Script CODE

Param($property,$tport=135,$timeout=1000,[switch]$port,[switch]$verbose)
Begin{
    function TestPort {
        Param($srv)
        $error.Clear()
        $ErrorActionPreference = "SilentlyContinue"
        $tcpclient = new-Object system.Net.Sockets.TcpClient
        $iar = $tcpclient.BeginConnect($srv,$tport,$null,$null)
        $wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
        # Traps    
        trap {if($verbose){Write-Host "General Exception"};return $false}
        trap [System.Net.Sockets.SocketException]
        {
            if($verbose){Write-Host "Exception: $($_.exception.message)"}
            return $false
        }
        if(!$wait)
        {
            $tcpclient.Close()
            if($verbose){Write-Host "Connection Timeout"}
            return $false
        }
        else
        {
            $tcpclient.EndConnect($iar) | out-Null
            $tcpclient.Close()
        }
        if(!$error[0]){return $true}
    }
    function PingServer {
        Param($MyHost)
        $pingresult = Get-WmiObject win32_pingstatus -f "address=’$MyHost’"
        if($pingresult.statuscode -eq 0) {$true} else {$false}
    }
}
Process{
    if($_)
    {
        if($port)
        {
            if($property)
            {
                if(TestPort $_.$property){$_}  
            }
            else
            {
                if(TestPort $_){$_}
            }
        }
        else
        {
            if($property)
            {
                if(PingServer $_.$property){$_}  
            }
            else
            {
                if(PingServer $_){$_}
            }
        }
    }
}

If you want this as a function use this code

function Test-Host{
Param($property,$tport=135,$timeout=1000,[switch]$port,[switch]$verbose)
Begin{
    function TestPort {
        Param($srv)
        $error.Clear()
        $ErrorActionPreference = "SilentlyContinue"
        $tcpclient = new-Object system.Net.Sockets.TcpClient
        $iar = $tcpclient.BeginConnect($srv,$tport,$null,$null)
        $wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
        # Traps    
        trap {if($verbose){Write-Host "General Exception"};return $false}
        trap [System.Net.Sockets.SocketException]
        {
            if($verbose){Write-Host "Exception: $($_.exception.message)"}
            return $false
        }
        if(!$wait)
        {
            $tcpclient.Close()
            if($verbose){Write-Host "Connection Timeout"}
            return $false
        }
        else
        {
            $tcpclient.EndConnect($iar) | out-Null
            $tcpclient.Close()
        }
        if(!$error[0]){return $true}
    }
    function PingServer {
        Param($MyHost)
        $pingresult = Get-WmiObject win32_pingstatus -f "address=’$MyHost’"
        if($pingresult.statuscode -eq 0) {$true} else {$false}
    }
}
Process{
    if($_)
    {
        if($port)
        {
            if($property)
            {
                if(TestPort $_.$property){$_}  
            }
            else
            {
                if(TestPort $_){$_}
            }
        }
        else
        {
            if($property)
            {
                if(PingServer $_.$property){$_}  
            }
            else
            {
                if(PingServer $_){$_}
            }
        }
    }
}}

Get-CitrixApplication (Playing Around Series)

Here is a quick demo of getting a Citrix Application and playing with its properties.

Best Viewed Full Screen

Get the Flash Player to see this content.


Demo File

#
# First we need to create the MFCOM Object
#
$mfapp = new-object -com MetaFrameCom.MetaFrameApplication
#
# To initialize we need to pass the app we want to accesss
#
$mfapp.Initialize(3,"Applications\Powershell")
#
# With Applications we need to load the data
#
$mfapp.loaddata(1)
#
# Lets see what we have
#
$mfapp | Get-Member -type Properties
#
# Lets look at Users and Groups
#
$mfapp | select Users,Groups
#
# How bout Servers
#
$mfapp.Servers | Select ServerName
#
# Sessions?
#
$mfApp.Sessions | ft SessionID,AppName,ClientAddress,ClientHRes,ClientVRes -auto

Get-CitrixFarm (Playing Around Series)

I wanted to show how EASY it is to play with Citrix MFCom so here is a little video.

I also want to note how most of the properties (like Servers,Applications,Zones) all return objects that have their own properties and methods. So you could very easily have these lines in your profile and always have everything just sitting there waiting to be used.

$farm = New-Object -Com ‘MetaframeCOM.MetaFrameFarm’
$farm.Initialize(1)
Write-Host "Loaded Farm Info from $($farm.FarmName)

Best Viewed Full Screen

Get the Flash Player to see this content.


Demo File

# Get Citrix Farm Object
#
$farm = New-Object -Com ‘MetaframeCOM.MetaFrameFarm’
#
# Initialize Farm
#
$farm.Initialize(1)
#
# Now that we have are farm. Lets make sure we have the one we want by Getting the FarmName
$Farm.FarmName
#
# Lets see what we have to play with
#
$farm | Get-Member -type Properties
#
#
# We have the Farm we want. Some of the Info we want is Admins. So lets Start there
#
$farm.Admins
#
# To View just a list
#
$farm.Admins | Select FriendlyName
#
# Lets see what Applications we have
#
$farm.Applications | ft BrowserName,ParentFolderDN
#
# To View the Servers
#
$farm.Servers | ft ServerName,IPAddress,SessionCount
#
# How bout Sessions?
$farm.Sessions
#
# Lets look at Print Drivers we Have installed
#
$farm.Drivers
#
# If you have multiple Zones you can get the Names Servers and DataCollector for the Zone
$farm.Zones
#

Get-CitrixServer (Playing Around Series)

This is a quick run through a MFCOm Citrix Server Object

Best Viewed Full Screen

Get the Flash Player to see this content.


Demo File

#
# We start by creating a Server Object
#
$mfsrv = New-Object -ComObject MetaFrameCOM.MetaFrameServer
#
# Initializing Server
#
$mfsrv.Initialize(6,$ENV:ComputerName)
#
# Now we have are server… Lets see what we have to play with
#
$mfsrv | Get-Member -type Properties
#
# Lets start by looking at the current sessions on the server
#
$mfsrv.Sessions | ft SessionID,AppName,ClientAddress,ClientHRes,ClientVRes -auto
#
# What about what Zone it is in?
#
$mfsrv.ZoneName
#
# Printers?
#
$mfsrv.Printers
#
# Lets see what Processes are running
#
$mfsrv.Processes | ft SessionID,ProcessID,UserName,ProcessState -auto
#
# A common task is Server Load
#
$mfsrv.WinServerObject.ServerLoad
#
# Last (and perhaps most important) What applications?
#
$mfsrv.Applications | ft BrowserName,ParentFolderDN

Vmotion with VI ToolKit (Playing Around Series)

I wanted to show you how simple it was to VMotion with new CMDLets. I also want to point out the most if not all the VMware CMDLets return VM Objects so you could easily do something like
Get-VM MyVM | Stop-VM | Remove-CDDrive | Move-VM -Dest $EsxHost | New-CDDrive -isoPath $isoPath -StartConnected | Start-VM

Best Viewed Full Screen

Get the Flash Player to see this content.


Demo File

# Connect to Virtual Center
Get-VC home.halr9000.com
# Get ESX host
$esxHost = Get-VMHost 192.168.0.55
# Verify we got the correct ESX Host
$esxHost
# Get Virtual Machine
$vm = Get-VM SDK-XPSP2
# Verify We have the correct VM
$vm
# Test VM move with -whatif
Move-VM -VM $VM -Destination $EsxHost -whatif
# Lets do it for real
Move-VM -VM $VM -Destination $EsxHost

Controlling VMWare VMs with VI Toolkit (Playing Around Series)

In this video I show starting, Pausing, Resuming and Stopping VMs using Get-VM, Start-VM, Suspend-VM, and Stop-VM

Note: These are fast run throughts, but you can pause and read the comments.

BEST VIEWED FULL SCREEN

Get the Flash Player to see this content.


Demo File

# Connect to Virtual Center
Get-VC home.halr9000.com
# View our current VMs
Get-VM
# Pick Specific VM
get-vm SDK-XPSP2
# To start VM
get-vm SDK-XPSP2 | Start-VM
# To pause VM
get-vm SDK-XPSP2 | Suspend-VM -Confirm:$False
# To resume it again
get-vm SDK-XPSP2 | Start-VM
# To stop VM
get-vm SDK-XPSP2 | Stop-VM -Confirm:$False

Intro to VMWare VI Toolkit for Windows (Playing Around Series)

I know there are a good bit of people out there that are unable install and play with the new VMWare toolkit. So in this post I though I would record some of my playing around with Get-VM 🙂

I show Get-VM, Get-HardDisks, Get-CDDrive, Get-NetworkAdapter, and Get-FloppyDrive. I recommend pausing and reading the video as you go.

Note: This is a fast run through. I recommend pausing and reading the Comments.

BEST VIEWED FULL SCREEN

Get the Flash Player to see this content.

Some shout outs:
To Hal from PowerScripting.Net for use of his Lab for recordings. Here is his blog: Hals Blog
To Camtasia for incredible product:
Click Here
To VMWare for some Great CMDLets: Click Here

Demo File

Get-VC home.halr9000.com
# Lets look at the all the commands we have.
Get-Vicommand | more
# Now lets look at Get-VM
Get-VM
# What properties do we have for the VMs
Get-VM | Get-Member -type property
# Lets look at the Hard Disks
Get-VM | Get-HardDisk
# Here are the properties for a HardDisk
Get-VM | Get-HardDisk | Get-Member -type Property
# Lets look at VMs with over 2gb of disk
Get-VM | Get-HardDisk | ?{$_.CapacityKB*1kb -gt 2gb}
# What about 4gb
Get-VM | Get-HardDisk | ?{$_.CapacityKB*1kb -gt 4gb}
# Now lets look at the CD Drives
Get-VM | Get-CDDrive
# What about the properties available
Get-VM | Get-CDDrive | get-member -type property
# Lets make sure none of the CD’s have ISO’s attached
Get-VM | Get-CDDrive | ?{$_.ISOPath}
# How bout NICs
Get-VM | Get-NetworkAdapter
# what do they have to offer?
Get-VM | Get-NetworkAdapter | get-member -type property
# Lets look at all the NICs, but only the Mac and NetworkName
Get-VM | Get-NetworkAdapter | select MacAddress,NetworkName
# Finally, Lets take a quick peak at floppies
Get-VM | Get-FloppyDrive

Fun with Active Directory (Playing Around Series)

This is the first in a series of posts call “Playing Around Series.” This series will basically be demo Videos of different Snapins/.NET Classes and their use.

In this entry I run through creating a DirectoryEntry, DirectorySearcher, and using the System.DirectoryServices.ActiveDirectory.Domain Class.

Note: This is a fast run through. I STRONGLY recommend pausing and reading the Comments. Best Viewed Full Screen

Get the Flash Player to see this content.


Special Shout-out to JayKul and Jeffrey Snover for the Start-Demo script.
http://www.powershellcentral.com/scripts/302

Demo Text

#
# Lets start off by looking at DirectoryEntry
#
$DE = New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=tstUsr101,OU=MyUsers,DC=corp,DC=lab")
#
# First lets see what we have access to
#
$DE | Get-Member
#’
# Hmmm.. doesn’t seem like much. OH WAIT! Remember Powershell abstracts the class… Lets add psbase
#
$DE.psbase | Get-Member
#
# Lets look at what properties are available.
#
$DE.psbase.Properties
#
# Thats more like it. You may also note that some AD properties are still missing.
# That is because that LDAP doesnt return all the properties. For these you need to "GET" them.
$DE.psbase.InvokeGet(‘msExchUMFaxID’)
#
# Using DirectoryEntry is fine if you know the DN of the object, but what if you need to search?
# Lets look at System.DirectoryServices.DirectorySearcher
#
# The Searcher needs some info so put that in variables first
#
$root = [ADSI]""  ## This is using the Type Accelerator we spoke about earlier… This is Gets the base
$filter = "(&(objectcategory=user))"
#
# Now Lets create the searcher
#
$searcher = New-Object System.DirectoryServices.DirectorySearcher($root,$filter)
#
# That gets the searcher ready, but to execute we need to call findall() or findone()
#
$users = $searcher.findAll()
#
# Lets see what we got. We have alot so lets only pick the first 10
#
$users | select -first 10
#
# Tons of info, but notice that this is NOT the same as DirectoryEntry
#
$users | get-Member
#
# It still has the properties property, Lets look (but only the first 3)
#
$users | select -first 3 | %{$_.Properties}
#
# Finally Lets look at System.DirectoryDervices.ActiveDirectory.Domain
#
# We can use this to interactively browse around
#
[system.directoryservices.activedirectory.domain]::GetCurrentDomain()
#
# Lets assign that to variable to play with
#
$domain = [system.directoryservices.activedirectory.domain]::GetCurrentDomain()
$domain
#
# Lets see what this has to offer
#
$domain | get-member
#
# Tons of cool stuff here.
#
# We can find all domain controllers
$domain.FindAllDomainControllers()
#
# We Can look at our Domain FSMO
#
$domain | ft PdcRoleOwner,RidRoleOwner,InfrastructureRoleOwner
#
# I can even step the tree and get my forest root
#
$forest = $domain.Forest
$forest
#
# With our new found $forest object… what can do we do?
#
$forest | Get-Member
#
# WE can find all our GCs
#
$forest.FindAllGlobalCatalogs()
#
# We can look at the Forest Mode
#
$forest.ForestMode
#
# Look at the Forest FSMO
#
$forest | ft SchemaRoleOwner,NamingRoleOwner
#
# Even look at sites
$forest.Sites
#
# We can go on forever and ever. If you would like we can revisit this later.
#