About the Author
Author

stoff

Get All MSOLRoleMembers

This is a small little script I wrote for going through all administrator roles in your O365 tenant and listing out the members of each. This can be handy if you feel like you’re losing control over who has what permission in the tenant or someone says the classic “I want what he has”.

$DateStamp = Get-Date -Format "yyyy-MM-dd-HH-mm"
$LogFile = ("C:\temp\get_all_msolrolemembers-" + $DateStamp + ".csv")

# Defining the log function
Function LogWrite
{
	Param ([string]$logstring)
	Add-content $Logfile -value $logstring
}
LogWrite ("msolrole;email;displayname;islicensed")

$msolroles = get-msolrole
foreach($role in $msolroles)
{
	$rolemembers = get-msolrolemember -roleobjectid $role.objectid
	foreach($rolemember in $rolemembers)
	{
		LogWrite ($role.name + ";" + $rolemember.emailaddress + ";" + $rolemember.DisplayName + ";" + $rolemember.islicensed +";")
	}
}

Licensed Shared mailboxes

SCENARIO
You’re managing Office 365 for a company. You start seeing those licenses count down and you don’t know where they are going. Then it’s time to check if you have “Shared mailboxes” that are licensed!

PROBLEM
The problem here is that sometimes user mailboxes are converted to a shared mailbox. Maybe it’s an employee that left but you still want to access the mailbox, or maybe the mailbox was accidentally created as a user mailbox to begin with. And Microsoft even has a button in Exchange Online for converting to Shared mailboxes! But the problem is that button does indeed convert it – but it’s not deactivating the license! This is probably working as intended as deactivating the license has some other affects like legal hold and other services.

SOLUTION
This little command will list the mailboxes that are tagged as Shared mailboxes and lookup if their Azure AD object is licensed or not. It requires you to already have a remote PS session with Exchange Online as well as a connecting to MSOL service:

Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails SharedMailbox | Get-MsolUser | Where-Object { $_.isLicensed -eq "TRUE" }

Then you may want to write something like this to automatically remove the licenses. Change “yourlicenseplan” to.. well, your license plan 🙂

Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails SharedMailbox | Get-MsolUser | Where-Object { $_.isLicensed -eq "TRUE" } | foreach {Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -RemoveLicenses "yourlicenseplan:ENTERPRISEPACK"}

Credit goes to Mohammed Wasay (https://www.mowasay.com/2016/03/office365-get-a-list-of-shared-mailboxes-that-are-accidentally-licensed/).

SharePoint 2013 error “Exception from HRESULT: 0x80131401”

SCENARIO
After patching a SharePoint server with normal OS patches and reboot you are no longer able to browse to the applications or Central Admin. When looking at the log you see this error from C2WTS:
“An exception occurred when trying to issue security token: Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401).”
This was on a normal SharePoint Foundation 2013 server (build 15.0.4569.1506)

PROBLEM
If you check this TechNet forum post it seems to be related to “third party monitoring tools”. Unfortunately, SCOM is considered a third party tool in this case. And as it happens, we have just upgraded to SCOM2016!

SOLUTION
According to the TechNet forum post (and this official MS post) you should update or disable any third party monitoring tool. So, uninstalling the SCOM monitoring agent, rebooting, reinstalling it with “NOAPM=1” parameter will solve the issue (atleast it did for me).
However, if that it not an option (sometimes you can’t just reboot a critical server!), disabling Load Optimization does work, even if means your SharePoint is now unsupported. So I’m posting this for all us “it needs to be fixed now and I can’t find, update or disable whatever DLL is causing this!”-techies! So setting these registry keys works:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework, create a new ‘DWORD (32-bit) Value’ named “LoaderOptimization” with a value of “1”.
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework, create a new ‘DWORD (32-bit) Value’ named “LoaderOptimization” with a value of “1”.

But as those MS people will tell you, it really isn’t a recommended solution (which is weird since it originated from MS support!).

New-MSOLUserPrincipalName

SCENARIO
You’re changing the e-mail domain of a user or even a bunch of users. After that you also need to set their UPN’s to reflect the change.

PROBLEM
The problem is that Azure AD Connect service doesn’t currently support changing domain of a UPN of an object that is already synced! So you have to run a powershell command to change it. But it get’s even more complicated because you can’t change the UPN from one federated domain to another without making it “unfederated” first.

SOLUTION
Enter New-MSOLUserPrincipalName, which is a function that will take the user with the current UPN ($UserPrincipalName), change it to a temporary UPN with the domain extension “@[your tenant].onmicrosoft.com” and change it to the new UPN ($NewUserPrincipalName).

