o365 Groups, My Hatred of it

I hate PowerShell, I hate o365 (more specifically o365 Groups / Outlook Groups), and I hate SharePoint in the Office 365 Tenant. 

I know that is a strong way to start off a statement on managing o365 Groups but after banging my head against the wall for too long around o365 Groups I can’t think of a more appropriate statement regarding my feelings for Microsoft’s new product line.  So let me break down my frustration and give a few insights.

I am going to start with my hatred of SharePoint.  First off, the platform is a pig and it is a bloated pig, but I am not going to get into that right now.  With Microsoft’s new direction for SharePoint in building other products on top of it such as o365 Groups or Planner, Microsoft is stepping in the world of SharePoint and making a muck of the SharePoint environment with other products that trample over the storage and URL-space of the SharePoint tenant.  So when you create an o365 Group or a Planner plan, then you have created a SharePoint site collection in the tenant that you don’t see in the dashboard or have direct control over the quota (without PowerShell). 

Moving into my hatred of o365 Groups.  Here is a product that Microsoft is building as a collaborative communication tool (what about Yammer) and they are encouraging users to create their own groups, but they have little governance on how the groups are created (and that is just coming in now).  One exciting thing about groups is that the users can create whatever they want… and guess what, it shows up in the GAL.  A user could effectively create a group saying “Union Formation Group” and what could the company do to stop it, they could create a lot of legal problems in the company instantly and there is no way to really stop it short of turning off Groups.  Keep in mind that these Groups use quota from SharePoint too.  Here is just another though on Groups, the name.  We have AD Groups, Azure Groups, o365 Groups, just group Groups, and where will this end.  Let’s stop using generic names for products (Word?) which causes so much confusion when using the Google to try to return information (“the Google” was not a typo, it is a being now).

Lastly, I am going to complain about PowerShell or more specifically the implementation of PowerShell and the documentation for the o365 Groups.  Microsoft’s documentation is scattered and not clear on top of the fact that when you search for “Office 365 Group” or “o365 Group” you get everything from groups about o365 to permission groups in SharePoint (back to naming).  Even when you find the documentation that shows things like optional parameters for the PowerShell it is very incomplete.  For example, many of the options that are available on “Set-UnifiedGroup” (did you notice that one?  All of a sudden an o365 Group is called a “Unified Group”) are available too on “New-UnifiedGroup” even though it doesn’t show up there in the documentation.  Here is another fun one, if you want to set the quota for the file storage, it is a SharePoint PowerShell command and does not involve the “Unified Group.”  My favorite of all, I was trying to interact with the “Description” field for the o365 Group but that is the “Notes” field in PowerShell, what the hell?  Why do you even use named properties when you change the meaning of the names or the names in the UI. 

Well, there was my rant.  I doubt there will be anything helpful, but if you want the complete current list of PowerShell parameters I have it below.  Please look back in a few weeks for some examples on connecting to PowerShell through C# to create a new Unified Group or whatever the hell Microsoft changes the name to next.

 

  • New-UnifiedGroup
    • [-AccessType <Public | Private>]
    • [-Alias <String>]
    • [-AutoSubscribeNewMembers <SwitchParameter>]
    • [-Confirm [<SwitchParameter>]]
    • [-Database <DatabaseIdParameter>]
    • [-DisplayName <String>]
    • [-DomainController <Fqdn>]
    • [-EmailAddresses <ProxyAddressCollection>]
    • [-ExecutingUser <RecipientIdParameter>]
    • [-ExternalDirectoryObjectId <String>]
    • [-FromSyncClient <SwitchParameter>]
    • [-Language <CultureInfo>]
    • [-ManagedBy <RecipientIdParameter[]>]
    • [-Members <RecipientIdParameter[]>]
    • [-Name <String>]
    • [-Notes <String>]
    • [-Organization <OrganizationIdParameter>]
    • [-OrganizationalUnit <OrganizationalUnitIdParameter>]
    • [-OverrideRecipientQuotas <SwitchParameter>]
    • [-PrimarySmtpAddress <SmtpAddress>]
    • [-RecipientIdType <Unknown | ExternalId | Smtp | LegacyDn>]
    • [-RequireSenderAuthenticationEnabled <$true | $false>]
    • [-SharePointResources <MultiValuedProperty>]
    • [-SuppressWarmupMessage <SwitchParameter>]
    • [-ValidationOrganization <String>]
    • [-WhatIf [<SwitchParameter>]]
    • [<CommonParameters>]

The IKEA Dignitet

