Trying to prove that Skynet should be running on PowerShell!

Category Archives: Citrix

This can be quite hard in a large organisation. It’s one thing to migrate the ACLs to Office 365 one time, it’s another thing to keep them updated.

At least I was kind of lost on how to tackle this problem in the beginning.

This is probably not the perfect solution, but it saves us a lot of time!

Short version (everything in the list below is done by powershell):

The shared mailbox user account gets created by a powershell script that reads the output of the order form (which currently gets approved/created by helpdesk).

An access group gets created

An owner group gets created

The ACLs of the access group is changed so the owner group has access to change it’s members, and the “Managed By”-attribute is set.

The owner group becomes a member of another group, which gives access to a powershell form published in our Citrix-farm. This form is used for managing the membership of the mailbox access group.

The owner (typically the person who ordered the mailbox) gets added to Owner-group and Access-group.

Another script looks for new access groups and shared mailboxes, finds it in Exchange Online/Azure, creates the shared mailbox and assigns the “Full Access/Send As”-rights to the “access group”.

All the ACLs are verified to make sure everything went according to plan.

If everything has been done correctly, an e-mail gets sent to the members of the “owner-group” with a link to a guide explaining where to find the Citrix app (PowerShell form), how to add the new mailbox in outlook etc….

The PowerShell-form, when started by a user, finds all the “Owner-groups” the current user is a member of and lists the corresponding mailboxes in a droplist. When a mailbox is selected, it lists the members and allows the user to add new ones and remove current ones.

You search by entering a Name, E-mailaddress or SamAccountName, the search goes off “in real time” (OnChange), no search button.

Here’s a screenshot of the form when started:

This is how it looks when a mailbox is selected: (sorry for all the blurring…)

This allows any user to manage their own mailbox in an easy and userfriendly way, and they dont need to contact helpdesk everytime someone else needs access to the mailbox, or needs to be removed.

And that’s it! 🙂

I will try to do some blog posts on the steps involved in this process, at least those who were kind of tricky to achieve. (Setting ACLs in AD was not as straightforward as I thought…)

Any code that I think is applicable for someone else will of course be published!

Even if you configure your User Profile Manager in Citrix correctly, keep it up date and so on, you might end up with the same problem we had; every now and then a profile contains a file that is locked so the profile doesn’t get cleaned up after user log off.

When that user logs on again they might end up with a “username.domain001”-profile, then 002 and so on. And the user profile settings soon become pretty messy.

One way of making this problem less of a pain, is to have a script clean up the folders (and of course the registry values) to make sure the users can get their profiles loaded correctly.

As always, use any script you find on the internet with caution, and test them fully before deploying anything in your production environment.

A script walkthrough follows:

First of all, I usually set the variables that might differ from different environments and/or domains etc.

Most of these are pretty obvious in this script, but one that might require some explanation is this one:

This just collects all the local users on a server/computer. We didn’t want these profiles to get cleaned up since they don’t have any central profiles.

The next ‘weird’ one:

# Tune performance with $SpeedBrake. Lower is quicker, but uses more CPU.
$SpeedBrake=1

This variable is used in a “Start-Sleep”-cmdlet later, this is to make sure the script doesn’t steal a lot of CPU-resources.

The next one is farily obvious, but I’ll explain it anyway:

# Add a regex that works for your usernaming standard
$UserNameRegEx="\w"

This should be changed to match whatever you have as a standard for your SamAccountNames. the “\w” will more or less match anything, so this should be changed to something that matches your environment. This is just used for extra safety, you might not want to end up deleting a service account profile for example.

Speaking of service accounts, if you have a naming standard for those, add it here:

# Add a list of other accounts you want to exclude
$ExcludedUsers="Public","ctx","svc"

If the account name contains for example “svc”, it will be ignored by the script.

But what about logged on users? We don’t want to remove their profiles, do we?
The hard thing about this, is that there was no easy way (like a cmdlet) to list logged on users. (at least not when I wrote this script a while back), so I went with the solution of listing all current processes and their owners, and select those that are unique. That looks like this:

Now we should have all the information we need to safely go through all the profiles and remove those that we don’t want anymore.

I wont go through this part “line by line”, but I think you will get the point when reading the code comments.

The first part of the code looks like this:

# Start to loop through all the profile folders
foreach ($LocalProfileFolder in $LocalProfileFolders)
{
# Sleep to prevent CPU load
sleep -m $SpeedBrake
# Set this variable to True, it will be changed if it should stay later.
$ThisProfileShouldBeDeleted=$True
# This this folder match the username regex?
if ($LocalProfileFolder.Name -match $UserNameRegEx)
{
# Make sure it doesn't match any of the "ignored" users, (logged on ones etc...)
foreach ($UserToIgnore in $UsersToIgnore)
{
# Again, sleep to prevent CPU load.
sleep -m $SpeedBrake
# Check if it matches a "ignored" user
if ($LocalProfileFolder.Name -like "*$UserToIgnore*")
{
# If it did, it should not be deleted.
$ThisProfileShouldBeDeleted=$False
}
}

So it starts by setting $ThisProfileShouldBeDeleted to $True. It then does a couple of checks (regex matching etc) to make sure that the users profile is OK to delete. (If not, it sets $ThisProfileShouldBeDeleted to false.)

A few things to point out, the script always tries to delete the profile through WMI since this is the “cleanest” way of doing this (removes the registry values together with the folder). This is the same thing as going through “My Computer” to remove the profile.

If there was no “WMI-profile”, it just deletes the folder. I know it looks terrible when using “cmd /c rd /s /q” instead of Remove-Item to do this, but Remove-Item has a bug that makes it a bad idea to use it for this sort of thing. (It has to do with how it handles symbol links).