function New-MSOLUserPrincipalName {
  param (
    $UserPrincipalName,
    $NewUserPrincipalName
  )
  $TempUPN = "{0}@[your tenantname].onmicrosoft.com" -f $UserPrincipalName.split("@")
  Set-MsolUserPrincipalName -UserPrincipalName $UserPrincipalName -NewUserPrincipalName $TempUPN | Out-Null
  Set-MsolUserPrincipalName -UserPrincipalName $TempUPN -NewUserPrincipalName $NewUserPrincipalName
  Write-Output -InputObject "Successfully changed UPN from $UserPrincipalName to $NewUserPrincipalName"
}   

Thanx to Johan Dahlbom for this one!

Download PS1 from Dropbox

Download PS1 from Dropbox

Star Wars – Rogue One

I finally did it! I finally saw “Star Wars Rogue One”. Or “Star Wars Episode 3.9” as I’d call it! As a huge fan of the original triology I was definitely looking forward to seeing it but for one reason or another (one being my son’s refusal to see a movie he wasn’t allowed by the authorities to see!) it never happened when it was playing in the cinemas. And I certainly didn’t want to see a low quality “grabbed from the internet” version of the movie.

First off – spoiler warning! There are some spoilers below so don’t go there unless you’ve already seen the movie or don’t care about having it spoilt!

All in all – I was positively surprised at how good it was! I don’t know why but my expectations weren’t that great, probably because Episode VII was such a disappointment. But this one was really, really good.

And if you know me well enough you know one thing I love is continuity! Screwing up, or even ignoring continuity, can get me to dislike an otherwise good movie or TV show. Or in the case of Babylon 5 absolutely love a TV show that really isn’t that great once you remove the 5 story arc. And in this case most continuity I felt was acceptable, as expected there were tons of great references to Episode IV – one of the smaller ones being Bail Organa saying he’s going back to Alderaan and I spontaneously scream “don’t do it!!”. The other thing being the lengths they went to to have Tarkin and Leia in this movie when neither was actually in it! (there were ofcourse other characters that were “brought back” from the original triology, like Mon Mothma)

But another pitfall of trying to adhere to continuity is you can’t create characters or major plots without.. well, killing them before the end of the movie. And I’m sorry if this spoils it for the people that haven’t seen it but when they have a rebel meeting about wether to extract the Death Stars plan you can just go around the table and you know, based on who’s in Episode IV, who’s going to make it back alive! So in that way you kind of knew how the ending was going to be. And to my surprise they did the un-Hollywoodian (is that even a word!) thing and stuck with it!

And regarding Tarkin and Leia who were both computer generated faces superimposed on other actors.. I don’t know why the brain is so god damn good at it but you definitely saw that there some something “off” about their faces. Most notably Leia, even though it was just a few seconds and one line you saw that it wasn’t quite right. Great that they tried but it seems like an impossible task because the brain is just too good at face recognition for it to work.

Now – Darth Vader… well what can you say about Darth Vader… the problem with this movie is that the “original trilogy Darth Vader” was tall, imposing but not one for the front lines and certainly not a killing machine. That would have been more a Darth Vader from Episode 3.2 or something. But this movie ends a few days, maybe even hours, ahead of the first scene in Episode IV. But the original Darth Vader sent in his troops and never went in first himself, both the boarding in Episode IV and invasion of Hoth showed that. So ending it with a Darth Vader killing machine, even though it was cool as hell, didn’t really line up with the first scene of Episode IV. And it felt just .. misplaced somehow. But even though I’m a sucker for continuity I have to say that it was so damn cool that I’m gonna forgive that because sometimes rule of cool wins 🙂

Upgrading AD FS 2012R2 to 2016

SCENARIO
You have a working ADFS farm running version 3 on Windows 2012R2 and want to upgrade to ADFS 2016 delivered in Windows Server 2016.

PROBLEM
The problem is that this is, if you ask Microsoft, a very straight forward “next-next-finish” process to do as the only TechNet article I found about it makes it look pretty straight forward. But that article was written for Windows Internal Database (there is now also one for SQL cluster backend. Also you’ll notice at the bottom that it’s written for Technical Preview of Windows Server 2016 and also assumed you have no AD group policies that may break stuff! So there are still alot of things that can, and will, go wrong if you follow that procedure.

SOLUTION
There really isn’t one solution since there are so many issues you may run into but I managed to work through them all. But here are my comments to the TechNet article and where things went wrong for me:
2) It’s never showing in a screenshot but it is shown in the next – you have to chose to join an existing farm, the default option is creating a new farm which is a totally different thing!
But even after going through the setup process succesfully after patching and rebooting I got the error 1297 “A privilege that the service requires to function properly does not exist in the service account configuration. You may use the Services Microsoft Management Console (MMC) snap-in (services.msc) and the Local Security Settings MMC snap-in (secpol.msc) to view the service configuration and the account configuration“. As it turns out, this is a policy issue with the Windows Server 2016 baseline that limits who and what can “Log on as a service” and “Generate a security audit”. Creating an override policy for this and adding the service account running the AD FS service solved this issue for me! (thanks to https://blogs.technet.microsoft.com/pie/2015/09/04/adfs-refuses-to-start-error-1297/)
3) This is actually very important later on knowing which server is primary and not!
4) and 5) These are confirmed as not required if you’re running a SQL cluster backend. However, you still need to check later for which server is primary and not.
6) This entire Powershell is just wrong and not accepted at all, atleast in my environment! You’re much better off starting the Remote Access Manager and starting the Wizard from there. This will allow you to chose the certificate in a dropdown without knowing the thumbprint. But this is where I ran into problems and lot’s of them!