So my wife purchased something to hang some of the kids artwork on the walls and while the product looks innocuous enough it is really a nightmare.  The product I am writing about is the IKEA Dignitet Curtain Wire (http://www.ikea.com/us/en/catalog/products/60075295/).  I am sure that many people have seen this product on Pinterest but this is not a product I would recommend (at least if you have drywall walls).  I installed it as directed by the very short instruction manual but there was no mention about the proper wire tension or anything about proper anchors for the walls.  I chose to use wall anchors that are rated for fifty pounds each which according to that logic each pedestal should be rated to 150 lbs assuming the drywall would hold that much weight.  So upon installing the brackets which went fine, I began to tension the wire (not too tight from what I could tell) but my wall anchors began pulling from the drywall.  Due to the narrow base and simple points on how this mounts it appears that it becomes very easy to create a torsional force on the screws that were holding it on the wall thus increasing the amount of weight that was being applied to the screws.  So at this point I have six holes in my wall that technically are not strong enough to properly tension the wire.  I used ended up adding some tape around the screws to add additional size for the anchors and by not tensioning the wire very tight it appears to be holding.  

In summation, I would not recommend this product if you are going to mount it on drywall, it should be fine on a wood wall but other than that, this is not a good product.  

Yammer OAuth for data export

Anyone familiar with Yammer will know that many of the APIs are a bit lacking.  Also, all API connections will need an oAuth token that has access to the data in question.  So what do you do if you have a console application that needs to use Yammer Data Export API and drop the into a database or more to the point, how do you get the oAuth token?  I am not going to post the specifics on how to get the data and extract it but I will post some code on how to get the oAuth token.

To start there is some information you will need from Yammer which is only obtained after creating a Yammer app (https://developer.yammer.com/v1.0/docs/app-registration).  Your redirect URL for the included code needs to be http://localhost:80/Temporary_Listen_Addresses/  (if you get an error relating to access denied the port may be being used or it could be an issue with your privileges on the device).  *NOTE you do not need to publish your app for this functionality to work, so you can create the app then never finalize it.  Yammer's documentation https://developer.yammer.com/v1.0/docs/authentication-1 does not include the specifics on how to implement this on a console application and only includes the basic information.

The included code makse the assumptions that you will have the following app seetings in your App.config: "ClientID", "RedirectURL", "ClientSecret", and "oAuthToken" with all of these fields populated, with the exception of the "oAuthToken" field, from the information in your Yammer app settings.

I have included the complete class to perform the login here and to implement it you just need to call the constructor. 

  1. var yammerLogin = new YammerLogin.YammerAuthentication();
  2. string token = yammerLogin.oAuthToken;

The oAuthToken will be stored in the App.config and it will only re-auth if the token has failed to login. 

I hope this will help save a few hours of work for a few people out there.

Migrating Drupal from MySQL to MSSQL

So I am going to start by ranting a little bit about Microsoft Azure cloud services.  Something odd about Azure is that when you are creating a new Drupal or WordPress site it will automatically crate a MySQL database but if there is already a MySQL database it will not create it automatically.  You can however create a MySQL database then install your CMS and associate it with said database.  The second part of my rant is that with a MSSQL database the smallest size is 2 GB and it is less expensive than the 20 MB MySQL database, which just seems odd to me.

 

Okay, now that I have that over with, let me get to the heart of what I wanted to talk about and discuss installing Drupal on a MSSQL and migrating (if need be) from MySQL in Azure.  So, to start there is one very easy config change to allow Drupal to run on MSSQL.  Download the drivers from https://www.drupal.org/project/sqlsrv then extract the files.  With the files extracted copy the sqlsrv folder and drop it in the includes/databases directory in the root of your Drupal installation.  After the files are uploaded update the configuration settings in the settings.php file and update the connection for the $databases to have the driver “'driver' => 'sqlsrv'”.  Something to note, if you are performing this on Azure the PHP MSQL Drivers are already installed but if you are running this install on a different system you may need to install PHP MSSQL drivers.

 

One thing that was missing on my installation was a SUBSTRING function that is used for Drupal when performing a post.  The site worked fine but when I tried to post as an authenticated user I received an error.  To solve the problem I needed to add the function.  Click Here for the specific TSQL code.  (UPDATE)Even with the substring SQL function installed I was still having trouble.  So I ended up hitting the install.php page and then running a database update.  This seems to have fixed my missing SQL functions, but only time will tell if I am not missing anymore.  I have included all of the functions that are created in the link referenced in this paragaraph.

 

So if you need to migrate from MySQL to MSSQL there are a few steps that you need to take.  After creating the new database in MSSQL download the MSSQL Migration Assistant for MySQL from http://www.microsoft.com/en-us/download/details.aspx?id=42657.  Point the MySQL to your old MySQL instance and point the MSSQL to the new MSSQL instance.  Start by changing the target schema to dbo (this will make the migration easy).  Then right click on your database and click “Convert Schema” this will create the local metadata of the schema.  Once the schema conversion is done, on the target database right click and select “Synchronize with Database.”  Once the synchronization is complete (this will take a while) your tables will be created but without data.  Lastly right click on your original MySQL database and select “Migrate Data.” 

 

If you have not updated your connection in your settings.php file, you can update that now to point to the MSSQL instance and you should be good.  I tested my change by making a small change to my site and seeing how it reflected in the database (specifically I changed my locale on my user account). 

 

I hope this will help the few that run Azure sites under your MSDN and do not want to pay for additional MySQL storage.