2014/07/01

PowerShell - Handy function to connect to Office365 services


I just started to play with a Microsoft Office 365 environment (Azure Active Directory, Lync Online and Exchange Online) and I thought I would make it through PowerShell obviously :-)

But when you start your PowerShell console... you need to load modules, connect to each services, enter your credentials...yada yada yada...

With Office 365 you can administer the following services using PowerShell:
  • Azure Active Directory
  • Exchange Online PowerShell
  • SharePoint Online PowerShell
  • Lync Online PowerShell


Note: However I was not able to test the SharePoint part, so this is not included in the function below yet.

Here is a very handy function that you can include to your PowerShell Profil to connect to all the service at once.


Requirements

  • Azure Active Directory Download
  • Exchange Online PowerShell (no download needed, the function will create an implicit remoting module)
  • SharePoint Online PowerShell (no download needed, the function will create an implicit remoting module)
  • Lync Online PowerShell Download




PowerShell Function Connect-Office365


function Connect-Office365
{
<#
.SYNOPSIS
    This function will prompt for credentials, load module MSOLservice,
    load implicit modules for Office 365 Services (AD, Lync, Exchange) using PSSession.
.DESCRIPTION
    This function will prompt for credentials, load module MSOLservice,
    load implicit modules for Office 365 Services (AD, Lync, Exchange) using PSSession.
.EXAMPLE
    Connect-Office365
   
    This will prompt for your credentials and connect to the Office365 services
.EXAMPLE
    Connect-Office365 -verbose
   
    This will prompt for your credentials and connect to the Office365 services.
    Additionally you will see verbose messages on the screen to follow what is happening in the background
.NOTES
    Francois-Xavier Cat
    lazywinadmin.com
    @lazywinadm
#>
    [CmdletBinding()]
    PARAM ()
    BEGIN
    {
        TRY
        {
            #Modules
            IF (-not (Get-Module -Name MSOnline -ListAvailable))
            {
                Write-Verbose -Message "BEGIN - Import module Azure Active Directory"
                Import-Module -Name MSOnline -ErrorAction Stop -ErrorVariable ErrorBeginIpmoMSOnline
            }
            
            IF (-not (Get-Module -Name LyncOnlineConnector -ListAvailable))
            {
                Write-Verbose -Message "BEGIN - Import module Lync Online"
                Import-Module -Name LyncOnlineConnector -ErrorAction Stop -ErrorVariable ErrorBeginIpmoLyncOnline
            }
        }
        CATCH
        {
            Write-Warning -Message "BEGIN - Something went wrong!"
            IF ($ErrorBeginIpmoMSOnline)
            {
                Write-Warning -Message "BEGIN - Error while importing MSOnline module"
            }
            IF ($ErrorBeginIpmoLyncOnline)
            {
                Write-Warning -Message "BEGIN - Error while importing LyncOnlineConnector module"
            }
            
            Write-Warning -Message $error[0].exception.message
        }
    }
    PROCESS
    {
        TRY
        {
            
            # CREDENTIAL
            Write-Verbose -Message "PROCESS - Ask for Office365 Credential"
            $O365cred = Get-Credential -ErrorAction Stop -ErrorVariable ErrorCredential
            
            # AZURE ACTIVE DIRECTORY (MSOnline)
            Write-Verbose -Message "PROCESS - Connect to Azure Active Directory"
            Connect-MsolService -Credential $O365cred -ErrorAction Stop -ErrorVariable ErrorConnectMSOL
            
            # EXCHANGE ONLINE (Implicit Remoting module)
            Write-Verbose -Message "PROCESS - Create session to Exchange online"
            $ExchangeURL = "https://ps.outlook.com/powershell/"
            $O365PS = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ExchangeURL -Credential $O365cred -Authentication Basic -AllowRedirection -ErrorAction Stop -ErrorVariable ErrorConnectExchange
            
            Write-Verbose -Message "PROCESS - Open session to Exchange online (Prefix: Cloud)"
            Import-PSSession -Session $O365PS –Prefix ExchCloud
            
            # LYNC ONLINE (LyncOnlineConnector)
            Write-Verbose -Message "PROCESS - Create session to Lync online"
            $lyncsession = New-CsOnlineSession –Credential $O365cred -ErrorAction Stop -ErrorVariable ErrorConnectExchange
            Import-PSSession -Session $lyncsession -Prefix LyncCloud
            
            # SHAREPOINT ONLINE (Implicit Remoting module)
            #Connect-SPOService -Url https://contoso-admin.sharepoint.com –credential $O365cred
        }
        CATCH
        {
            Write-Warning -Message "PROCESS - Something went wrong!"
            IF ($ErrorCredential)
            {
                Write-Warning -Message "PROCESS - Error while gathering credential"
            }
            IF ($ErrorConnectMSOL)
            {
                Write-Warning -Message "PROCESS - Error while connecting to Azure AD"
            }
            IF ($ErrorConnectExchange)
            {
                Write-Warning -Message "PROCESS - Error while connecting to Exchange Online"
            }
            IF ($ErrorConnectLync)
            {
                Write-Warning -Message "PROCESS - Error while connecting to Lync Online"
            }
            
            Write-Warning -Message $error[0].exception.message
        }
    }
}