The first problem I had when configuring the WAP was connectivity resulting in the error “An error occurred when attempting to establish a trust relationship with the federation service. Error: Unable to connect to the remote server”. This was first due to physical firewall, then the local firewall policy settings and in the end that the service itself was down! So this was basically alot network issues, not the biggest thing in the world.

Now that that was done with I ran into the next problem that caused so much headache for me – “An error occurred when attempting to establish a trust relationship with the federation service. Error: Unauthorized. Verify that the service account has administrative access on the target Federation Server.”! The account that the WAP uses to connect to the internal AD FS server with that has to be a local user and local admin account on the internal AD FS server (since the WAP server shouldn’t be a member of the same domain as the internal AD FS servers). The problem is that there is a group policy baseline for Windows Server 2016 that denies logon from the network for all local users (“Deny access to this computer from the network“)! This resulted in the error since it wasn’t allowed to login with anything but the console! Setting that to only “Guest” should be enough for this.

So after getting that problem solved I got the next error – “An error occurred when attempting to establish a trust relationship with the federation service. Error: Internal Server Error“. Looking at all logs and events and I couldn’t figure out what tha hell was causing this issue. Well, as it turns out it was related to step 4 and 5 which you shouldn’t have done if you’re running SQL backend! When you point to the internal AD FS service address (the web address sts.xxxxxxx.com) you’re supposed to use a host file to control that and point it to the load balanced IP address. Well when I did that I always ended up on a server that was NOT the primary computer and therefor I couldn’t add the WAP! When I changed the host file to point directly to the IP of a server that was Primary computer for the farm it worked! Just remember to change this back since you don’t want the WAP servers point to one specifik AD FS server.

That is as far as I’ve gotten as the rest of the upgrade involves upgrading the forest and domain schema which I’m really not ready to do.

Selling The Old Car or Beware of “vikoperdinbil.se”

So now that we have our new car we begin the task of selling off our old car. We’ve tried selling off old cars ourselves before and it’s never ended well. I expect too much professionalism for that when we’re talking about this much money and I’ve always ended up with the complete opposite so I didn’t want to go the private route. Even though it means getting less I wanted to sell it to a dealer who could do the work. After trying out different “what’s my car worth” sites I ended up trying out a company called “Vi Köper Din Bil” (“we buy your car”) with the website “vikoperdinbil.se”. I’m typing it there because my hopes are anyone googling it will see this and stay away!!

On their website you simply enter the model, make, year and mileage of your car and they will guestimate it’s worth. For our Seat Leon they guestimated about 112.000:- “plus any extra options” which we had plenty of on that car. That’s about half of what we paid for it three years later but sounded ok. I mean the “street value” of the car would be 130.000:- but they needed a cut of that so ofcourse I couldn’t get that. But based on that estimate I made an appointment to take my car in to get a proper go-through and evaluation. I took time off work, I cleaned the car, loaded her up with the summer tyres and coordinated with the wife to come pick me up afterwards. But at the station they went through it (and didn’t find anything wrong with it at all), sent everything off to their expert who came back with an offer. 90.000:-! That’s 22.000 less, or more accurately 22% less, than their gustimate which included the comment “plus any extra options”!

Their business strategy is pretty obvious – give customers an optimistic guestimations and then when they’ve take the time and make the effort of going into their station they can just slash 20% off that and some people will go for it. Or “lockpriser” as we say in swedish. Real estate agents are given warnings whenever they are caught using tactics like that but for cardealers this is totally acceptable?! Even going through their own “what our customers think of us” turns up a gem where a guy says that he was happy even though they slashed 20% off the initial guestimate! There are also plenty of reviews on Trustpilot against them for this tactic!

Naturually I said “get the fuck out of here!” and left on the spot. So beware of “vikoperdinbil.se” unless you’re ready to get an offer about 40.000:- less than the street value. How do I know that? Well my option B was to take it to the authorized Seat dealer in Täby. They gave us 110.000:- for it and put it up for sale for 130.000:- and in 3 days the ad was taken down!

Buying a new car – how hard can it be? Part III

[Previously on the blog – me and the wife wanted to buy a new car and ordered an Audi A5 for 492.000 SEK and it was delivered in late February but only after wondering if this was their first car delivery ever!]

