Office 365 DirSync appliance is now supporting x64 architecture

Quick update: Office 365 DirSync appliance is now supporting x64 architecture

Advertisements

Live@edu has grown 100% year over year and topped 22M user mark!

I wanted to re-share exciting news on my blog. Live@edu has grown 100% year over year and topped 22M user mark!

http://blogs.technet.com/b/microsoft_blog/archive/2011/11/16/live-edu-tops-22m-users-grows-100-percent-year-over-year.aspx

Disabling Forwarding for an Outlook Live domain and Removing Forwarding Options from the OWA

Note: Good friend and colleague of mine Jim Muir wrote an article on how to disable forwarding in Live@edu. I’ve volunteered to re-publish it, so all credits for this content are going to Jim!

User Driven Options

Users can create inbox rules to automatically forward messages to e-mail addresses
outside an organization. Depending on an customer’s policies, they may choose
to prevent the forwarding of all such messages or to prevent the delivery of a
subset of auto-forwarded messages.

Administrator Driven Options

Disabling Forwarding for an Outlook Live domain

To accomplish this, IT Admins must first disable forwarding in the domain using Powershell. For instructions to install Powershell and connect it to the Outlook Live service, follow the online
instructions.
Once connected, use the -AutoForwardEnabled parameter which controls automatic message forwarding to remote domains.

Set-RemoteDomain Default -AutoForwardEnabled $false

If a rollback is required, use the same Powershell command with the parameter for –AutoForwardEnabled to $true.

Removing Forwarding Options from the OWA UI

There are three locations in the OWA UI that pertain to forwarding e-mail.

The first location

for forwarding appears in the OWA UI in the account section under the section called Shortcuts to other things you can do as shown here:

The second location

is within the “My Account” options page. When a user clicks on the “Forward your e-mail” link, the “My Account” options appear with the Forwarding section enabled. In the Forwarding section, there is a field to enter the address to forward the e-mail to and a tick box to enable a user to keep a copy of the forwarded message in the Outlook Web App.

The third location

appears as in the Organize E-Mail section when a user clicks the New drop down menu and selects the option Create a new rule for arriving messages which creates a new inbox rule. In the New Inbox Rule window, an option appears for Redirect the message to…

In order to remove these options from the user interface, IT Admins need to use Windows Powershell. IT Admins should remove the forwarding options from all three locations. If an IT admin wishes to turn off forwarding for all users in their domain, they should edit the DefaultMailboxPlan policy. If an IT admin wishes to apply this role to a small number of users, they will need to explicitly create a role assignment policy instead of using the default assignment policy.

In the example provided below, the default mailbox plan policy is used to turn off the forwarding features for all users. Assuming that the IT admin is connected to the service with Windows Powershell , follow these instructions:

  1. Create a new custom role name and base it off the default mailbox plan
    New-ManagementRole -Parent MyBaseOptions_DefaultMailboxPlan -Name
  2. Remove the DeliverToMailboxAndForward, ForwardingAddress and ForwardingSmtpAddress parameters from the mailboxes for the role Set-ManagementRoleEntry \Set-Mailbox -Parameters DeliverToMailboxAndForward,ForwardingAddress,ForwardingSmtpAddress –RemoveParameter
    NOTE: Outlook Live administrators have additional RBAC roles assigned. If you need to turn off the forwarding feature for an administrator account, you will need to clean up the DeliverToMailboxAndForward, ForwardingAddress and ForwardingSmtpAddress parameters for each role assignment.
  3. Remove the ForwardAsAttachementTo, ForwardTo and RedirectTo parameters from the inbox rules for the role
    Set-ManagementRoleEntry \New-InboxRule -Parameters ForwardAsAttachmentTo,ForwardTo,RedirectTo –RemoveParameter
    NOTE: Removing the ForwardAsAttachementTo, ForwardTo and RedirectTo parameters from the inbox rules also removes the option to set an inbox rule to forward the message as a text message.
  4. Assign the role to the default mailbox plan policy
    New-ManagementRoleAssignment -Policy RoleAssignmentPolicy-DefaultMailboxPlan -Role
  5. Remove the previous management role assignment
    Remove-ManagementRoleAssignment MyBaseOptions_DefaultMailboxPlan-RoleAssignmentPolicy-DefaultMail
  6. The administrator is asked to confirm the removal. Type Y to remove.

Once confirmed

the OWA UI will not display the forwarding options in the three locations outlined above

  1. My Account user interface
  2. Connected Accounts user interface
  3. New Inbox Rule interface

If a rollback is required, use the same PowerShell commands but instead of using the -RemoveParameter switch, use –AddParameter.

Career Changes

After many years of working with Microsoft as a contractor (vendor) I have finally caved-in. I am very excited to announce that I’ve accepted a full time position with Microsoft Corporation. As of January 4, 2011 I have joined Office 365 Deployment Team. The hiring process in Microsoft deserves a separate blog entry – it’s a long winding trail (more like an obstacle course) where coming out on the other end is its own reward. The lesson that I’ve learned (over and over again) is: patience is a virtue.

So… what does is mean for this blog. Well, being inside of the “mother-ship” and being part of the “mother-ship” is a little deferent from each other. As a Microsoft employee I represent Microsoft’s official “party line”, therefore some topics could be covered in slightly deferent manner. Naturally, I am expecting my perspective(s) to change a little bit, as I will become more exposed to the inner-workings of the “machine”. Nevertheless, I don’t expect any drastic changes; after all I was hired for who I am. Wish me luck, it should be a cool ride.

