Posts RSS Comments RSS 127 Posts and 199 Comments till now

Further Testing with S.DS.P (~1 sec slower)

I have to say I am in awe. I never expected to get so close to ADFind.exe in performance, but if you look below you will notice how close s.ds.p really got.

Before I show the results I want to respond to some of joe’s comments on his blog entry here: PowerShell + S.DS.Protocols Versus AdFind…
btw… I STRONGLY recommend reading this entry… actually subscribing to his blog. While he does spout off random quotes… he provides some incredibly useful info from time to time.

note: References to joe as joe (case intentional) is not ment as disrespect, but simply the way joe refers to himself. If you have the pleasure of getting to know him… you will understand this.

[1] I understand fully that joe really wants .NET and Powershell to succeed, but finds it unlikely.

[2] My testing (although possibly not perfect) was much more precise and I assume his testing had to be skewed by something. Its just not possible. I tried this on 4 completely different systems. Different OS’s, x64 and x86, Hyper-v and ESX, and different domain sizes. By the end of the testing.. I ran approximately 600 test (although I only documented 240.)

[3] While I can appreciate his lack of faith in measure-command. It was the only way I could remove human error and maintain an unbiased count for each test. Measure-command’s overhead is maintained completely outside of the measured expression.

[4] MOST IMPORTANTLY: Perhaps the reason joe questions my purpose of doing these tests is because I did not make it clear. My purpose in these test was to determine if it is feasible to reach the same performance of adfind.exe in Powershell. Why? adfind.exe works great, why not just that. Simply put, if I can achieve close to the same performance, I’m able to get the speed while maintaining the benefit of dealing with objects. While this concept may escape people, once you grasp it… it is key to easy and fast scripts or commands. Nothing more, nothing less. While I will not argue I like a good debate, that is not my soul reason for being.

To be clear, this is only the first step. I now need to process some properties and see if s.ds.p/powershell can compete in that area. As I was with the count I am skeptical about achieving performance even close to adfind, but perhaps that will surprise me as the search did.

[5] My count was NOT off :P The logic of using userclass=* vs userclass=user was.

For those inclined to do so… Here is the COMPLETE output of the results without the average
Prod700kResults
Results Prod 400k VM
Small 200k Domain on Local Hardware
Small 200k Domain on VM

This first test was done in a LARGE environment with 700k+ userclass objects.

Prod 700k

This test was done on a production quality VM with approx 400k users.

Prod 400k

This test was on my Home Win2k8 DC. I only have about 200k userclass objects at home, but it is a beefy box.

Local 200k

This is on my laptop that has about 200k userclass objects as well.

VM 200k

Here are the scripts I ran for the testing

This is the actual worker code