Now that was 3 weeks ago. And in those three weeks unfortunately enough has happened to make me say “I won’t go back there again”.

Not only because of the reasons I’ve already listed (1) them telling us to go away from the business section in a rather rude manner, 2) the unprofessional way of handling the tyre situation 3) noone informed us of the deposit we had to make before we got there) but as it turns out they made even bigger mistakes – one huge mistake during the ordering process and two pretty big mistakes with the delivery.

When delivering an Audi, the representative is supposed to help you sign up to the myAudi account and tie your car to that account. Nope, didn’t happend! Fortunately I know my way around Internet and websites but it led me to the next big issue. They also failed to inform us that the little plastic badge on the set of keys we got was actually very, VERY valuable since it had a PIN to enable remote access of the car! Without this I couldn’t use the electronics I paid for and selling it would be pretty damn hard! Fortunately we hadn’t thrown that little plastic thing in the bin yet but at no point did we think it was something we needed to keep! But the major f*ck up was discovered when we were loading up the car with some kids and realised this model didn’t have 3 seatbelts in the back, only 2!!! I didn’t even know that was possible but apparently it’s an extra option for Audi that costs a mere 3.600 SEK! Had the original salesguy informed us about that we would absolutely have clicked it. But he didn’t so now we’re stuck with a car that only has 4 seatbelts! This was a dealbreaker when we started this (one of the reasons we didn’t go for a Mustang!) and we made sure to check that it did have it when we were in the showroom! I can only imagine the salesguy picked up on us only having one kid and in an attempt to keep the price below 500.000 didn’t click it but it leaves a very sour taste! Fortunately we have a cheap ass VW Polo that has 3 seatbelts in the back so if we ever need one extra seat we can use that. But still… And “we should have checked it ourselves”, yeah you could say that, but as I said in part I, it’s a freaking jungle!! Unless you work there knowing what’s included in the “2017 A5 Sportback Proline Sport Edition” from the go, it’s damn impossible! And when adding stuff BAM! you’re told that it’s not compatible with the current loadout! It’s rediculous! Sometimes I think those configurations should have a “these things are NOT included in your layout”-list, that would have spelt it out for us that it was an extra option.

So, expect a new one of these in 3 years when it’s time to buy a new car again. Maybe we’ll go for a Mustang that time around or maybe Tesla if they are affordable by then.

Read Part I here.

Read Part II here.

Buying a new car – how hard can it be? Part II

[Previously on the blog – me and the wife wanted to buy a new car and ordered an Audi A5 for 492.000:- and was told it would be delivered end of March]

And so we waited. And waited.

Eventually in mid February we got an e-mail from the insurance company telling us it was time to insure our Audi. ??.. so we called up the dealer in Järva, got put on hold and eventually told by the manager that “I’m gonna have to call you back”. And so he did. And yeah, the car had arrived and we were free to pick it up next week. At this point I’m wondering “how long has it been there and when were you going to tell us!?” but I was just too excited and grateful that it was already here to question that. After our dealing with Toyota I thought it’d be best if we gave them the week and come in on Friday afternoon. This gave them over 8 days to get the car ready. And then he assigned the delivery to another salesman which I thought was weird but as it turns out the salesman, Daniel, that I liked so much and ordered the car from was no longer working there for reasons noone wanted to get into. When I woke up on Tuesday, 3 days before the delivery, it was snowing. And I remembered we hadn’t ordered the winter tyres so it would be illegal for us to drive our new car home from the dealer without it! So I called them up and asked what they usually do in this situation when customers have ordered cars without winter tyres and it’s snowing. And he had no clue. His first response was just hoping it would get warmer and thaw so it wouldn’t be a problem. I couldn’t tell if it was a joke or serious but it was absolutely unprofessional! So I had to ask him if he could fix winter tyres for us which he ofcourse was willing to try to do but couldn’t make a promise he’d get them in time. Seriously, he had 3 days to find new wintertyres for a new car in Stockholm, how hard can that be, pick up the phone to Euromasters and have them send over a set with DHL!? Well, he couldn’t just call anyone to get any kind of tyres, he had to order Audi originals regardless if we wanted it or not! Then we didn’t hear anything from him and we were just left assuming it was sorted when we went in to pick up the car on Friday afternoon. And much to our delight and surprise he had sorted it. On the car was now brand new Audi original winter tyres! “Great, so can we get the car now” … “well not really because you still haven’t paid us the 130.000 that was due”. Huh? Well, as it turns out we were supposed to send in the money to them so they had it before we could pick up the car and noone had told us about this. He said it was the “other guy” that had missed informing us of that. Personally I think it should be on a check list when preparing to deliver a car to make sure the car is legal to drive on the day of delivery and that the payment was settled, but apparently this guy didn’t think that was on them, those were my problems to solve!