Archiving Exchange Mailboxes to .PST files

Update:

Rather than deleting this old entry, I wanted to update it with a simple link to “Microsoft Exchange PST Capture 2.0”: http://aka.ms/pstcapture2

It might help more than an original technique described below

PST files

Somehow I always manage to hit problems that are poorly documented and I have to spend hours of installing/re-installing software, adding features and patches… and reading posts that are somewhat relevant but not 100% covering the issue.

So my task of de jure was to assist our IT Admins to off-load user mailboxes form local Exchange server to PSF files for archiving purposes. I’ve volunteered for it thinking that – hey, what can be difficult about that. So after several hours of trying to figure out what is that I need here is definitive path that worked for me.

  • Install “Windows 7 x86” (32 bit version is important detail) [I’ve virtualized this machine]
  • Install Outlook 2010 x86 [You’ll need MAPI protocol from it… ]
  • W7 comes with PowerShell (just make sure that you have it installed/enabled)
  • Install Remote Server Administration Tools for Windows 7
    [Exchange Management tools (which we’ll install later) will need it. It is not really documented all that well or throws an obvious error that tells you – hey you are missing a pre-requisite. That would be easy… Exchange installer goes through the install verifies something and tell you that everything is fine… and shortly thereafter fails with odd error “An error occurred. The error code was 3221684226. The message was The system cannot find the file specified ” Gotta love it!)
  • Enable Active Directory Domain Services Tools (that is an Add Remove Programs\Windows Features)
  • To avoid error “The log file directory ‘C:\Program Files\Microsoft\Exchange Server\Logging\MigrationLogs’ does not exist” you need to:
    a) Create that folder AND (if you still having the error)
    b) Create a registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Exchange\Exchange Migration
  • Add your admin account to “Enterprise Adminis” group and to “Exchange Organization Administrators” group
  • Now you can download and install the “Microsoft Exchange Server 2007 Management Tools (32-Bit)” You’ll need to identify your version of Exchange with currently installed SP by looking at “About” dialog box of your exchange server and then looking here: http://support.microsoft.com/kb/158530
  • Now you are ready to off-load your users into PSTs with TWO PowerShell consecutive commands
    1) Firstly you need to grant yourself right to access the mailbox to avoid this misleading error:
    Export-Mailbox : Error was found for because: Error occurred in the step: Movingmessages. Failed to copy messages to the destination mailbox store with error: MAPI or an unspecified service provider. ID no: 00000000-0000-00000000, error code: -1056749164
    To grant yourself right you’ll need to execute following cmdlet:
    Add-mailboxpermission -identity -accessrights fullaccess -user
    2) And lastly you can execute this command:
    Export-Mailbox –Identity -PSTFolderPath
    Note: Make sure that your path for your destination PSF is pre-created…

I think this pretty much documents several several hours of my life.

Happy codding

AD account management and BPOS

Living with BPOS

Few weeks ago Schakra cut the umbilical cord of local Exchange server and fully moved into the cloud for all Exchange needs. The “cut” was rather anticlimactic. No email outage, no interruptions, no user screams… it was boring and trivial event. So what we have lacked in the “excitement” of migration, we have acquired on account management front. You would think that having less systems to manage will simplify life of an AD admin… not so fast. Once you’ve got accustom to Exchange management console you become dependent on those [pseudo-hidden] attributes such as msExchHideFromAddressLists, proxyAddresses, etc. With or without local Exchange box my admins demanded functionality to hide accounts, add additional addresses to user mailboxes, etc, etc. My first reaction was: “here is the list of attributes and ADSI Edit – go at it…” then I’ve started an investigation on how to “gracefully” expose the UI for those hidden treasures. Options were not so obvious, as one hoped: ADSI (or other LDAP) editor, upgrading AD to 2008 functional level and use of ADUC in that mode or the scripting. Of course having full-blown Identity Management system would help too.
Demographic data of BPOS user-base suggests that many of its users would lack the fully established Identity Management system, or the latest functional-level of AD, or the tools/comfort-level to edit raw AD data. So I’ve decided to attempt to automate a simple account creation process for all of those who are in post-migration stage of Office 365 deployment.

Choosing PowerShell