[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null

$domainDN = ([ADSI]"").distinguishedName
$domain = $domainDN -replace  ",","." -replace "dc=",""

[int]$pageCount = 0
[int]$pageSize = 1000
[int]$count = 0

$connection = New-Object System.DirectoryServices.Protocols.LdapConnection($domain)  
$subtree = [System.DirectoryServices.Protocols.SearchScope]"Subtree"
$filter = "(objectclass=*)"

$searchRequest = New-Object System.DirectoryServices.Protocols.SearchRequest($DomainDN,$filter,$subtree,"1.1")  
$pagedRequest = New-Object System.DirectoryServices.Protocols.PageResultRequestControl($pageSize)
$searchRequest.Controls.add($pagedRequest) | out-null
$searchOptions = New-Object System.DirectoryServices.Protocols.SearchOptionsControl([System.DirectoryServices.Protocols.SearchOption]::DomainScope)
$searchRequest.Controls.Add($searchOptions) | out-null
 
while ($True)
{
    # Increment the pageCount by 1
    $pageCount++

    # Cast the directory response into a SearchResponse object
    $searchResponse = $connection.SendRequest($searchRequest)

    # Display the retrieved page number and the number of directory entries in the retrieved page
    # "Page:{0} Contains {1} response entries" -f $pageCount,$searchResponse.entries.count
    $count += ($searchResponse.entries).count
   
    # Display the entries within this page
    $searchResponse.Entries | select distinguishedName
    # if this is true, there are no more pages to request
    if ($searchResponse.Controls[0].Cookie.Length -eq 0){write-Output $count;break}

    # Set the cookie of the pageRequest equal to the cookie of the pageResponse to request the next
    # page of data in the send request and cast the directory control into a PageResultResponseControl object
    $pagedRequest.Cookie = $searchResponse.Controls[0].Cookie
}

Script I used to automate the 60 test per Environment.

Param($count=30)

$dn = ([ADSI]"").distinguishedName

function TestOne {
    Write-Host "  + Test ${i}.1"
    Write-Host "    + Running ADFind Test"
    $joeTime      = Measure-Command { D:\Scripts\adfind -b "$dn" -c -f "(objectclass=user)" 2>&1 | out-Null }
    Write-Host "      - $($joetime.TotalSeconds)"
    Write-Host "    + Running DSP Test"
    $DSPTime11    = Measure-command { D:\Scripts\Test-DSProtocalsSP.ps1 }
    Write-Host "      - $($DSPTime11.TotalSeconds)"
    $myresults  = "" | select @{n="ADFind"           ;e={$joeTime.TotalSeconds}},
                              @{n="DSP Using 1.1"    ;e={$DSPTime11.TotalSeconds}}
    $myresults
}
function TestTwo {
    Write-Host "  + Test ${i}.2"
    Write-Host "    + Running DSP Test"
    $DSPTime11    = Measure-command { D:\Scripts\Test-DSProtocalsSP.ps1 }
    Write-Host "      - $($DSPTime11.TotalSeconds)"
    Write-Host "    + Running ADFind Test"
    $joeTime      = Measure-Command { D:\Scripts\adfind -b "$dn" -c -f "(objectclass=user)" 2>&1 | out-Null }
    Write-Host "      - $($joetime.TotalSeconds)"
    $myresults  = "" | select @{n="ADFind"           ;e={$joeTime.TotalSeconds}},
                              @{n="DSP Using 1.1"    ;e={$DSPTime11.TotalSeconds}}
    $myresults
}

Write-Host
for($i = 0 ; $i -le $count ; $i++)
{
    Write-Host "+ Test $i"
    TestOne
    TestTwo
}
Write-Host

My First Venture into S.DS.P and Powershell

There has be much debate and agony on the the slowness of System.DirectoryServices.DirectorySearcher Class. This has lead me down the path of playing with System.DirectoryServices.Protocols (aka s.ds.p.)

By far the best tool out there right now is ADFind by joe Richards. So I used this for my target (although I didnt expect to get close.)

Here is the Guide I used in my Journey:
Introduction to System.DirectoryServices.Protocols (S.DS.P)

I started by writing the script you will find below and tested in a domain with well over 700k users and one with 200K. I did the test three different times in each Domain changing the order so cache hits wouldn’t be an issue. I also use objectclass on all three so index wouldn’t be a factor. I should NOTE that my script ONLY returns the count ATM. I am going to add properties next.

As you will see by the test results below… I got pretty darn close to adfind.exe in regards to perf. I was quite impressed with S.DS.P. Now to be fair, this was just counting objects. I am sure adfind.exe will start sneaking ahead abit further when we start processing properties and such. Can’t wait to see! Understand these test were just to see what tests I should focus on. I will posting another entry on more extensive count test with just DSP Using 1.1 and Adfind.

Test 1 700K Users done Remote

DirectorySearcher : 125.9123257
ADFind : 46.3763349
DSP Using DN : 69.5628776
DSP Using 1.1 : 49.4458161

Test 2 700K Users done Remote

DirectorySearcher : 125.0230257
ADFind : 46.4486472
DSP Using DN : 68.9255288
DSP Using 1.1 : 49.0780736

Test 3 700K Users done Remote

DirectorySearcher : 125.0230257
ADFind : 47.9162918
DSP Using DN : 79.6885386
DSP Using 1.1 : 54.152966

Test 1 200K done Local

DirectorySearcher : 121.1063569
ADFind : 55.2775406
DSP Using DN : 67.897922
DSP Using 1.1 : 28.5441615

Test 2 200K done Local

DirectorySearcher : 80.0894455
ADFind : 23.558696
DSP Using DN : 54.3111576
DSP Using 1.1 : 42.3485998

Test 3 200K done Local

DirectorySearcher : 99.1125363
ADFind : 80.1497852
DSP Using DN : 64.3716824
DSP Using 1.1 : 64.1940421

Summary: adfind.exe was faster (by bout 4sec on Avg.) remotely and larger domain, but protocals was faster (by bout 8 sec on Avg.) local on smaller domain.
Remote

ADFind: 46.92
DSP Using 1.1: 50.89
DSP Using DN: 72.73
DirectorySearcher: 125.32

Local

DSP Using 1.1: 45.03
ADFind: 52.99
DSP Using DN: 62.19
DirectorySearcher: 100.10

Here the script I ran for the test and how I measured the commands. I am going to play with passing the stats control and see what the server says later.

$SearcherExpression = @’
$searcher = new-object System.DirectoryServices.DirectorySearcher([ADSI]"","(objectclass=user)",@("distinguishedName"))
$searcher.pagesize = 1000
$searcher.findall()
‘@

Write-Host "Test 1"
Write-Host ("-"*40)
$myresults1 = "" | select @{n="DirectorySearcher";e={(Measure-command {invoke-expression $SearcherExpression}).TotalSeconds}},
                         @{n="ADFind";e={(Measure-Command { .\adfind -b "dc=corp,dc=lab" -c -f "(objectclass=user)" }).TotalSeconds}},
                         @{n="DSP Using DN";e={(Measure-command { .\Test-DSProtocals.ps1 }).TotalSeconds}},
                         @{n="DSP Using 1.1";e={(Measure-command { .\Test-DSProtocalsSP.ps1 }).TotalSeconds}}
$myresults1 | fl

Write-Host "Test 2"
Write-Host ("-"*40)
$myresults2 = "" | select @{n="ADFind";e={(Measure-Command { .\adfind -b "dc=corp,dc=lab" -c -f "(objectclass=user)" }).TotalSeconds}},
                         @{n="DSP Using 1.1";e={(Measure-command { .\Test-DSProtocalsSP.ps1 }).TotalSeconds}},
                         @{n="DSP Using DN";e={(Measure-command { .\Test-DSProtocals.ps1 }).TotalSeconds}},
                         @{n="DirectorySearcher";e={(Measure-command {invoke-expression $SearcherExpression}).TotalSeconds}}

$myresults2 | fl

Write-Host "Test 3"
Write-Host ("-"*40)
$myresults3 = "" | select @{n="DSP Using DN";e={(Measure-command { .\Test-DSProtocals.ps1 }).TotalSeconds}},
                         @{n="DSP Using 1.1";e={(Measure-command { .\Test-DSProtocalsSP.ps1 }).TotalSeconds}},
                         @{n="DirectorySearcher";e={(Measure-command {invoke-expression $SearcherExpression}).TotalSeconds}},
                         @{n="ADFind";e={(Measure-Command { .\adfind -b "dc=corp,dc=lab" -c -f "(objectclass=user)" }).TotalSeconds}}
$myresults3 | fl

$myresults1,$myresults2,$myresults3

Here is what the output of that Script looks like

S.DS.P : MyTest.ps1 Output

Here is the System.DirectoryServices.Protocols Code

[System.Reflection.assembly]::LoadWithPartialName("system.directoryservices.protocols") | Out-Null
$domain = ([ADSI]"").distinguishedName -replace  ",","." -replace "dc=",""
$DomainDN = "DC=" + $Domain -replace "\.",",DC="
[int]$pageCount = 0
[int]$pageSize = 1000
[int]$count = 0
$connection = New-Object System.DirectoryServices.Protocols.LdapConnection($domain)  
$subtree = [System.DirectoryServices.Protocols.SearchScope]"Subtree"
$filter = "(objectclass=user)"
$searchRequest = New-Object System.DirectoryServices.Protocols.SearchRequest($DomainDN,$filter,$subtree,@("1.1"))  
$pagedRequest = New-Object System.DirectoryServices.Protocols.PageResultRequestControl($pageSize)
$searchRequest.Controls.add($pagedRequest) | out-null
$searchOptions = new-object System.DirectoryServices.Protocols.SearchOptionsControl([System.DirectoryServices.Protocols.SearchOption]::DomainScope)
$searchRequest.Controls.Add($searchOptions) | out-null

while ($true)
{
    ## increment the pageCount by 1
    $pageCount++
    ## cast the directory response into a
    ## SearchResponse object
    $searchResponse = $connection.SendRequest($searchRequest)
    ## verify support for this advanced search operation
    if (($searchResponse.Controls.Length -lt 1) -or
        !($searchResponse.Controls[0] -is [System.DirectoryServices.Protocols.PageResultResponseControl]))
    {
        Write-Host "The server cannot page the result set"
        return;
    }
    ## cast the diretory control into
    ## a PageResultResponseControl object.
    $pageResponse = $searchResponse.Controls[0]
    ## display the retrieved page number and the number of
    ## directory entries in the retrieved page                    
    #"Page:{0} Contains {1} response entries" -f $pageCount,$searchResponse.entries.count
    $count += $searchResponse.entries.count
    ## display the entries within this page
    ## foreach($entry in $searchResponse.entries){$entry.DistinguishedName}
    ## if this is true, there
    ## are no more pages to request
    if ($pageResponse.Cookie.Length -eq 0){write-Host $count;break}
    ## set the cookie of the pageRequest equal to the cookie
    ## of the pageResponse to request the next page of data
    ## in the send request
    $pagedRequest.Cookie = $pageResponse.Cookie
}

More AD CMDLets from SDMSoftware

It includes snapins to get and re-animate tombstones

Darren discusses this on his blog: Powershell Hits The Morgue

Looking for interesting Citrix Problems

I am working on some blog entries and content for Citrix CDN and was curious what you guys thought.

If you have time, please leave some comments on problems or suggestions of things you would like to see. Specifically I am looking for some “real” world scenarios that I can present and provide solutions for.

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 player.

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 $_){$_}
            }
        }
    }
}}

