Martin’s New Blog
Thursday, 19. August 2010 0:47
Since August 18th 2010, Martin is blogging on the website of his consultancy company zetConsultants zetConsultants.com/blog
Category:Uncategorized | Comment (0) | Author: Frank-Peter
Thursday, 19. August 2010 0:47
Since August 18th 2010, Martin is blogging on the website of his consultancy company zetConsultants zetConsultants.com/blog
Category:Uncategorized | Comment (0) | Author: Frank-Peter
Thursday, 24. June 2010 17:33
Hello again, Frank-Peter here.
The other day, one of my PowerShell training participants stumbled upon an issue with foreach: if you try to run a foreach loop against an empty variable whose type isn’t array the loop will execute the code once. This can be demonstrated easily either in PowerShell 1.0 or 2.0 with the $null variable:
PS C:\Test> foreach ($element in $null) {write-host "element: $element"}
element:
PS C:\Test>
In that case I’d expect that foreach doesn’t execute any code meaning that foreach should treat an empty or undefined non-array variable as same as an empty array variable (like shown below):
PS C:\Test> foreach ($element in @()) {write-host "element: $element"}
PS C:\Test>
So take care
Category:Uncategorized | Comments (1) | Author: Frank-Peter
Thursday, 10. June 2010 14:15
If you’re using Windows PowerShell to administrer and automate Citrix Farms the day will dawn when you ask yourself (or someone else) if it is possible to fire up the locally installed Windows PowerShell Console in order to perform a task against a Citrix Farm remotely. Yes, it is possible
In case of XenApp 6 you make use of PowerShell 2.0′s Remoting feature as follows:
# # Remote XenApp 6 w/ PowerShell 2.0 Remoting # $CitrixServer = 'ctx001' $session = New-PSSession -ComputerName $CitrixServer Enter-PSSession -Session $session Add-PSSnapin Citrix*
In case of MFCOM-based Legacy Farm Server you can either create a PowerShell Remoting Session like above or – if you still use PowerShell 1.0 you have no other choice – create a remote COM object:
#
# Remote MFCOM w/ PowerShell 2.0 Remoting
#
$CitrixServer = 'ctx001'
$session = New-PSSession -ComputerName $CitrixServer[activator]::CreateInstance($type, $null)
Enter-PSSession -Session $session
$farm = New-Object -ComObject 'MetaFrameCOM.MetaFrameFarm'
#
# Remote MFCOM w/ PowerShell 1.0 and .NET
#
$CitrixServer = 'ctx001'
$type = [type]::GetTypeFromProgID('MetaFrameCOM.MetaFrameFarm', $CitrixServer)
$farm = [activator]::CreateInstance($type, $null)
Category:Citrix, PowerShell | Comment (0) | Author: Frank-Peter
Wednesday, 9. June 2010 15:01
Recently, I wrote here about the release of the Citrix XenApp 6 PowerShell SDK and that XenApp 6 neither supports nor contains the MFCOM programming interface of XenApp 5 and older versions (which I will call Legacy Farm from now on).
Upcoming Legacy Farm to XenApp 6 migration projects will definitely go along with the requirement to automatically export the Legacy Farm’s objects like Applications or Administrators in order to import them into the new XenApp 6 Farm. Since XenApp6 has no MFCOM support you won’t be able to use MFCOM based migration scripts you may have written for former migration projects. What you need instead is a Migration Tool that “speaks” both MFCOM and XenApp 6 Commands – meaning a tool that is able to communicate with the Legacy Farm as well as the new farm.
Good news is that such a tool is already available, currently it is still in Beta and it is supposed to be released in mid of this month – the Citrix XenApp 6 Migration Tool (Download)
The XenApp 6 Migration Tool contains a PowerShell 2.0 Module whose Cmdlets and Functions can be used to export Legacy Farm settings from a XenApp 5 Farm and import them to a XenApp 6 Farm. The following types of objects can be migrated:
Settings you can’t transfer:
The XenApp 6 Migration Tool supports only migration from a single XenApp 5 Farm. It isn’t possible to consolidate multiple Legacy Farms into one XenApp 6 Farm. The Legacy Farm must be based on XenApp 5 for WS2003 + HRP5 or XenApp 5 for WS2008. The new farm must be running XenApp 6 for WS2008 R2.
Category:Citrix, PowerShell | Comment (0) | Author: Frank-Peter
Tuesday, 8. June 2010 14:59
In corporate IT environments, the broken compatibility for user profiles leads to formidable challenges in Windows XP to Windows 7 migration projects. Even if it seems possible to automate this task using “homebrew scripts” – forget about it.
You definitely can save hours and days of development time if you spend 30 minutes in order to read Benny’s Immidio White Paper Migration To Windows 7 with Immidio Flex Profiles (Download)
Category:Immidio Flex Profiles | Comment (0) | Author: Frank-Peter
Wednesday, 19. May 2010 12:08
Hello again! Today I will share a small PowerShell function, ExpandEnvironmentVariables that I use to expand environment variables that are written in legacy syntax (%varname%). For instance, the function is useful if you read values from configuration text files that may contain variable names.
ExpandEnvironmentVariables supports PowerShell 1 and 2. It is designed to accept pipeline input and uses the ExpandEnvironmentVariables() method of the System.Environment class to resolve variables. The function supports nested variable references
function ExpandEnvironmentVariables {
param (
[string]$String
)
begin {
function _exp ([string]$str) {
$s1 = $str
$s2 = [System.Environment]::ExpandEnvironmentVariables($s1)
while ($s2 -ne $s1) {
$s1 = $s2
$s2 = [System.Environment]::ExpandEnvironmentVariables($s1)
}
$s2
}
}
process {
if ($_) {
$String = $_
} elseif (!$String) {
throw 'No value for the String parameter specified.'
}
_exp -str $String
}
}
Category:Scripting, Windows PowerShell | Comment (0) | Author: Frank-Peter
Sunday, 9. May 2010 17:16
About two weeks ago Citrix has released the XenApp 6 PowerShell SDK that enables people to manage XenApp 6 farms using Microsoft PowerShell scripting. The modules included in the SDK are Citrix XenApp Commands (aka XenApp cmdlets), Citrix Group Policy Provider, and Citrix Common Commands. The Citrix Principal Design Engineer Tom M Kludy wrote some nice blogs about the XenApp 6 SDK.
Reading the XenApp cmdlets reference I found the following information for those of you who are familiar with MFCOM:
Starting in XenApp 6.0, MFCOM as a publically supported programming and scripting interface will no longer be available. All existing MFCOM-based code no longer works on XenApp 6.0. No doubt that the absence of MFCOM will be something that requires additional effort to the adoption of XenApp 6.0.
Take a deep breath and don’t panic! Most of MFCOM scripts can be replaced by one-liners meaning that most of the short MFCOM scripts are obsolete as they’ve been replaced by PowerShell cmdlets.
For example adding a Citrix admin with the XenApp 6 PowerShell SDK is a one-liner:
New-XAAdministrator –AdministratorName ctxadmin –AdministratorType Full
In MFCOM, an administrator would need to write a script with dozens lines of code like below to accomplish the same task. So after all, it was definitely a good idea to discontinue MFCOM Support.
function Test-IsCitrixAdministrator(){
$MetaFrameWinFarmObject = 1
$MFCOM = New-Object -ComObject 'MetaframeCOM.MetaFrameFarm'
if (!$MFCOM)
{
$result = $false
}
else
{
$MFCOM.Initialize($MetaFrameWinFarmObject)
$result = [boolean] $MFCOM.WinFarmObject.IsCitrixAdministrator
$MFCOM = $null
}
$result
}
function Test-ADGroup(){
param(
$name = $(throw "No AD group name specified.")
)
$domainRoot = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().RootDomain.Name
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"GC://$domainRoot")
$searcher.Filter = "(&(objectClass=Group)(name=$name))"
$result = $searcher.FindOne()
[boolean] $result
}
function Add-CitrixAdmins(){
param(
$accounts = $(throw "No comma-seperated list of Citrix Admin accounts specified."),
$adminType = $(throw "No Admin Type specified. (Full or ViewOnly?)")
)
$MetaFrameWinFarmObject = 1
$MFAdminPermissionViewOnly = 1
$MFAdminPermissionFullAdmin = 3
$MFAccountAuthorityADS = 3
$MFAccountGlobalGroup = 4
$MFAccountEnable = 1
switch($adminType)
{
"Full"
{
$MFAdminPermission = $MFAdminPermissionFullAdmin
}
"ViewOnly"
{
$MFAdminPermission = $MFAdminPermissionViewOnly
}
default
{
throw "This function supports only the Citrix Admin Privilege levels Full and ViewOnly."
}
}
$MFCOM = New-Object -ComObject 'MetaframeCOM.MetaFrameFarm'
$MFCOM.Initialize($MetaFrameWinFarmObject)
$currentAdmins = $MFCOM.Admins | %{$_.FriendlyName}
$newAdmins = $accounts.Split(",")
$defaultDomain = $env:USERDOMAIN
foreach($account in $newAdmins)
{
$newAdmin = $account.Split("\")
if($newAdmin.Count -eq 1)
{
$accountDomain = $defaultDomain
$accountName = $account
if (-not (Test-ADGroup $accountName)){throw "Group does not exist in $accountDomain - $accountName"}
}
else
{
$accountDomain = $newAdmin[0]
$accountName = $newAdmin[1]
}
if($currentAdmins -notcontains "$accountDomain\$accountName")
{
$mfAdmin = $MFCOM.AddAdmin()
$mfAdmin.AdminType = $MFAdminPermission
$mfAdmin.AAType = $MFAccountAuthorityADS
$mfAdmin.AAName = $accountDomain
$mfAdmin.AccountType = $MFAccountGlobalGroup
$mfAdmin.AccountName = $accountName
$mfAdmin.Enable = $MFAccountEnable
$mfAdmin.SaveData()
$mfAdmin = $null
}
}
}
Category:Citrix, PowerShell | Comments (3) | Author: Frank-Peter
Wednesday, 28. April 2010 16:51
By chance (meaning by googling something) I stumbled over a script library called Scriptbox, and I found a really useful script there. It’s a huge resource! With about 6.500 vbs, js, and ps1 scripts I consider it one of biggest libraries ever.
Category:Scripting, VBScript, Windows PowerShell | Comments (1) | Author: Frank-Peter
Wednesday, 21. April 2010 14:37
One of these days, while analyzing a PowerShell script, I noticed something strange that I didn’t see before: a so-called Loop Label.
Loop labels allow you to name a looping statement (like for, foreach, or while) and to specify that name with a continue or break statement in order to instruct PowerShell to skip the rest of the current iteration (continue) or completely halt the execution (break) of that specific loop.
When does a loop label make sense? Loop labels are only useful with nested loops meaning that if you want to halt the outer loop execution within the inner loop.
Take a look at the code below. The inner loop will be halted as soon as the inner loop counter $j has reached the value 2:
for ($i = 0; $i -lt 5; $i++) {
for ($j = 0; $j -lt 5; $j++) {
if ($j -eq 2) {
break
}
Write-Host "outer loop counter = $i, inner loop counter = $j"
}
}
If you want to halt execution of the outer loop instead you need to define and specify a loop label as follows:
:outerloop for ($i = 0; $i -lt 5; $i++) {
for ($j = 0; $j -lt 5; $j++) {
if ($j -eq 2) {
break outerloop
}
Write-Host "outer loop counter = $i, inner loop counter = $j"
}
}
Category:Scripting, Windows PowerShell | Comments (1) | Author: Frank-Peter
Saturday, 20. March 2010 10:51
O’Reilly has enabled Lee Holmes to publish the revised edition of Windows PowerShell Cookbook online. It is a work in progress. The content is published while it’s being written, and you can read it and submit feedback.
Category:Windows PowerShell | Comment (0) | Author: Frank-Peter