At first I was ready to write a command-line tool that would simply create a user account with pre-populated set of must-have attributes. PowerShell (being an interactive version of C# for the masses) is well situated for all sorts of administrative tasks; however my goal of providing familiar environment to my system admins will not be accomplished by writing a command-line utility. Having UI is a good thing for the comfort level. So I’ve decided to wrap a windows-forms application in PowerShell format. “Why oh why”, you would ask? PowerShell is command line environment after all. Writing windows form application defeats the purpose of the shell. Well… the answer is – not really. Even though it is not traditional approach to use the shell, having windows-forms should provide Windows admin with familiarity and therefore convenience. Yet, having PowerShell-based application provides ease of source maintenance and therefore gives end-user an ability to tweak application to his/her liking. So behold the PowerShell script/app to create your user accounts in AD.

Goals

Here are the goals that I’ve set for myself while writing this app

  • Create form-based application in PowerShell
  • Ensure that all ‘business logic’ for account creation is automated (OU location, group membership, etc.)
  • Ensure that there is as little typing as possible (Auto-concatenated display name, auto created alias, etc.)
  • To ease a pain for PowerShell adopters with creation of form-based application (One can re-use parts of my app to write something else)
  • Have no dependencies on AD-management snap-in (Use of ‘plain-Jane’ PowerShell would allow user to run it as-is without an additional dependencies and installs)

Non-Goals

Things that this ‘app’ is not…

  • Fool-Proofing (Although there is no end for error-proofing, I had to keep in mind that this is a ‘script’. PowerShell would throw plenty of nasty errors on the screen is something goes wrong.)
  • Full account management console (This is an app to create a user in AD, not edit a user or delete a user. I am sure it is more than possible to extend this to the full-blown 3rd party account management console… but why)

Business Logic

In my application I’ve used internal to Schakra assumptions. My system admin team is having set of internal rules for our internal account creation such as user location in AD is determined according to user’s employment type, account name and display names are calculated with particular formulas, group membership is pre-determined according to user’s employment status, etc. etc. All those things are easily modifiable and adjustable. Feel free to extend the application and adopt it for your internal use.

Source

Download script/app from Skydrive

CLS
Write-Host("Loading .NET assemblies...");

[System.Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") | out-null
[System.Reflection.Assembly]::Load("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") | out-null

function CreateDisplayName()
{
[System.String]$formattedDisplayName = [System.String]::Empty;
$formattedDisplayName = [System.String]::Format("{0} {1}", $textBoxFirst.Text.Trim(), $textBoxLast.Text.Trim());
$textBoxDisplayName.Text = $formattedDisplayName;
}

function CreateAlias()
{
if (0 -ne $textBoxLast.Text.Length)
{
[System.String]$formattedAlias = [System.String]::Empty;
$formattedAlias = [System.String]::Format("{0}{1}", $textBoxFirst.Text.Trim(), $textBoxLast.Text.Trim().Substring(0, 1));
$textBoxAlias.Text = $formattedAlias;
}
}

function Get-User
{
param
(
[Parameter( Mandatory=$true, Position=0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias("alias")] [String] $UserName,

[Parameter( Mandatory=$true, Position=2, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias("attribute")] [String] $AttributeName
)

[System.String] $filterSyntax = "(&(objectCategory=person)(objectClass=user)(" + $attributeName + "=" + $userName + "))";

$searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"");
$searcher.filter = $filterSyntax;
$searcher.CacheResults = $true;
$searcher.SearchScope = "Subtree";
$searcher.PageSize = 1000;
[System.DirectoryServices.SearchResult] $result = $searcher.FindOne();

if ($null -ne $result)
{
[System.DirectoryServices.DirectoryEntry]$entry = $result.GetDirectoryEntry()
Write-Host("Manager DN: " + $result.Path.Substring(7).Trim());
return $result;
}

return $null;
}

function ConvertADSLargeInteger([object] $adsLargeInteger)
{
$highPart = $adsLargeInteger.GetType().InvokeMember("HighPart", [System.Reflection.BindingFlags]::GetProperty, $null, $adsLargeInteger, $null)
$lowPart = $adsLargeInteger.GetType().InvokeMember("LowPart", [System.Reflection.BindingFlags]::GetProperty, $null, $adsLargeInteger, $null)

$bytes = [System.BitConverter]::GetBytes($highPart)
$tmp = [System.Byte[]]@(0,0,0,0,0,0,0,0)
[System.Array]::Copy($bytes, 0, $tmp, 4, 4)
$highPart = [System.BitConverter]::ToInt64($tmp, 0)

$bytes = [System.BitConverter]::GetBytes($lowPart)
$lowPart = [System.BitConverter]::ToUInt32($bytes, 0)

return $lowPart + $highPart
}

function UpdateFields()
{
CreateDisplayName;
CreateAlias;
}

function Form-OnSubmit
{
$result = Form-Validate;
if ($true -eq $result)
{
Form-Submit;
}
}

function Manager-OnClick
{
$value = $textBoxManager.Text.Trim();

if ([System.String]::IsNullOrEmpty($value))
{
Write-Host("Manager's name is not specified");
return;
}

$manager = Get-User -UserName $value -AttributeName "sAMAccountName";

if ($null -eq $manager)
{
$labelManager.ForeColor = [System.Drawing.Color]::Black;
Write-Host("Could not resolve manager's account with specified sAMAccountName: " + $value);
}
else
{
$labelManager.ForeColor = [System.Drawing.Color]::DarkGreen;
return;
}

$manager = Get-User -UserName $value -AttributeName "displayName";

if ($null -eq $manager)
{
$labelManager.ForeColor = [System.Drawing.Color]::Black;
Write-Host("Could not resolve manager's account with specified displayName: " + $value);
}
else
{
$labelManager.ForeColor = [System.Drawing.Color]::DarkGreen;
return;
}
}

function Form-Submit
{
[System.String]$methodName = 'Form-Submit';
Write-Host("Entering '" + $methodName + "' function");

[System.String]$dominaController = "LDAP://si-dc:389/dc=schakra,dc=int";
Write-Host("Connecting to " + $dominaController);

[ADSI]$domain = [ADSI] $dominaController
[System.String]$destinationOU = [System.String]::Empty;
[System.String]$country = $comboBoxLocation.SelectedItem.ToString();
[System.String]$employeeType = $comboBoxEmployeeType.SelectedItem.ToString()

Write-Host ("Country: " + $country);
Write-Host ("Employee Type: " + $employeeType);

[System.Text.StringBuilder]$builder = New-Object System.Text.StringBuilder;

$builder.Append("LDAP://OU=");

if ($employeeType -eq "Full Time Employee" -or $employeeType -eq "Intern")
{
$builder.Append("Users,");
}
else
{
$builder.Append("Vendors,");
}

if ($country -eq "US")
{
$builder.Append("OU=Schakra-US,");
}
else
{
$builder.Append("OU=Schakra-India,");
}

$builder.Append("DC=schakra,DC=int");
Write-Host ("Destination OU: "+ $builder.ToString());
[ADSI]$usersOU = [ADSI] $builder.ToString();

[System.String]$mailSuffix = "@schakra.com";
[System.String]$domainName = "@schakra.local";
Write-Host ("CN: " + "cn=" + $textBoxDisplayName.Text);

[System.DirectoryServices.DirectoryEntry]$user = $usersOU.Create("user","cn=" + $textBoxDisplayName.Text);
Write-Host($user.GetType());

$user.put("givenName", $textBoxFirst.Text);
$user.put("sn", $textBoxLast.Text);
$user.put("title", $textBoxTitle.Text);
$user.put("mail", $textBoxAlias.Text + $mailSuffix);
$user.put("targetAddress", $textBoxAlias.Text + $mailSuffix);
$user.put("displayName", $textBoxDisplayName.Text);
$user.put("sAMAccountName", $textBoxAlias.Text);
$user.put("userPrincipalName", $textBoxAlias.Text + $domainName);
$user.put("description", $employeeType);
$user.put("employeeType", $employeeType);

$manager = Get-User -UserName $textBoxManager.Text -AttributeName "sAMAccountName";
if ($null -eq $manager)
{
$manager = Get-User -UserName $textBoxManager.Text -AttributeName "displayName";
}

if ($null -ne $manager)
{
$user.put("manager", $manager.Path.Substring(7));
}

if ($country -eq "US")
{
$user.put("c","US");
$user.put("co","United States");
$user.put("countryCode", 840);
$user.put("physicalDeliveryOfficeName", "US - Redmond");
}
else
{
$user.put("c","IN");
$user.put("co","India");
$user.put("countryCode", 356);
$user.put("physicalDeliveryOfficeName", "India - Hyderabad");

}

if ($checkBoxHideFromGal.Checked -eq $True)
{
Write-Host("Hiding from GAL");
$user.put("msExchHideFromAddressLists", $True);
}

if ($checkBoxAllowVpn.Checked -eq $True)
{
Write-Host("Allowing VPN access");
$user.put("msNPAllowDialin", $True)
}

$user.SetInfo()

if ($checkBoxEnabled.Checked -eq $True)
{
$user.psbase.Invoke("SetPassword","YourPasswordValue");
$user.psbase.InvokeSet('Accountdisabled',$false);

if ($checkBoxChangePasswordOnNextLogin.Checked -eq $True)
{
Write-Host("Resseting password on the next logon");
$user.pwdLastSet = 0;
}

$user.psbase.CommitChanges();
}

# Adding user to his/her 'default' distribution group
[System.Text.StringBuilder]$distributionGroupuilder = New-Object System.Text.StringBuilder;
$distributionGroupuilder.Append("LDAP://");

if ($country -eq "US")
{
$distributionGroupuilder.Append("CN=US-");
}
else
{
$distributionGroupuilder.Append("CN=India-");
}

switch ($employeeType)
{
"Intern"
{
$distributionGroupuilder.Append("Interns,");
}

"Full Time Employee"
{
$distributionGroupuilder.Append("FTE,");
}

"Contractor/Vendor"
{
$distributionGroupuilder.Append("Vendors,");
}
}

$distributionGroupuilder.Append("OU=Distribution,OU=Groups,DC=schakra,DC=int");

[System.String]$distributionGroupPath = $distributionGroupuilder.ToString();

Write-Host("Adding user to the group: " + $distributionGroupPath);

$distributionGroup = [ADSI]$distributionGroupPath;
$distributionGroup.Add("LDAP://" + $user.distinguishedName);

Form-Exit;
Write-Host("Exiting '" + $methodName + "' function");
}

function Form-Exit
{
[System.String]$methodName = 'Form-Exit';

Write-Host("Entering '" + $methodName + "' function");
Write-Host("Closing Windows Form...");
$form.Close() | out-null
Write-Host("Exiting '" + $methodName + "' function");
}

function Form-Build
{
[System.String]$methodName = 'Form-Build';
Write-Host("Entering '" + $methodName + "' function");

[System.Windows.Forms.Button]$buttonCancel = New-Object System.Windows.Forms.Button
[System.Windows.Forms.Button]$buttonOK = New-Object System.Windows.Forms.Button
[System.Windows.Forms.Button]$buttonManager = New-Object System.Windows.Forms.Button;

[System.Windows.Forms.GroupBox]$distributionGroupBoxOther = New-Object System.Windows.Forms.GroupBox;

[System.Windows.Forms.CheckBox]$checkBoxAllowVpn = New-Object System.Windows.Forms.CheckBox;
[System.Windows.Forms.CheckBox]$checkBoxChangePasswordOnNextLogin = New-Object System.Windows.Forms.CheckBox;
[System.Windows.Forms.CheckBox]$checkBoxEnabled = New-Object System.Windows.Forms.CheckBox;
[System.Windows.Forms.CheckBox]$checkBoxHideFromGal = New-Object System.Windows.Forms.CheckBox;

[System.Windows.Forms.ComboBox]$comboBoxLocation = New-Object System.Windows.Forms.ComboBox;
[System.Windows.Forms.ComboBox]$comboBoxEmployeeType = New-Object System.Windows.Forms.ComboBox;
[System.Windows.Forms.ComboBox]$comboBoxDepartment = New-Object System.Windows.Forms.ComboBox;

[System.Windows.Forms.Label]$labelFirst = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelMiddleInitial = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelLast = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelDisplayName = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelAlias = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelTitle = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelDepartment = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelLocation = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelEmployeeType = New-Object System.Windows.Forms.Label;
[System.Windows.Forms.Label]$labelManager = New-Object System.Windows.Forms.Label;

[System.Windows.Forms.TextBox]$textBoxFirst = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxMiddleInitial = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxLast = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxDisplayName = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxAlias = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxTitle = New-Object System.Windows.Forms.TextBox;
[System.Windows.Forms.TextBox]$textBoxManager = New-Object System.Windows.Forms.TextBox;

$distributionGroupBoxOther.SuspendLayout | out-null

##
## labelFirst
##
$labelFirst.AutoSize = $true;
[System.Drawing.Point]$labelFirst.Location = New-Object System.Drawing.Point(11, 7);
$labelFirst.Name = "labelFirst";
[System.Drawing.Size]$labelFirst.Size = New-Object System.Drawing.Size(57, 13);
$labelFirst.Text = "First Name";

##
## textBoxFirst
##
[System.Drawing.Point]$textBoxFirst.Location = New-Object System.Drawing.Point(11, 23);
$textBoxFirst.Name = "textBoxFirst";
[System.Drawing.Size]$textBoxFirst.Size = New-Object System.Drawing.Size(122, 20);
$textBoxFirst.TabIndex = 1;
$textBoxFirst.add_TextChanged({UpdateFields})

##
## labelMiddleInitial
##
$labelMiddleInitial.AutoSize = $true;
[System.Drawing.Point]$labelMiddleInitial.Location = New-Object System.Drawing.Point(137, 7);
$labelMiddleInitial.Name = "labelMiddleInitial";
[System.Drawing.Size]$labelMiddleInitial.Size = New-Object System.Drawing.Size(25, 13);
$labelMiddleInitial.Text = "M.I."

##
## textBoxMiddleInitial
##
[System.Drawing.Point]$textBoxMiddleInitial.Location = New-Object System.Drawing.Point(138, 23);
$textBoxMiddleInitial.Name = "textBoxMiddleInitial";
[System.Drawing.Size]$textBoxMiddleInitial.Size = New-Object System.Drawing.Size(42, 20);
$textBoxMiddleInitial.TabIndex = 2;

##
## labelLast
##
$labelLast.AutoSize = $true;
[System.Drawing.Point]$labelLast.Location = New-Object System.Drawing.Point(183, 7);
$labelLast.Name = "labelLast";
[System.Drawing.Size]$labelLast.Size = New-Object System.Drawing.Size(58, 13);
$labelLast.Text = "Last Name";

##
## textBoxLast
##
[System.Drawing.Point]$textBoxLast.Location = New-Object System.Drawing.Point(186, 23);
$textBoxLast.Name = "textBoxLast";
[System.Drawing.Size]$textBoxLast.Size = New-Object System.Drawing.Size(119, 20);
$textBoxLast.TabIndex = 3;
$textBoxLast.add_TextChanged({UpdateFields})

##
## labelDisplayName
##
$labelDisplayName.AutoSize = $true;
[System.Drawing.Point]$labelDisplayName.Location = New-Object System.Drawing.Point(11, 46);
$labelDisplayName.Name = "labelDisplayName";
[System.Drawing.Size]$labelDisplayName.Size = New-Object System.Drawing.Size(72, 13);
$labelDisplayName.Text = "Display Name";

##
## textBoxDisplayName
##
[System.Drawing.Point]$textBoxDisplayName.Location = New-Object System.Drawing.Point(11, 62);
$textBoxDisplayName.Name = "textBoxDisplayName";
[System.Drawing.Size]$textBoxDisplayName.Size = New-Object System.Drawing.Size(294, 20);
$textBoxDisplayName.TabIndex = 4;

##
## labelAlias
##
$labelAlias.AutoSize = $true;
[System.Drawing.Point]$labelAlias.Location = New-Object System.Drawing.Point(11, 85);
$labelAlias.Name = "labelAlias";
[System.Drawing.Size]$labelAlias.Size = New-Object System.Drawing.Size(29, 13);
$labelAlias.Text = "Alias";

##
## textBoxAlias
##
[System.Drawing.Point]$textBoxAlias.Location = New-Object System.Drawing.Point(11, 101);
$textBoxAlias.Name = "textBoxAlias";
[System.Drawing.Size]$textBoxAlias.Size = New-Object System.Drawing.Size(119, 20);
$textBoxAlias.TabIndex = 5;

##
## labelTitle
##
$labelTitle.AutoSize = $true
[System.Drawing.Point]$labelTitle.Location = New-Object System.Drawing.Point(137, 85);
$labelTitle.Name = "labelTitle";
[System.Drawing.Size]$labelTitle.Size = New-Object System.Drawing.Size(27, 13);
$labelTitle.Text = "Title";

##
## textBoxTitle
##
[System.Drawing.Point]$textBoxTitle.Location = New-Object System.Drawing.Point(140, 101);
$textBoxTitle.Name = "textBoxTitle";
[System.Drawing.Size]$textBoxTitle.Size = New-Object System.Drawing.Size(165, 20);
$textBoxTitle.TabIndex = 6;

##
## labelDepartment
##
$labelDepartment.AutoSize = $true;
[System.Drawing.Point]$labelDepartment.Location = New-Object System.Drawing.Point(11, 124);
$labelDepartment.Name = "labelDelartment";
[System.Drawing.Size]$labelDepartment.Size = New-Object System.Drawing.Size(62, 13);
$labelDepartment.Text = "Department";

##
## comboBoxDepartment
##
$comboBoxDepartment.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$comboBoxDepartment.FormattingEnabled = $true
[System.Drawing.Point]$comboBoxDepartment.Location = New-Object System.Drawing.Point(11, 140)
$comboBoxDepartment.Name = "comboBoxDepartment"
[System.Drawing.Size]$comboBoxDepartment.Size = New-Object System.Drawing.Size(119, 21)
$comboBoxDepartment.TabIndex = 7;

## Populating combo-box with values
[System.Array]$departmentItems = "Products","Services";
ForEach ($item in $departmentItems)
{
$comboBoxDepartment.Items.Add($item) | out-null
}

##
## labelLocation
##
$labelLocation.AutoSize = $true;
[System.Drawing.Point]$labelLocation.Location = New-Object System.Drawing.Point(137, 124);
$labelLocation.Name = "labelLocation";
[System.Drawing.Size]$labelLocation.Size = New-Object System.Drawing.Size(48, 13);
$labelLocation.Text = "Location";

##
## comboBoxLocation
##
$comboBoxLocation.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList;
$comboBoxLocation.FormattingEnabled = $true;
$comboBoxLocation.Location = New-Object System.Drawing.Point(140, 140);
$comboBoxLocation.Name = "comboBoxLocation";
$comboBoxLocation.Size = New-Object System.Drawing.Size(165, 21);
$comboBoxLocation.TabIndex = 8;

## Populating combo-box with values

[System.Array]$locationItems = "US", "India";
ForEach ($item in $locationItems )
{
$comboBoxLocation.Items.Add($item) | out-null
}

##
## labelEmployeeType
##
$labelEmployeeType.AutoSize = $true
[System.Drawing.Point]$labelEmployeeType.Location = New-Object System.Drawing.Point(11, 164)
$labelEmployeeType.Name = "labelEmployeeType"
[System.Drawing.Size]$labelEmployeeType.Size = New-Object System.Drawing.Size(80, 13)
$labelEmployeeType.Text = "Employee Type";

##
## comboBoxEmployeeType
##
$comboBoxEmployeeType.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList;
$comboBoxEmployeeType.FormattingEnabled = $true;
[System.Drawing.Point]$comboBoxEmployeeType.Location = New-Object System.Drawing.Point(11, 180);
$comboBoxEmployeeType.Name = "comboBoxEmployeeType";
[System.Drawing.Size]$comboBoxEmployeeType.Size = New-Object System.Drawing.Size(119, 21);
$comboBoxEmployeeType.TabIndex = 10;
[System.Array]$EmployeeTypeItems = "Full Time Employee","Contractor/Vendor", "Intern";
ForEach ($Item in $EmployeeTypeItems )
{
$comboBoxEmployeeType.Items.Add($Item) | out-null
}

##
## labelManager
##
$labelManager.AutoSize = $true;
$labelManager.Location = New-Object System.Drawing.Point(137, 164);
$labelManager.Name = "labelManager";
$labelManager.Size = New-Object System.Drawing.Size(49, 13);
$labelManager.Text = "Manager";

##
## textBoxManager
##
$textBoxManager.Location = New-Object System.Drawing.Point(140, 180);
$textBoxManager.Name = "textBoxManager";
$textBoxManager.Size = New-Object System.Drawing.Size(140, 20);
$textBoxManager.TabIndex = 11;

##
## buttonManager
##
$buttonManager.FlatStyle = [System.Windows.Forms.FlatStyle]::System;
$buttonManager.Location = New-Object System.Drawing.Point(284, 181);
$buttonManager.Margin = New-Object System.Windows.Forms.Padding(1);
$buttonManager.Name = "buttonManager";
$buttonManager.Size = New-Object System.Drawing.Size(21, 20);
$buttonManager.TabIndex = 12;
$buttonManager.Text = "...";
$buttonManager.TextAlign = [System.Drawing.ContentAlignment]::BottomLeft;
$buttonManager.UseVisualStyleBackColor = $true;
$buttonManager.Add_Click({Manager-OnClick});
##
## distributionGroupBoxOther
##
$distributionGroupBoxOther.Controls.Add($checkBoxAllowVpn);
$distributionGroupBoxOther.Controls.Add($checkBoxChangePasswordOnNextLogin);
$distributionGroupBoxOther.Controls.Add($checkBoxEnabled);
$distributionGroupBoxOther.Controls.Add($checkBoxHideFromGal);
[System.Drawing.Point]$distributionGroupBoxOther.Location = New-Object System.Drawing.Point(11, 215);
$distributionGroupBoxOther.Name = "distributionGroupBoxOther";
[System.Drawing.Size]$distributionGroupBoxOther.Size = New-Object System.Drawing.Size(294, 72);
$distributionGroupBoxOther.TabStop = $false;
$distributionGroupBoxOther.Text = "Additional Settings";

##
## checkBoxEnabled
##
$checkBoxEnabled.AutoSize = $true;
$checkBoxEnabled.Checked = $true;
$checkBoxEnabled.Name = "checkBoxEnabled";
[System.Drawing.Point]$checkBoxEnabled.Location = New-Object System.Drawing.Point(6, 19);
[System.Drawing.Size]$checkBoxEnabled.Size = New-Object System.Drawing.Size(65, 17);
$checkBoxEnabled.TabIndex = 13;
$checkBoxEnabled.Text = "Enabled";
$checkBoxEnabled.UseVisualStyleBackColor = $true;

##
## checkBoxAllowVpn
##
$checkBoxAllowVpn.AutoSize = $true;
$checkBoxAllowVpn.Checked = $true;
[System.Drawing.Point]$checkBoxAllowVpn.Location = New-Object System.Drawing.Point(6, 42);
$checkBoxAllowVpn.Name = "checkBoxAllowVpn";
[System.Drawing.Size]$checkBoxAllowVpn.Size = New-Object System.Drawing.Size(76, 17);
$checkBoxAllowVpn.TabIndex = 14;
$checkBoxAllowVpn.Text = "Allow VPN";
$checkBoxAllowVpn.UseVisualStyleBackColor = $true;

##
## checkBoxChangePasswordOnNextLogin
##
$checkBoxChangePasswordOnNextLogin.AutoSize = $true;
$checkBoxChangePasswordOnNextLogin.Checked = $true;
[System.Drawing.Point]$checkBoxChangePasswordOnNextLogin.Location = New-Object System.Drawing.Point(109, 19);
$checkBoxChangePasswordOnNextLogin.Name = "checkBoxChangePasswordOnNextLogin";
[System.Drawing.Size]$checkBoxChangePasswordOnNextLogin.Size = New-Object System.Drawing.Size(178, 17);
$checkBoxChangePasswordOnNextLogin.TabIndex = 15;
$checkBoxChangePasswordOnNextLogin.Text = "Change password on next logon";
$checkBoxChangePasswordOnNextLogin.UseVisualStyleBackColor = $true;

##
## checkBoxHideFromGal
##
$checkBoxHideFromGal.AutoSize = $true;
[System.Drawing.Point]$checkBoxHideFromGal.Location = New-Object System.Drawing.Point(109, 42);
$checkBoxHideFromGal.Name = "checkBoxHideFromGal";
[System.Drawing.Size]$checkBoxHideFromGal.Size = New-Object System.Drawing.Size(98, 17);
$checkBoxHideFromGal.TabIndex = 16;
$checkBoxHideFromGal.Text = "Hide From GAL";
$checkBoxHideFromGal.UseVisualStyleBackColor = $true;

##
## buttonCancel
##
[System.Drawing.Point]$buttonCancel.Location = New-Object System.Drawing.Point(233, 296);
$buttonCancel.Name = "buttonCancel";
[System.Drawing.Size]$buttonCancel.Size = New-Object System.Drawing.Size(75, 23);
$buttonCancel.TabIndex = 17
$buttonCancel.Text = "Cancel"
$buttonCancel.UseVisualStyleBackColor = $true;
$buttonCancel.Add_Click({Form-Exit});

##
## buttonOK
##
[System.Drawing.Point]$buttonOK.Location = New-Object System.Drawing.Point(151, 296)
$buttonOK.Name = "buttonOK"
[System.Drawing.Size]$buttonOK.Size = New-Object System.Drawing.Size(75, 23)
$buttonOK.TabIndex = 18
$buttonOK.Text = "OK"
$buttonOK.UseVisualStyleBackColor = $true;
$buttonOK.Add_Click({Form-OnSubmit});

Write-Host("Generating form");

#
#Form1
#
[System.Windows.Forms.Form]$Form = New-Object System.Windows.Forms.Form;
$Form.ClientSize = New-Object System.Drawing.Size(320, 330);
$Form.Controls.Add($comboBoxDepartment);
$Form.Controls.Add($labelDepartment);
$Form.Controls.Add($labelEmployeeType);
$Form.Controls.Add($comboBoxEmployeeType);
$Form.Controls.Add($labelLocation);
$Form.Controls.Add($comboBoxLocation);
$Form.Controls.Add($textBoxMiddleInitial);
$Form.Controls.Add($labelMiddleInitial);
$Form.Controls.Add($textBoxDisplayName);
$Form.Controls.Add($labelDisplayName);
$Form.Controls.Add($distributionGroupBoxOther);
$Form.Controls.Add($textBoxTitle);
$Form.Controls.Add($textBoxAlias);
$Form.Controls.Add($textBoxLast);
$Form.Controls.Add($textBoxFirst);
$Form.Controls.Add($labelTitle);
$Form.Controls.Add($labelAlias);
$Form.Controls.Add($labelLast);
$Form.Controls.Add($labelFirst);
$Form.Controls.Add($labelManager);
$Form.Controls.Add($textBoxManager);
$Form.Controls.Add($buttonManager);
$Form.Controls.Add($buttonOK);
$Form.Controls.Add($buttonCancel);

$Form.MaximizeBox = $false;
$Form.Name = "Form01";
$Form.ShowIcon = $false;
$Form.Text = "Create new Active Directory user";
$Form.ShowDialog() | Out-Null

Write-Host("Exiting '" + $methodName + "' function");
}

function Form-Validate
{
[System.String] $methodName = "Form-Validate";
Write-Host("Entering " + $methodName + " function");

[System.Boolean] $havingFirst = $false;
[System.Boolean] $havingLast = $false;
[System.Boolean] $havingDisplay = $false;
[System.Boolean] $havingAlias = $false;
[System.Boolean] $havingDepartment = $false;
[System.Boolean] $havingLocation = $false;
[System.Boolean] $havingEmployeeType = $false;

##
## FirstName
##
Try
{
if([System.String]::IsNullOrEmpty( $textBoxFirst.Text) )
{
$labelFirst.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'givenName' (First Name) is not specified");
$havingFirst = $false;
}
else
{
$labelFirst.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'givenName' (First Name) is OK");
$havingFirst = $true;
}

}
Catch [System.Exception]
{
$labelFirst.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'givenName' (First Name) is not specified");
$havingFirst = $false;
}
##
## LastName
##
Try
{
if([System.String]::IsNullOrEmpty( $textBoxLast.Text) )
{
$labelLast.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'sn' (Last/Family Name/Surname) is not specified");
$havingLast = $false;

}
else
{
$labelLast.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'sn' (Last/Family Name/Surname) is OK");
$havingLast = $true;
}

}
Catch [System.Exception]
{
$labelLast.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'sn' (Last/Family Name/Surname) is not specified");
$havingLast = $false;
}

##
## DisplayName
##
Try
{
if([System.String]::IsNullOrEmpty( $textBoxDisplayName.Text))
{
$labelDisplayName.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'DisplayName' is not specified");
$havingDisplay = $false;

}
else
{
$labelDisplayName.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'DisplayName' is OK");
$havingDisplay = $true;
}

}
Catch [System.Exception]
{
$labelDisplayName.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'DisplayName' is not specified");
$havingDisplay = $false;
}

##
## Alias
##
Try
{
if([System.String]::IsNullOrEmpty( $textBoxAlias.Text) )
{
$labelAlias.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Alias' is not specified");
$havingAlias = $flase;

}
else
{
$labelAlias.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'Alias' is OK");
$havingAlias = $true;
}

}
Catch [System.Exception]
{
$labelAlias.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Alias' is not specified");
$havingAlias = $false;
}

##
## Department
##
Try
{
if([System.String]::IsNullOrEmpty( $comboBoxDepartment.SelectedItem) )
{
$labelDepartment.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Department' is not specified");
$havingDepartment = $false;
}
else
{
$labelDepartment.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'Department' is OK");
$havingDepartment = $true;
}
}
Catch [System.Exception]
{
$labelDepartment.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Department' is not specified");
$havingDepartment = $false;
}

##
## Location
##
Try
{
if([System.String]::IsNullOrEmpty($comboBoxLocation.SelectedItem) )
{
$labelLocation.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Location' is not specified");
$havingLocation = $false;
}
else
{
$labelLocation.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'Location' is OK");
$havingLocation = $true;
}
}
Catch [System.Exception]
{
$labelLocation.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'Location' is not specified");
$havingLocation = $false;
}

##
## EmployeeType
##
Try
{
if([System.String]::IsNullOrEmpty( $comboBoxEmployeeType.SelectedItem) )
{
$labelEmployeeType.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'EmployeeType' is not specified");
$havingEmployeeType = $false;

}
else
{
$labelEmployeeType.ForeColor = [System.Drawing.Color]::Black;
Write-Host("'EmployeeType' is OK");
$havingEmployeeType = $true;
}

}
Catch [System.Exception]
{
$labelEmployeeType.ForeColor = [System.Drawing.Color]::Red;
Write-Host("'EmployeeType' is not specified");
$havingEmployeeType = $false;
}

#Write-Host("Exiting " + $methodName + " function");
#Write-Host("havingFirst: " + $havingFirst);
#Write-Host("havingLast: " + $havingLast);
#Write-Host("havingDisplay: " + $havingDisplay);
#Write-Host("havingAlias: " + $havingAlias);
#Write-Host("havingDepartment: " + $havingDepartment);
#Write-Host("havingLocation:" + $havingLocation);
#Write-Host("havingEmployeeType: " + $havingEmployeeType);
return $havingFirst -and $havingLast -and $havingDisplay -and $havingAlias -and $havingDepartment -and $havingLocation -and $havingEmployeeType;
}

Form-Build;

Happy coding!

Metaverse Router 1.1

I have updated Metaverse Router code on CodePlex. One bug was fixed “XML Tag Capitalization”; minor but nasty little bug that was throwing exceptions during initialization of the provisioning modules. I have also updated the solution and project to Visual Studio 2010 with WIX 3.5 for an MSI building purposes.