Build Lab w/ Quest AD CMDLets

Earlier I wrote a post about a script that I used to build my AD Lab Build Lab (v1 w/out Quest Tools) and I mentioned I
would post a Quest version. I had some time run it (took about 6hrs.) So without further ado:

Whats it do Again?
# Creates A TestOU OU
# Creates A TestComputers OU
# Creates A TestUsers OU
# Creates A TestGroups OU
# Creates 10K OU’s Under TestOU
## Each of the 10k OUs will have 4 Child OUs
### Each OU should have 5 users Accounts and 5 Machines Accounts
# Create 500 Group Policies.
# Link 100 policies on the 10k Base OUs
# Create 2000 Users in the TestUser OU
# Create 2000 Computers in the TestComputer OU
# Create 2K Groups

Note: Added Write-Progress for OU/User Creation

# Adding Required Snapins
Add-PSSnapin SDMSoftware.PowerShell.GPMC -ea 0
Add-PSSnapin Quest.ActiveRoles.ADManagement -ea 0

$DomainDN = (([ADSI]"").distinguishedName[0])
$DomainDNS = (([ADSI]"").distinguishedName[0]) -replace "DC=","" -replace ",","."
$users = @()

# A TestOU OU
$BaseOU = New-QADObject -Type OrganizationalUnit -ParentContainer $DomainDN  -Name TestOU