So I ended up using Swish, a Swedish “send money instantly to another phone number” system that is quite a common way to send money here – just not supposed to be used for transactions of this size!! Fortunately my bank allowed the transaction, otherwise I don’t know what they’d do but I was furious enough to leave there and then and have another look at the Cupra – just ask Toyota. So now that that was sorted we got a big, long debriefing on insurance options. After that he unveiled our new car. And it was glorious!! I knew the car was so hitech that we were in for long education of what everything did.. but nope, he wasn’t into that, “I could spend an hour talking about everything but you pretty much want to get on the road huh?”.. well that didn’t stop him from talking insurances for a very long time but ok so let’s get on the road.. nope, we had to take a detour to their servicecenter to pay for the tyres. Fortunately the guy there was an absolute professional and got that over with quickly in the kind of “getting it done!” method I love. After that we got an ok to go out on the road, finally!

To be continued tomorrow…

Read Part I here.

Read Part III here.

Buying a new car – how hard can it be? Part I

Me and the wife were in the market to buy a car. And my wife has expensive taste. And we had the cash to spend. Sounds like a dream for any car dealer, right? But you know after our dealings with Toyota last year that I didn’t think very highly of car dealers… and that was about to get even lower!

My wife have always wanted to buy a Mustang. But purchasing a new Mustang in Stockholm proved pretty impossible as the only dealer we were in contact with didn’t have any available for us to try as other customers had crashed them both and we didn’t want to order one blindly. Besides I got the feeling he wasn’t too eager to sell one to us anyway. So we checked out a secondhand dealer that had a great Mustang waiting to be bought. After sitting in it we both kinda realised this isn’t the kind of car you use driving back and forth to school or to Ikea. So that idea was put on hold.

The next idea was a Tesla. But in Sweden the start at about 750.000 SEK which is shitload of money but when you start adding on stuff it goes up to 7 digits quite fast. So no, not yet.

Then we went for a sport version of the car we have today, a Seat Leon Cupra. The only dealer we had even remotely close to us turned out to be amateurs! They only had one for customers to try out. And the owner was using it as his private car. And we had to book an appointment to testdrive it! Well we did but it turns out the boss’s wife or daughter had taken the car for high street shopping that afternoon and got stuck in traffic. Who knew there might be traffic jams when going from Stockholm city to Barkarby at 5pm!? And when we test drove it we found their candy stash, we found her wallet and some left over shopping. As I said, amateur hour. Unfortunately the car was an absolut beast and we were tempted to buy one had it not been for the dealer.

So then we raised the bar! As we’ve been happy with both our Volkswagens and our Seat we decided to test the upgrade in the family and go for an Audi! Now I wanted to use Möller Bil again since we were so pleased with how the Seat turned out and how professional they’ve been but no Möller retailer close to us sells Audi. So we went to the Audi retailer in Järva. First thing that happened was they didn’t respond to my e-mail requests. Usually not a big thing but car dealers are supposed to be more eager than this, but oh well. So we went to their showroom and were told that we weren’t welcomed because we were in the business section! Should have gone home right there and then to be honest because the only reason we were in the business area was poor signage from their end! But we didn’t go home, we went up a floor to the consumer section and met a really friendly and nice salesguy, Daniel. He tried to understand what we wanted and our criterias – the wife wanted a bit of luxury but I wanted to pay the least amount for it! We went there looking at an A4 but when the wife saw their latest A5 Sportback she was totally sold! And when I saw their virtual cockpit, so was I. We tested sitting in an A5 to get the feel for the interior, noting that there was indeed 3 seatbelts in the back (more why that was important later!) and then we testdrove an A4 with identical engine to get the feel for the cars power. We were both very, very pleased. So we sat down to go through the list of options for the car to try to come up with a good car that fit our needs and what that would cost us. He went through every option (or so we thought!) with us and based on what he knew of our needs made recommendations. Since every manufacturer has their own terms/language, options and editions it’s a real jungle to sort it out but he did a good job of explaining it. I really liked this guy! So he came up with a car for 492.000 SEK, almost half a million. Naturually we needed to have a talk about it but after two days we made the decision to go for it. We went back and talked with him again to place the order. No fuzz at all, we agreed we’d put down 130.000 which we’d get from selling our current car when we got the new car. It would take “about 5 months” to get the car. A bit long but it would be worth waiting for. Now, did we want winter tyres on this or not? That was an extra 20.000 SEK. I knew I could get tyres for about half that price, and 5 months from end of October would be and of March so no really need for it, so no thanks. And the order was placed and we were happy with it all.

And then we waited. And waited…

Read Part II here.

Read Part III here.

Remove User Mailbox Permissions

SCENARIO
A user has alot of mailbox permissions to other mailboxes that needs to be revoked.

