Powershell-enabled business card :)
Friday, 25. June 2010 10:12 | Author:Martin Zugec
Category:Uncategorized, Windows PowerShell | Comments (2)
Friday, 25. June 2010 10:12 | Author:Martin Zugec
Category:Uncategorized, Windows PowerShell | Comments (2)
Thursday, 24. June 2010 17:33 | Author:Frank-Peter
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)
Thursday, 10. June 2010 14:15 | Author:Frank-Peter
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)
Wednesday, 9. June 2010 22:41 | Author:Martin Zugec
As you maybe know, I have decided to start my new career as freelancer and one of first important decisions I had to make was regarding groupware (understand – mail + calendar + contacts).
In last few years, I got extremely used to combination of Exchange + Outlook + Windows Mobile. Synchronization of emails is nice, however what is extremely important for me is ability to synchronize calendar and contacts. I love the fact that I can add meeting to my Outlook and my mobile will let me know what, when and where.
As I said, I am starting as freelancer, therefore I started one-man consultancy company. I considered few different scenarios:
1.) Hosting my own Exchange server
2.) Microsoft BPOS
3.) 3rd party Exchange hosting
4.) Google Apps
Above options are based on my preferences (1 is most preferred, 4 is least preferred).
However, soon I realized that each of them got disadvantages.
Hosting my own Exchange server
Of course, most flexible solution, however not cheapest. I will need to have server at home running 24/7 and of course downtimes of my providers could affect my business. Economical? Not really (electricity etc). Easy too use? Also not
Microsoft BPOS
BPOS (Business Productivity Online Suite) is Microsoft set of services. It is part of global MS strategy regarding cloud computing (Azure = PaaS, BPOS = SaaS, IaaS is not covered yet). It costs $5 per account (monthly), which is very interesting and cheap. My problem however was that you had to buy at least 5 accounts (which is ok for small company, however not for freelancer).
3rd party Exchange hosting
Same as BPOS, however more expensive and not covered by big company (like MS). Advantage is that (for some providers), Outlook license is included ($10 per account per month).
Google Apps
Originally, this was not really an option for me. But surprise, surprise, Google won this fight
What you get as part of Google Apps? Email, calendar, contacts, documents and sites.
There are two editions – Standard and Premium. Most important difference for me is that Premium is paid service, it offers 25GB mailbox, support for Outlook client (!) and of course support & SLA. Standard is available for free on other hand.
What is very nice is that Google Apps supports Windows Mobile natively (!). All you need to do is to specify m.google.com as address of your Exchange server and you will get push notifications. Registration and usage is very simple – Google still follows minimalism approach.
Martin Zugec
Category:Uncategorized | Comment (0)
Wednesday, 9. June 2010 15:01 | Author:Frank-Peter
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)
Tuesday, 8. June 2010 14:59 | Author:Frank-Peter
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)
Wednesday, 19. May 2010 12:08 | Author:Frank-Peter
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)
Sunday, 9. May 2010 17:16 | Author:Frank-Peter
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)
Wednesday, 28. April 2010 16:51 | Author:Frank-Peter
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)
Wednesday, 21. April 2010 14:37 | Author:Frank-Peter
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)