Running the function



Here the result in action







Adding the function to your PowerShell profile



The next time you reload your PowerShell, the function Connect-Office365 will be available to your PowerShell.

Finally we can see two implicit modules created for Lync and Exchange with a sample of cmdlets available. Those cmdlets contains the prefix we defined in the function ExchCloud and LyncCloud.

Implicit remoting modules loaded start by a "tmp". You can see a sample of the Cmdlets available
with the prefix we included.



Download

Space for improvements
  • Check if PSsession already opened ? Same credential used?
  • Parameters
    • [Switch]$AzureAD,
    • [Switch]$LyncOnline,
    • [Switch]$ExchangeOnline


Thanks for reading! If you have any questions, leave a comment or send me an email at fxcat@lazywinadmin.com. I invite you to follow me on Twitter @lazywinadm / Google+ / LinkedIn. You can also follow the LazyWinAdmin Blog on Facebook Page and Google+ Page.

36 comments:

  1. This has made my day; thank you for the amazing tool!

    ReplyDelete
  2. Good stuff. Thanks for the script.

    ReplyDelete
  3. Great Post. learned a lot about PS & UI. I am good with PS but having trouble passing values to windows controls and calling new farms from those controls. look for a book or video or step by step guide on how to pass values from controls and forms to other controls and forms and call other functions. Any suggestion or guidence will be much appriciated.

    ReplyDelete
  4. Hey Zee,

    Check this article from SAPIEN, it explains how to pass values to your Winforms
    http://www.sapien.com/blog/2013/10/01/powershell-studio-passing-and-returning-values-using-forms/
    --
    FX

    *Francois-Xavier Cat*
    Blog | Twitter | LinkedIn | Google+ | PowerShell MVP

    ReplyDelete
  5. Hi,
    Nice script!
    Can you exclude groups by name, etc? I would like to run it using searchroot at the top of the domain, but exclude Domain Users and Domain Computers.

    ReplyDelete
  6. Thanks Joseph,
    I will add this to my todo list.

    ReplyDelete
  7. I was happy to see that YouTube does have Powershell Summit 2014 recordings!

    ReplyDelete
  8. Yep it is very cool some folks brought their cameras to record some of the sessions.
    With the new equipments, all the future Summits will be recorded (hopefully) :-)

    ReplyDelete
  9. Hi !
    Thanks for the comment!
    Are you talking about the "Change History" ?

    If not can you send me a sample of your output here: info at lazywinadmin.com


    Thanks! :-)

    ReplyDelete
  10. This does not work on Windows 7 and Windows 8/8.1. The task is set to run in my case every 5 minutes. However it does not run. The task can be run manually successfully.

    ReplyDelete
  11. Hi Gareth,
    The problem might be something else. I just tried on 8.1, works like a charm.


    Did you check "Run with highest privileges", "Run whether user is logged on or not" ? Also if the account that run the task is not a local administrator, make sure the account is member of "Log on as a batch job" is the local security policy (Note: Local Policies\User Rights Assignment)


    Hope this help

    ReplyDelete
  12. That's the thing I am using accounts that are listed in the Log on as a batch job, based on the local admin group. The tasks run manually in the scheduler, They not adhering to the schedule, particularly when needing to run a task every 10 minutes. I could replicate the same results on two different machines, one Win7 and the other Win8.1, strangely I have daily batch jobs running on other machines (Servers) that run with no issue.


    I eventually used GoodSync for the specific requirement that serves it owns sync function and is not bound to the windows component. This has options to sync based on activity, essentially like a watch folder.

    ReplyDelete
  13. HI, I got the same error, may I know how did you fix that ?

    ReplyDelete
  14. Hey guys,


    This issue is related to the ValidatePattern line, which validate if the email addresses have the good format (of a email address of course ;-)


    So the issue is with my pattern, I must have forgot something. Could you send me by email the email addresses you used ? so i can fix this ? Here is my email info@lazywinadmin.com


    You can quickly fix this issue by removing the lines who starts by [ValidatePattern.....

    ReplyDelete
  15. Thank you!

    It runs smoothly after I installed power shell v3.0, it was 2.0 before.

    ReplyDelete
  16. It's really a super stuff that would definitely be a good help in my future circumstance.
    Though, in the same scene to audit the changes made in active directory, I tried an automated solution named LepideAuditor for active directory i.e., (http://www.lepide.com/lepideauditor/active-directory.html) that worked fantastically. It provides all critical changes reports in real time at granular level.
    By the way, thanks again for sharing this.

    ReplyDelete
  17. Such a great information shared !
    Though in my circumstance due to not much familiar with PS usage, I used Lepide auditor suite i.e., (http://www.lepide.com/lepideauditor/group-policy.html) to audit changes made in group policy and worked fantastic. It audit all critical changes in real time at granular level.
    However, I would definitely give a try to this method.

    ReplyDelete
  18. Thanks for sharing such a great information.
    In my environment with the same auditing concern, I use Lepide Auditor suite i.e., http://www.lepide.com/lepideauditor/group-policy.html that works good for me. It audit all changes made in group policy objects at granular level and provide the data in real time.

    ReplyDelete
  19. Such a great stuff !
    In my circumstance to audit changes made in active directory, I use Lepide auditor suite (http://www.lepide.com/lepideauditor/active-directory.html) that is very powerful tool.
    It audits all changes made in active directory & group policy at granular level and provides the captured data in real time.

    ReplyDelete
  20. How do I query the group form a different domain with credentials?

    ReplyDelete
  21. Hey ScSql,

    It is probably possible using something like that:
    https://social.technet.microsoft.com/Forums/windowsserver/en-US/0f440bb6-3e94-46bb-9a4c-885655981f9b/powershell-using-adsi-with-alternate-credentials



    I'll check soon to update the function and post about it

    ReplyDelete
  22. This is one of those things I've set up intuitively about 20 times and then I open up the GUI again and have a huge brainfart concerning how to set an exact number of minutes.

    ReplyDelete
  23. We have *many* domain controllers. It would be fantastic if you could include the output of

    Get-ADReplicationAttributeMetadata $GroupName -Attribute member -server localhost | fl LastOriginatingChangeDirectoryServerIdentity



    That way the report could include *where* the change was made.


    I've added it to my (extremely lengthy) todo list but I figured I'd run it by you as you could probably complete it *far* faster than I could :)

    ReplyDelete
  24. Thanks for your comment! Happy this is helpful :-)
    I put this here ...since I got this same brainfart...

    ReplyDelete
  25. Really cool, I did not know about this, THANKS! I will try to give it a try when I'm back.

    You can check the last version of this script on my github.

    https://github.com/lazywinadmin/PowerShell/blob/master/AD-GROUP-Monitor_MemberShip/AD-GROUP-Monitor_MemberShip.ps1

    ReplyDelete
  26. How would it be possible to do this with the MICROSOFT AD plugin instead of the Quest one??

    ReplyDelete
  27. Hey Tom,
    I actually have a working version that support either Quest or Microsoft AD Module.
    You'll find it on GitHub here : https://github.com/lazywinadmin/PowerShell/blob/master/AD-GROUP-Monitor_MemberShip/AD-GROUP-Monitor_MemberShip.ps1



    I will post an update sometimes soon on my blog to make it official

    ReplyDelete
  28. I'd love to see this type of integration.

    ReplyDelete
  29. Are these membership lookups recursive?

    ReplyDelete
  30. Pre-requsite: http://software.dell.com/products/activeroles-server/powershell.aspx

    ReplyDelete
  31. Hi Simon, nope but it is on my list ! Thanks for your comment

    ReplyDelete