PROBLEM
The problem is that the GUI, even in an on-prem interface, forces you to remove the permissions on the destination so you have to go to every mailbox he/she has access to, remove the permission and then go to the next. This is very time consuming, one wish you could open the user and remove the permissions to other mailboxes that way, but it doesn’t work like that unfortunately.

SOLUTION
This little script solves this problem. It goes through all mailboxes in your mailenvironment and checks all the boxes that the [USER] has access to and prompts to remove them one by one. I still feel a prompt is necessary because sometimes you get the request to “remove everything except these”, so by prompting we can chose which ones to remove. Alot faster than going to every mailbox in the list! For better performance, I suggest you specify a “-servername EXCHANGESERVER” in the “get-mailbox” command, otherwise it’ll go through the entire Exchange org.

$user = "[USER]"
$permissions = Get-Mailbox -resultsize unlimited | Get-MailboxPermission -User $user
foreach($permission in $permissions)
{
$identity = $permission.identity
$accessright = $permission.accessrights
write-host "Removing permission for $user on $identity"
remove-mailboxpermission -Identity $identity -User $user -Accessrights $accessright
}
Download PS1 from Dropbox

Download PS1 from Dropbox

Change Something On Users From File

SCENARIO
You’re the administrator of an Office 365 tenant and/or on-prem Exchange and Active Directory and you need to make bulk changes to a group of people and you have a list with UPNs ready to use.

PROBLEM
There really is no problem but it may be very repetetive tasks.

SOLUTION
This script will read the file “C:\temp\list_of_upns.txt“, which is just a list of UPN’s, and iterate through them making the change you want. Since I make alot of the same changes to different users depending on what I need. I simply un-comment by removing the “#” for whatever I need to script to change on the user. And remember to put the “#” back in to comment if you want it to do something else or you may end up doing unwanted things on the objects (like converting a bunch of on-prem mailboxes to Room mailboxes, true story!)

# Written by : Kristoffer Strom ([email protected])
# Date: 2017-02-20
#
#Starting the loop
ForEach ($user in $(Get-Content C:\temp\list_of_upns.txt ))
{
write-host $user
#Set-Mailbox $user -Type shared
#$userdn = get-aduser  -Filter{UserPrincipalName -eq $user} -properties DistinguishedName
#$DN = Get-ADUser -Filter { UserPrincipalName -Eq $user }
#set-aduser $DN -Replace @{extensionAttribute1 = "REPLACEMENTTEXT"}
#set-aduser $DN -clear extensionAttribute1, extensionAttribute1, AdminDisplayname, AdminDescription
#remove-adgroupmember -Identity "ADGROUP" -Member $DN
#Set-MsolUserLicense -UserPrincipalName $user -RemoveLicenses "XXXXXXXXXX:ENTERPRISEPACK"
#Set-MsolUserLicense -UserPrincipalName $user -RemoveLicenses "XXXXXXXXXX:POWER_BI_STANDARD"
}
Download PS1 from Dropbox

Download PS1 from Dropbox

Get User Serviceplans

SCENARIO
You’re the administrator of Office 365 and you want to programmatically extract information about what serviceplans (features) a specific user has access to and which he or she doesn’t have access to.

PROBLEM
Microsoft’s way of storing the information regarding licenses and features/plans isn’t quite logical sometimes for unitiated people so this might sound like a very complicated thing to do with Powershell and you’re left to do it through the portal instead.

SOLUTION
This little snippet of code will help you. You can add exporting features to it if you want, or input a user.txt file, but this is the stuff that displays the information. But if you want to get a complete dump of all information for all users, you should use this script instead which does that magic alot better.

#
# Written by : Kristoffer Strom ([email protected])
# Date: 2017-02-20
#
# Here we define what user we're querying:
$upn = "[INSERT UPN HERE]"
# Here we set the index to 0
$i = 0
# Run the query to get user info
$user = get-msoluser -userprincipalname $upn
# Store the license array
$features = $user.licenses
# Just an empty row
write-host ""
# Running the loop to show info on all licenses
while($i -lt $features.count)
{
    $AccountSkuId = $features[$i].AccountSkuId
    Write-host -NoNewline -ForegroundColor Cyan "Features for $AccountSkuId"
    $features[$i].servicestatus | ft
    $i++
}
Download PS1 from Dropbox

Download PS1 from Dropbox

UPDATE: Apparently the new Powershell moduled for MSOL handled this differently so the output became quite different. Rather than type out one plan at a time it bunched them together so there was no way of seeing which feature belonged to which plan. So I re-wrote this with a “while” loop and “format table” command to force it to seperate the output. (seriously, remove the “ | ft” part and see what that does to this snippet!)

Get AD User By UPN

SCENARIO
You’re managing Office 365 and want to do Powershell quieries against the on-premise Active Directory