# A TestComputers OU
$TestComps = New-QADObject -Type OrganizationalUnit -ParentContainer $DomainDN -Name TestComputers

# A TestUsers OU
$TestUsers = New-QADObject -Type OrganizationalUnit -ParentContainer $DomainDN -Name TestUsers

# A TestGroups OU
$TestGrps = New-QADObject -Type OrganizationalUnit -ParentContainer $DomainDN -Name TestGroups

# 10K OUs Under TestOU
foreach($i in 1..10000)
{
    $lvl1Child = New-QADObject -Type OrganizationalUnit -ParentContainer $BaseOU.dn -Name "LvL1ChildOU$i"
    Write-Progress "Creating OUs LvL1ChildOU$i" -status "Updating" -perc ($i/10000*100)
    ## Each of the 10k OUs will have 4 Child OUs
    foreach($x in 1..4)
    {
        $lvl2Child = New-QADObject -Type OrganizationalUnit -ParentContainer $lvl1Child.dn -Name "LvL2Child${i}${x}"
        Write-Progress "Creating Child OUs LvL2Child${i}${x}" -status "Updating" -perc ($x/4*100) -id 1  
        foreach($y in 1..5)
        {
            ## Each OU should have 5 users Accounts and 5 Machines Accounts
            Write-Progress "Creating Child Users/Computers" -status "Updating" -perc ($y/5*100) -id 2
            New-QADUser -ParentContainer $lvl2Child.dn -Name "usr${i}${x}${y}" -SamAccountName "usr${i}${x}${y}" -UserPrincipalName "usr${i}${x}${y}@$DomainDNS" -UserPass "!P@ssw0rd22!" | Out-Null
            New-QADObject -ParentContainer $lvl2Child.dn -name "srv${i}${x}${y}" -objectAttributes @{"sAMAccountName"="srv${i}${x}${y}`$"} -type "Computer" | out-Null
        }
    }
}

# Create 500 Group Policies.
1..500 | %{New-SDMgpo "TestGPO$_"}

# Link 100 policies on the 10k Base OUs
1..100 | %{Add-SDMgpLink -name "TestGPO$_" -scope "OU=LvL1ChildOU$i,$($BaseOU.DN)"}

# Create 2000 Users in the TestUser OU
1..2000 | %{New-QADUser -ParentContainer $TestUsers.dn -Name "Testusr$_" -SamAccountName "Testusr$_" -UserPrincipalName "Testusr$($_)@$DomainDNS" -UserPass "!P@ssw0rd22!"}

# Create 2000 Computers in the TestComputer OU
1..2000 | %{New-QADObject -ParentContainer $TestComps.dn -name "TestComp$($_)" -objectAttributes @{"sAMAccountName"="TestComp$($_)`$"}}

# Create 2K Groups
1..2000 | %{New-QADGroup -ParentContainer $TestGrps.dn -name "TestGrp$_" -sAMAccountName "TestGrp$_"}

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 player.

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 player.

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 player.

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 player.

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

« Previous PageNext Page »