Connect-O365.ps1
<#PSScriptInfo
.TITLE Connect-O365 .VERSION 1.6.3 .GUID a3515355-c4b6-4ab8-8fa4-2150bbb88c96 .AUTHOR Jos Verlinde [MSFT] .COMPANYNAME Microsoft .COPYRIGHT .TAGS O365 RMS 'Exchange Online' 'SharePoint Online' 'Skype for Business' 'PnP-Powershell' 'Office 365' .LICENSEURI .PROJECTURI https://github.com/Josverl/Connect-O365 .ICONURI https://raw.githubusercontent.com/Josverl/Connect-O365/master/Connect-O365.png .EXTERNALMODULEDEPENDENCIES MSOnline, Microsoft.Online.SharePoint.PowerShell, AADRM, OfficeDevPnP.PowerShell.V16.Commands .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES V1.6.3 Add progress bars V1.6.2 Resolve multiple Aliases per parameter bug on some PS flavors, V1.6.1 add test for Sign-in Assistant,Add pro-acive check for modules during administration. V1.6.0 Publish to Github v1.5.9 update install OS version match logic to use [System.Environment]::OSVersion.Version, correct DefaultParameterSetName=”Admin", Add -test option to check correct installation V1.5.8 Seperate configuration download info from script, Retrieve Module info from github. V1.5.7 Update to SPO shell build : 5111 1200 (March 2016) v1.5.6 Add -close parameter and fixed parameter sets, added inline help to parameters v1.5.5 Fix Language for MSOnline / AAD module v1.5 Add installation of dependent modules v1.4 Correct bug wrt compliance search, remove prior created remote powershell sessions V1.3 Add dependend module information V1.2 Add try-catch for SPO PNP Powershell, as that is less common V1.1 Initial publication to scriptcenter #> <# .Synopsis Connect to Office 365 and get ready to administer all services. Includes installation of PowerShell modules 1/4/2016 .DESCRIPTION Connect to Office 365 and most related services and get ready to administer all services. The commandlet supports saving your administrative credentials in a safe manner so that it can be used in unattended files Allows Powershell administration of : O365, Azure AD , Azure RMS, Exchange Online, SharePoint Online including PNP Powershell .EXAMPLE connect-O365 -Account 'admin@contoso.com' -SharePoint .EXAMPLE connect-O365 -Account 'admin@contoso.com' -SPO -EXO -Skype -Compliance -AADRM .EXAMPLE #close any previously opened PS remote sessions (Exchange , Skype , Compliance Center) connect-O365 -close .EXAMPLE #Connect to MSOnline, and store securly store the credentials connect-O365 -Account 'admin@contoso.com' -Persist:$false .EXAMPLE connect-O365 -Account 'admin@contoso.com' #retrieve credentials for use in other cmdlets $Creds = Get-myCreds 'admin@contoso.com' .EXAMPLE #Download and Install dependent Modules connect-O365 -install #> [CmdletBinding(DefaultParameterSetName=”Admin")] [Alias("Connect-Office365")] [OutputType([int])] Param ( # Specify the (Admin) Account to authenticate with [Parameter(ParameterSetName="Admin",Mandatory=$true,Position=0)] [ValidateNotNullOrEmpty()] [string]$Account, # Save the account credentials for later use [Parameter(ParameterSetName="Admin",Mandatory=$false)] [switch]$Persist = $false, <# valid for Admin and Close #> #Connect to Azure AD aka MSOnline [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [Alias("AzureAD")] [switch]$AAD = $true, #Connect to Exchange Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [Alias("EXO")] [switch]$Exchange = $false, #Connect to Skype Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [Alias("CSO","Lync")] [switch]$Skype = $false, #Connecto to SharePoint Online [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [Alias("SPO","ODFB")] [switch]$SharePoint = $false, #Load and connecto to the O365 Compliance center [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [switch]$Compliance = $false, #Connect to Azure Rights Management [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [Alias("RMS","AzureRMS")] [switch]$AADRM = $false, #All Services [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Close",Mandatory=$false)] [switch]$All = $false, <# parameterset Close #> #Close all open Connections [Parameter(ParameterSetName="Close",Mandatory=$false)] [switch]$Close = $false, <# parameterset INstall #> #Download and Install the supporting Modules [Parameter(ParameterSetName="Install",Mandatory=$true)] [switch]$Install, #Specify the Language code of the modules to download ( not applicable to all modules) #Sample : -Language NL [Parameter(ParameterSetName="Install",Mandatory=$false)] [ValidatePattern("[a-zA-Z]{2}")] [Alias("Lang")] $Language = $Host.CurrentUICulture.TwoLetterISOLanguageName, # EN #Specify the Language-Locale code of the modules to download ( not applicable to all modules) #Sample : -Language NL-NL #Sample : -Language EN-US [Parameter(ParameterSetName="Install",Mandatory=$false)] [ValidatePattern("[a-zA-Z]{2}-[a-zA-Z]{2}")] $LangCountry = $Host.CurrentUICulture.Name, # EN-US #Specify where to download the installable MSI and EXE modules to [Parameter(ParameterSetName="Install",Mandatory=$false)] $Folder = $null, #'C:\Users\Jos\Downloads', # [Parameter(ParameterSetName="Install",Mandatory=$false)] # $InstallPreview = $true, #Mixed parameterset # Save the account credentials for later use [Parameter(ParameterSetName="Test",Mandatory=$false)] [Parameter(ParameterSetName="Install",Mandatory=$false)] [switch]$Test = $false, #Force asking for, and optionally force the Perstistance of the credentials. [Parameter(ParameterSetName="Admin",Mandatory=$false)] [Parameter(ParameterSetName="Install",Mandatory=$false)] [switch]$Force = $false ) function global:Store-myCreds ($username){ $Credential = Get-Credential -Credential $username $Store = "$env:USERPROFILE\creds\$USERNAME.txt" MkDir "$env:USERPROFILE\Creds" -ea 0 | Out-Null $Credential.Password | ConvertFrom-SecureString | Set-Content $store Write-Verbose "Saved credentials to $store" return $Credential } function global:Get-myCreds ($UserName , [switch]$Persist, [switch]$Force=$false){ $Store = "$env:USERPROFILE\creds\$USERNAME.txt" if ( (Test-Path $store) -AND $Force -eq $false ) { #use a stored password if found , unless -force is used to ask for and store a new password Write-Verbose "Retrieved credentials from $store" $Password = Get-Content $store | ConvertTo-SecureString $Credential = New-Object System.Management.Automation.PsCredential($UserName,$Password) return $Credential } else { if ($persist -and -not [string]::IsNullOrEmpty($UserName)) { $admincredentials = Store-myCreds $UserName return $admincredentials } else { return Get-Credential -Credential $username } } } # Write-Verbose -Message 'Connect-O365 Parameters :' $PSBoundParameters.GetEnumerator() | ForEach-Object { Write-Verbose -Message "$($PSItem)" } #Parameter logic for explicit ans implicit -All If ( $PsCmdlet.ParameterSetName -ieq "Close" ) { if ( $all -eq $false -and $exchange -eq $false -and $skype -eq $false -and $Compliance -eq $false -and $SharePoint -eq $false -and $AADRM -eq $false) { Write-Verbose "Online Workload specified, assume all workloads" $all = $true } } If ( $PsCmdlet.ParameterSetName -iin "Close","Admin" ) { if ($all) { $AAD = $true $Exchange = $true $Skype= $true $Compliance = $true $SharePoint= $true $AADRM = $TRUE } } $script:Prog_pct = 0 $script:Prog_step = 12 If ( $PsCmdlet.ParameterSetName -eq "Close") { Try { write-verbose "Closing open session(s) for :" Write-Progress "Connect-O365" -CurrentOperation "Closing" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step #Close Existing (remote Powershell Sessions) if ($Exchange) { Write-Progress "Connect-O365" -CurrentOperation "Closing - Exchange Online" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step write-verbose "- Exchange Online" Get-PSSession -Name "Exchange Online" -ea SilentlyContinue | Remove-PSSession } if ($Compliance) { Write-Progress "Connect-O365" -CurrentOperation "Closing - Compliance Center" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step write-verbose "- Compliance Center" Get-PSSession -Name "Compliance Center" -ea SilentlyContinue | Remove-PSSession } if ($Skype) { Write-Progress "Connect-O365" -CurrentOperation "Closing - Skype Online" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step write-verbose "- Skype Online" Get-PSSession -Name "Skype Online" -ea SilentlyContinue| Remove-PSSession } if ($SharePoint) { if ( get-module Microsoft.Online.SharePoint.Powershell ) { Write-Progress "Connect-O365" -CurrentOperation "Closing - SharePoint Online" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step write-verbose "- SharePoint Online" Try {Disconnect-SPOService -ErrorAction Ignore } catch{} write-verbose "- Disconnect PNP Powershell" Write-Progress "Connect-O365" -CurrentOperation "Closing - SharePoint Online PnP Powershell" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step #Also Disconnect PNPPowershell Try { Disconnect-SPOnline -ErrorAction Ignore } catch{} } } If($AADRM) { if ( get-module AADRM ) { write-verbose "- Azure RMS" Write-Progress "Connect-O365" -CurrentOperation "Closing - Azure RMS" -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step Disconnect-AadrmService } } return $True } catch { return $false } Finally { Write-Progress "Connect-O365" -Completed } } If ( $PsCmdlet.ParameterSetName -eq "Admin") { $operation = "Retrieve Credentials" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step $admincredentials = Get-myCreds $account -Persist:$Persist -Force:$Force if ($admincredentials -eq $null){ throw "A valid Tenant Admin Account is required." } if ( $AAD) { $operation = "Connecting to Azure AD" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step $mod = 'MSOnline' if ( (get-module -Name $mod -ListAvailable) -eq $null ) { Write-warning "Required module: $mod is not installed or cannot be located." Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow return $false } #Imports the installed Azure Active Directory module. Import-Module MSOnline -Verbose:$false #Establishes Online Services connection to Office 365 Management Layer. Connect-MsolService -Credential $admincredentials } if ($Skype ){ $operation = "Connecting to Skype Online" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step $mod = 'SkypeOnlineConnector' if ( (get-module -Name $mod -ListAvailable) -eq $null ) { Write-warning "Required module: $mod is not installed or cannot be located. " Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow return $false } #Imports the installed Skype for Business Online services module. Import-Module SkypeOnlineConnector -Verbose:$false -Force #Remove prior Session Get-PSSession -Name "Skype Online" -ea SilentlyContinue| Remove-PSSession #Create a Skype for Business Powershell session using defined credential. $SkypeSession = New-CsOnlineSession -Credential $admincredentials -Verbose:$false $SkypeSession.Name="Skype Online" #Imports Skype for Business session commands into your local Windows PowerShell session. Import-PSSession -Session $SkypeSession -AllowClobber -Verbose:$false | Out-Null } If ($SharePoint) { $operation = "Connecting to SharePoint Online" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step if (!$AAD) { Throw "AAD Connection required" } else { #get tenant name for AAD Connection $tname= (Get-MsolDomain | ?{ $_.IsInitial -eq $true}).Name.Split(".")[0] } $operation = "Connecting to SharePoint Online PnP" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step $mod = 'Microsoft.Online.Sharepoint.PowerShell' if ( (get-module -Name $mod -ListAvailable) -eq $null ) { Write-warning "Required module: $mod is not installed or cannot be located. " Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow return $false } #Imports SharePoint Online session commands into your local Windows PowerShell session. Import-Module Microsoft.Online.Sharepoint.PowerShell -DisableNameChecking -Verbose:$false #lookup the tenant name based on the intial domain for the tenant Connect-SPOService -url https://$tname-admin.sharepoint.com -Credential $admincredentials try { write-verbose "Connecting to SharePoint Online PNP" $mod = 'OfficeDevPnP.PowerShell.V16.Commands' if ( (get-module -Name $mod -ListAvailable) -eq $null ) { Write-Warning "Required module: $mod is not installed or cannot be located. " Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow #return $false } import-Module OfficeDevPnP.PowerShell.V16.Commands -DisableNameChecking -Verbose:$false Connect-SPOnline -Credential $admincredentials -url "https://$tname.sharepoint.com" } catch { Write-Warning "Unable to connect to SharePoint Online using the PnP PowerShell module" } } if ($Exchange ) { $operation = "Connecting to Exchange Online" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step #Remove prior Session Get-PSSession -Name "Exchange Online" -ea SilentlyContinue| Remove-PSSession #Creates an Exchange Online session using defined credential. $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $admincredentials -Authentication "Basic" -AllowRedirection $ExchangeSession.Name = "Exchange Online" #This imports the Office 365 session into your active Shell. Import-PSSession $ExchangeSession -AllowClobber -Verbose:$false -DisableNameChecking | Out-Null } if ($Compliance) { $operation = "Connecting to the Unified Compliance Center" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step #Remove prior Session Get-PSSession -Name "Compliance Center" -ea SilentlyContinue| Remove-PSSession $PSCompliance = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $AdminCredentials -Authentication Basic -AllowRedirection -WarningAction Ignore $PSCompliance.Name = "Compliance Center" Import-PSSession $PSCompliance -AllowClobber -Verbose:$false -DisableNameChecking | Out-Null } If ($AADRM) { $operation = "Connecting to Azure Rights Management" write-verbose $Operation Write-Progress "Connect-O365" -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step #Azure RMS $mod = 'AADRM' if ( (get-module -Name $mod -ListAvailable) -eq $null ) { Write-Warning "Required module: $mod is not installed or cannot be located. " Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow return $false } import-module AADRM -Verbose:$false Connect-AadrmService -Credential $admincredentials } } <# .Synopsis import a .psd1 file from a url ,( Github) .DESCRIPTION import a .psd1 file from a url and perform a safe expansion using a number of predefined variables. #> function Import-DataFile { param ( [Parameter(Mandatory)] [string] $Url ) try { #setup variables to use during configuration expansion $CPU = $env:PROCESSOR_ARCHITECTURE switch ($env:PROCESSOR_ARCHITECTURE) { 'x86' {$xcpu = 'x86' ; $bitness='32';} 'AMD64' {$xcpu = 'x64' ; $bitness='64'; } } $Filename = $URL.Split("/")[-1] try { wget -Uri $URL -OutFile "$env:TEMP\$Filename" } #failsafe if IE never been run catch { wget -Uri $URL -OutFile "$env:TEMP\$Filename" -UseBasicParsing } $content = Get-Content -Path "$env:TEMP\$Filename" -Raw -ErrorAction Stop Remove-Item "$env:TEMP\$Filename" -Force $scriptBlock = [scriptblock]::Create($content) # This list of approved cmdlets and variables is what is used when you import a module manifest [string[]] $allowedCommands = @( 'ConvertFrom-Json', 'Join-Path', 'Write-Verbose', 'Write-Host' ) #list of pedefined variables that can be used [string[]] $allowedVariables = @('language' ,'LangCountry', 'cpu','xcpu' , 'bitness' ) # This is the important line; it makes sure that your file is safe to run before you invoke it. # This protects you from injection attacks / etc, if someone has placed malicious content into # the data file. $scriptBlock.CheckRestrictedLanguage($allowedCommands, $allowedVariables, $true) # return & $scriptBlock } catch { throw } } If ( $PsCmdlet.ParameterSetName -eq "Install") { Write-Host -f Yellow "Starting Installation" #always perform module test after installation $test = $true # Get the location of the downloads folder # Ref : http://stackoverflow.com/questions/25049875/getting-any-special-folder-path-in-powershell-using-folder-guid Add-Type @" using System; using System.Runtime.InteropServices; public static class KnownFolder { public static readonly Guid Documents = new Guid( "FDD39AD0-238F-46AF-ADB4-6C85480369C7" ); public static readonly Guid Downloads = new Guid( "374DE290-123F-4565-9164-39C4925E467B" ); } public class shell32 { [DllImport("shell32.dll")] private static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath ); public static string GetKnownFolderPath(Guid rfid) { IntPtr pszPath; if (SHGetKnownFolderPath(rfid, 0, IntPtr.Zero, out pszPath) != 0) return ""; // add whatever error handling you fancy string path = Marshal.PtrToStringUni(pszPath); Marshal.FreeCoTaskMem(pszPath); return path; } } "@ #Lookup downloads location if ($Folder -eq $null ) {$folder = [shell32]::GetKnownFolderPath([KnownFolder]::Downloads) } write-verbose "Download folder : $folder" $operation = "Load the required module information from the configuration file" write-verbose $Operation Write-Progress "Install External PowerShell modules to connect to Office 365" ` -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; #load the required modules from a configuration file on GitHub $Components = Import-DataFile -url 'https://raw.githubusercontent.com/Josverl/Connect-O365/master/RequiredModuleInfo.psd1' #figure out the progress rate $script:Prog_step = 100 / $components.AdminComponents.Count $script:Prog_pct = $script:Prog_step #> # (Get-Module aadrm -ListAvailable).Version <# use the below in order to update relevant information Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | sort -Property DisplayName | select PSChildName, DisplayName, Publisher, DisplayVersion #> foreach ($c in $Components.AdminComponents) { $operation = "Install $($C.Name)" write-verbose $Operation Write-Progress "Install External PowerShell modules to connect to Office 365" ` -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step if ($c.Preview -ieq "Yes" -and $InstallPreview -eq $false) { write-host -f Gray "Skip Preview component : $($c.Name)" continue; } #IF OS Major Specified , and if the current OS Matches the specified OS if ($c.OS) { if ( ($c.OS).Split(",") -notcontains [System.Environment]::OSVersion.Version.Major) { write-host -f Gray "OS mismatch, Skip component : $($c.Name)" continue; } } switch ($c.Type.ToUpper() ) { {$_ -in "EXE","MSI"} { Write-Verbose "EXE or MSI package" $AppInfo = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$($c.ID)" -ErrorAction SilentlyContinue $Installed = $false; if ($AppInfo ) { $Installed = $appInfo.Displayname -ne $null } if (-not $Installed -or $force) { # Filename $file = Split-Path $c.Source -Leaf #path in downloads $msi = join-path $folder $file #remove existing item prior to Downloading Remove-Item $msi -Force -ea SilentlyContinue try { #download it Write-Verbose "Download package" Invoke-WebRequest $c.Source -OutFile $msi if ( Test-Path $msi ) { $Sign = Get-AuthenticodeSignature $msi if ( $Sign.Status -eq 'Valid' -and $sign.SignerCertificate.DnsNameList[0].Unicode -eq 'Microsoft Corporation' ) { if ($force) { #de-install before re-install write-host -ForegroundColor Yellow "Removing current $($c.Type) package" Start-Process -FilePath "msiexec" -ArgumentList "/uninstall $($c.ID) " -Wait } try { if ($c.Type -ieq "MSI" ) { Write-Verbose "Install MSI package : $msi" Start-Process -FilePath "msiexec" -ArgumentList "/package $msi /passive" -Wait } else { $Options = "/Passive" if ($c.Setup ) { $Options = $c.SetupOptions } Write-Verbose "Install EXE package : $msi $options" Start-Process -FilePath $MSI -ArgumentList $options -Wait } $AppInfo = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$($c.ID)" -ErrorAction SilentlyContinue Write-Host $c.Name "Version :" $AppInfo.DisplayVersion " was installed" -f Green } catch { Write-warning "$($c.Name) could not be installed" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } } } catch { Write-Warning "could not install: $($c.Name)" } } else { Write-Host $c.Name "Version :" $AppInfo.DisplayVersion " is already installed" } } "MODULE" { # Add check for PS5 / WMF 5 if (Get-Command install-module) { #check for installed version of this module $Current = Get-Module -Name $c.Module -ListAvailable | sort -Property Version | select -First 1 $Source = Find-Module -Name $c.Module -Repository $c.Source -Verbose:$false if ( $Current -eq $null ) { write-verbose "Preparing to install module $($c.Module)" #Not yet installed , find source #if not installed or newer version avaialble if( $Source -and $Current -eq $null -or ($Source.Version -GT $Current.Version) ) { #install it $IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") #Check Admin Perms if (-not $IsAdmin) { Write-Verbose "Start PS elevated to admin to run the install" Start-Process "$psHome\powershell.exe" -Verb Runas -ArgumentList "-Command Install-Module -Name $($c.Module) -Repository $($c.Source)" } else { Install-Module -InputObject $source } $Now = Get-Module $c.Module -ListAvailable -Verbose:$false if ($now){ Write-Host "Installed $($now.Name) version : $($Now.Version)" } } else { #Could not be found Write-warning "The Module $($c.Name) Could not be located" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } else { #version already installed if ($Source.Version -gt $Current.Version -or $force ) { write-verbose "Updating Module $($c.Module)" if (-not $IsAdmin) { Write-Verbose "Start PS elevated to admin to run the install" Start-Process "$psHome\powershell.exe" -Verb Runas -ArgumentList "-Command update-Module -Name $($c.Module)" } else { update-Module -InputObject $source -Force:$force } } else { Write-verbose "Version : $($Current.Version) of $($c.Name) is already installed" } $NOW = Get-Module $c.Module -ListAvailable Write-Host "Version : $($NOW.Version) of $($c.Name) was newly installed" } } else { #No PS5 / WMF 5 Write-warning "The Module $($c.Name) cannot be installed automatically. Please install manually or install WMF 5 (preview)" #Open in browser if (-not [string]::IsNullOrEmpty($c.Web)){ Start-Process $c.Web } } } default { Write-Warning "Unknown component type"} } } } #test is both a parameterset as well as an option for installation if ($test ) { Write-Host -f Yellow "Starting Test" $script:Prog_pct = 0 $script:Prog_step = 100 /6 $ServiceName ='Microsoft Online Services Sign-in Assistant' $operation = $ServiceName write-verbose $Operation Write-Progress "Test and validate External powershell modules to connect to Office 365" ` -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step Write-Host "Validating Service: $ServiceName" -NoNewline $SignInAssistant = Get-Service -Name msoidsvc if ( $SignInAssistant -eq $null ) { Write-Host Write-Warning "Service : '$ServiceName' is not installed" } else { if ($SignInAssistant.Status -ine "Running" ) { Write-Host Write-Warning "Service '$ServiceName' is not running" Write-Host "Install the missing module using the -Install parameter." -ForegroundColor Yellow } else { Write-Host " - OK" -ForegroundColor Green } } #test if all Local modules are installed correctly foreach ($module in @( "MSonline","SkypeOnlineConnector","Microsoft.Online.Sharepoint.PowerShell","OfficeDevPnP.PowerShell.V16.Commands","AADRM" ) ) { $operation = $Module write-verbose $Operation Write-Progress "Test and validate External powershell modules to connect to Office 365" ` -CurrentOperation $Operation -PercentComplete $script:Prog_pct ; $script:Prog_pct += $prog_step Write-Host "Validating Module : $Module" -NoNewline $M = Get-Module -Name $module -ListAvailable if ($m -eq $null) { Write-Host Write-warning "Module '$Module' is not installed or cannot be located." Write-Host "Install the missing module using the -Install parameter, or restart PowerShell." -ForegroundColor Yellow } else { Try { Import-Module -Name $module -Force -DisableNameChecking remove-module -Name $module -Force Write-Host " - OK" -ForegroundColor Green } catch { Write-Host Write-warning "Module '$Module' could not be Imported." Write-Host "Install the missing module using the -Install parameter, or restart PowerShell." -ForegroundColor Yellow } } } } |