PROBLEM
The problem is that Office 365 cmdlets like “get-msoluser” always gives you the users userprincipalname (UPN) because that is all that Office 365 cares about. But when you want to query the local on-premise Active Directory with “get-aduser” it doesn’t recognise the UPN when searching for users.

SOLUTION
The solution is adding it as a filter like this, where $MSOLUPN is the UPN you get from “get-msoluser“:

Get-ADUser -Filter { UserPrincipalName -Eq $MSOLUPN }

Again, this is pretty basic stuff, but still something you need to know and use all the time.

Set UsageLocation Where Empty

SCENARIO
You’re the administrator of a large tenant with several different e-mail domains for people in different countries. Manually setting a UsageLocation, which is required for license activation, for them all individually is unrealistic.

PROBLEM
The problem here is we need some way of filtering out who is actually where. The perfect solution is ofcourse to have the AD property (“msExchUsageLocation”) since Azure AD Connect syncs it out of the box. But not everyone has that luxury, especially if it’s a domain you’re not even in charge of. And the get-msoluser cmdlet with -domain filter will not only catch the ones that have the domain as their primary e-mail, but also the ones that have it as secondary so as a filter it won’t work.

SOLUTION
In comes this little bit of code! It loads all users, filters out everyone that has a license and everyone that doesn’t have a UPN matching the domain (in this example “test.se” and for the rest sets the UsageLocation to whatever you want, in this example “SE“. This way, we only get the ones that don’t have a license yet and only the ones with this specific domain as their primary e-mail (which should match UPN). So if your company’s name is “test” and everyone has a “test.com” address as a secondary, but the Swedish employees have “test.se” as their primary you can easily set their usagelocations like this. And then just change it around for the rest of the company.

#
# Written by : Kristoffer Strom ([email protected])
# Date: 2017-02-10
#
# Credit to Reditor bearxor (https://www.reddit.com/user/bearxor)
#
# We check all users for users with no UsageLocation set and matches a e-mail domain (test.se) and sets the UsageLocation SE (=Sweden)
Get-MsolUser -All | where{$_.UsageLocation -eq $null -and $_.userprincipalname -like "*@test.se"} | foreach{set-msoluser -UserPrincipalName $_.UserPrincipalName -UsageLocation "SE"}
Download PS1 from Dropbox

Download PS1 from Dropbox

Add Users To Group Based On Attribute

SCENARIO
You have a bunch of users with some property in common in your on-prem AD and you want to add them all to an AD group.

PROBLEM
Normally to add a bunch of users to an AD group you’d simple use “dynamic groups” and set the filter up and never bother with it again. This however becomes a problem when dealing with Azure AD since that doesn’t support dynamic groups (since it can’t look up all properties in your AD).

SOLUTION
The solution is below. You specify the name of the AD group (“NAME_OF_AD_GROUP” in example below) you want to add users, you change what attribute (“extensionattribute1“) you want it to filter on and what the attribute has to be (“WHATEVER“) and the script iterates through every users and adds them to the AD group. This can be setup as a secheduled task to get the same effect as a dynamic group but would work for Azure AD as well.

#
# Written by : Kristoffer Strom ([email protected])
# Date: 2017-02-09
#
# We start by defining what AD group we want to add the users to
$nameofgroup = "NAME_OF_AD_GROUP"
# Then we get a list of users based on an attribute, in this case "Extensionattribute1" equals "WHATEVER"
$listofusers = Get-ADUser -filter {extensionattribute1 -eq "WHATEVER"}
# Now we iterate through every user
foreach($individualuser in $listofusers)
  {
  # We declare this variable for write-host purposes only.
  $UserPN = $individualuser.UserPrincipalName
  # And we can write out the operation while we're at it
  Write-Host "Adding $UserPN to group $nameofgroup."
  # And add them to the group
  Add-ADGroupMember $nameofgroup $individualuser.DistinguishedName
  }
Download PS1 from Dropbox

Download PS1 from Dropbox

Sherlock, Arrival and Girl on the Train

I really like the BBC show “Sherlock”, you know the one with Benedict. Somehow I had completely missed the 4th “season” that came out in January! I type “season” in quotes since it’s just 3 episodes! I don’t know why I had no clue but by the time I found out it was available on Amazon so ordered it right away. So far only seen the first episode – really like it! They still have that special cinematography going on that I love! I can’t really decide if I want them to make more episodes or keep it to 3-4 every second year since that makes it kind of “special” when new episodes do come out? The other Sherlock show, “Elementary” with Jonny Lee Miller, is pretty damn good too but they make 25 episodes per year so they don’t feel so special!

Also saw “The Arrival” the other day. I missed it when it was on the big screen so had to make do with my TV at home. I expected a really good sci-fi movie about first contact with another species. Instead I got a really good sci-fi movie about .. well I can’t really tell you that but it’s a funny idea and a good twist! I really do love it when sci-fi movies are able to make the sci-fi take the backseat and the human heart & spirit in focus like this! Really well done! Can really recommend this one!

Also saw “The Girl on the Train”. That movie was sooooo very slow that it was hard to stay awake at times and it wasn’t that “different” than any other movie where guys are assholes. But the one great thing about this was Emily Blunt that was absolutely fantastic! Haven’t really seen her in anything that made me go “wow” before but in this role it was definitely “wow!”. So if you want to see good acting, see it. If not, don’t.

Bulk Converting Domains To Federated

SCENARIO
You’re the administrator of an Exchange environment with lots of domains registered over the years for whatever reasons, as an example different business units with different e-mail domains. You’ve added them all to the Azure AD and verified them but now you need to tie them to the AD Federation Service (ADFS).

PROBLEM
Problem is it takes alot of time to first sort out all domains that are verified and then federating them, a very tedious task.

SOLUTION
Solution is you export all your domains into a CSV file (just listing all the domainnames is fine), the run this script and it will import the CSV file and for every entry it will check to make sure if it’s verified and if so, federate it with the ADFS. Remember to run this on the ADFS server and the Powershell needs to be launched as administrator!

#
# Written by : Kristoffer Strom ([email protected])
# Date: 2017-02-08
#
# Let's begin by importing the file. Change the filename "CSV_FILENAME.csv" to whatever you see fit.
$domains = Import-Csv CSV_FILENAME.csv
# And now we iterate through every entry
foreach ($domain in $domains)
{
  # Getting the status of the domain
  $domainstatus = get-msoldomain -DomainName $domain.DomainName
  # If it's already federated we just say that and move onto the next one
  if($domainstatus.Authentication -eq "Federated") { write-host -Foregroundcolor Yellow "$domain is already federated." }
    # If it's verified we federated it
    ElseIf($domainstatus.Status -eq "Verified") { Convert-MsolDomainToFederated -DomainName $domain.DomainName -SupportMultipleDomain:$true; write-host -Foregroundcolor Green "$domain.DomainName changed to federated" }
    # Or if it's not Verified or doesn't exist we write this error
    ElseIf($domainstatus.Status -ne "Verified") { write-host -Foregroundcolor Red "$domain is not verified or does not exist in tenant." }
}
# End of iteration

OPTIONAL
You could replace the import of the CSV file to read out all the UPN suffixes from your domain. If you’ve done your job for a proper O365 migration you’ve made sure all the UPN’s match their e-mails then all e-mail domains should exist as a UPN suffix. If you want to do that, replace the line “$domains = Import-Csv CSV_FILENAME.csv” with this:

$ADForest = Get-ADForest
$domains = $ADForest.UPNSuffixes

Another option is to do a get-msoldomain and filter on “Verified” domains only. But beware, this will tie all verified domains to your ADFS, be sure you really want that! If you do, replace the “$domains=” statement with this:

$domains = Get-MsolDomain -Status Verified

This script can easily be converted into one that does the initial adding of the domains, but since every domain added gets a vertification code backs doing that in bulk is less than ideal.

Download PS1 from Dropbox

Download PS1 from Dropbox

Powershell to Exchange Online

SCENARIO
You’re used to having your Exchange server in your own environment and Powershelling to it and run all these scripts you’ve collected over the years.

PROBLEM
Now that the mailboxes are in a database you have no control of on a server somewhere at Microsoft how are you supposed to run those Exchange Powershells?

SOLUTION
This is the MS way of executing Powershell against Exchange Online using Powershell commands you’d usually use on an on-premise Exchange environment. This is very basic stuff, but if you’re just getting started with Office 365, this is essential to manage users in Exchange Online!

$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session

Basically what this does is connects you to Exchange Online and starts a remote Powershell session on Microsoft’s server. This unfortunately means that you are limited to the automation limits, which means sometimes when you do really, really heavy stuff you’ll run into throttling errors from “Microsoft.Online.Administration.Automation.MicrosoftOnlineException”. Usually that’s just an error saying you need to code better with more filters!

IT Nerdiness

I’m going to start another blog. I’ve been thinking about it for quite some time but never really got around to doing it. I’m gonna start a boring IT nerdy blog with my own “experiences from the field” from work!
If you didn’t know I’m an IT pro working with SharePoint both in house but also in the cloud, as wel as alot of other “Office 365” things for an enterprise with some 25k users. And one thing that us IT pros do well is share information. I wouldn’t be able to solve half of the issues I’m faced with all the time if it wasn’t for other IT pros out there sharing their experiences and their tricks. And one of the things I think I can contribute with the most is Powershell script.

Nothing too advanced though, just basic powershell tips that other people in my line of work might find usefull so they don’t have to write them their selves. I’m sure some of these scripts can be approved upon, so please let me know if you have suggestions!

Enjoy!