Conect AzureVM

You can manage your virtual machines directly on PowerShell using the Windows Remote Managing or WinRM and a PowerShell technique called Remote Shell, but locally.. so how you can use the same with you Azure VMs. let’s run this Script and wonder with the potential of this RemoteShell…

<#PSScriptInfo

.VERSION 1.0
.GUID b66368a8-dc27-481a-b4f3-dff65a6d42ee
.AUTHOR Azure-Automation-Team
.COMPANYNAME Microsoft
.COPYRIGHT
.TAGS AzureAutomation OMS VirtualMachines Utility
.LICENSEURI
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
#>
#Requires -Module Azure
<#
.DESCRIPTION
This runbook sets up a connection to an Azure virtual machine. It requires the Azure virtual machine to
have the Windows Remote Management service enabled, which is the default. It sets up a connection to the Azure
subscription and then imports the certificate used for the Azure VM so remote PowerShell calls can be made to it.
#>
Param()
<#
.SYNOPSIS
Sets up the connection to an Azure VM
.DESCRIPTION
This runbook sets up a connection to an Azure virtual machine. It requires the Azure virtual machine to
have the Windows Remote Management service enabled, which is the default. It sets up a connection to the Azure
subscription and then imports the certificate used for the Azure VM so remote PowerShell calls can be made to it.
.PARAMETER AzureSubscriptionName
Name of the Azure subscription to connect to.

.PARAMETER AzureOrgIdCredential
A credential containing an Org Id username / password with access to this Azure subscription.

 If invoking this runbook inline from within another runbook, pass a PSCredential for this parameter.
 If starting this runbook using Start-AzureAutomationRunbook, or via the Azure portal UI, pass as a string the
name of an Azure Automation PSCredential asset instead. Azure Automation will automatically grab the asset with
that name and pass it into the runbook.
.PARAMETER ServiceName
Name of the cloud service where the VM is located.
.PARAMETER VMName
Name of the virtual machine that you want to connect to.
.EXAMPLE
Connect-AzureVM -AzureSubscriptionName “Visual Studio Ultimate with MSDN” -ServiceName “Finance” -VMName “WebServer01” -AzureOrgIdCredential $cred
.NOTES
AUTHOR: System Center Automation Team
LASTEDIT: Dec 18, 2014
#>
workflow Connect-AzureVM
{
[OutputType([System.Uri])]
    Param
(
[parameter(Mandatory=$true)]
[String]
$AzureSubscriptionName,
  [parameter(Mandatory=$true)]
[PSCredential]
$AzureOrgIdCredential,

[parameter(Mandatory=$true)]
[String]
$ServiceName,

[parameter(Mandatory=$true)]
[String]
$VMName
)

Add-AzureAccount -Credential $AzureOrgIdCredential | Write-Verbose

 # Select the Azure subscription we will be working against
Select-AzureSubscription -SubscriptionName $AzureSubscriptionName | Write-Verbose
    InlineScript {
# Get the Azure certificate for remoting into this VM
$winRMCert = (Get-AzureVM -ServiceName $Using:ServiceName -Name $Using:VMName | select -ExpandProperty vm).DefaultWinRMCertificateThumbprint
$AzureX509cert = Get-AzureCertificate -ServiceName $Using:ServiceName -Thumbprint $winRMCert -ThumbprintAlgorithm sha1
        # Add the VM certificate into the LocalMachine
if ((Test-Path Cert:\LocalMachine\Root\$winRMCert) -eq $false)
{
Write-Progress “VM certificate is not in local machine certificate store – adding it”
$certByteArray = [System.Convert]::fromBase64String($AzureX509cert.Data)
$CertToImport = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (,$certByteArray)
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store “Root”, “LocalMachine”
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$store.Add($CertToImport)
$store.Close()
}

# Return the WinRM Uri so that it can be used to connect to this VM
Get-AzureWinRMUri -ServiceName $Using:ServiceName -Name $Using:VMName
}
}

Manage your AzureVMs

If you are handling by first time the Azure subscription, you can put the face as sitting in the millennial falcon… what this button stands for??

don’t worry, Azure is bringing so much that is simply impossible to afford all in a month. you keep learning all the time about it.

The Azure team, and the Office 365 got a plan, and they bring new capabilities every couple of weeks. as MCT we get a message directly from corp. where we was clearly advised to handle this courses with the actual material, and this MOC will be updated more frequently, than regular ones.

so, get back to the intention of this post. how can I manage my remaining U$200 of my trial, and stretch it so much as I can. well. first, if you’re patient, use the GUI and turn on/off your machines every time you’re gonna use them. if you don’t, try installing the Azure PowerShell module, https://azure.microsoft.com/en-us/downloads/ and then run the following  script to start your AzureVMs.

——————————————————-
Start-AzureVM -ServiceName CloudDemo001 -Name BOGDC01
——————————————————-
Import-module azure
Import-AzurePublishSettingsFile -PublishSettingsFile ‘c:\users\fcamp\Downloads\MSDN-11-5-2015-credentials.publishsettings’
Param(
[string]$servicename,
[string]$name,
[string]$userName,
[string]$password
)
$servicename = ‘CloudDemo001’
#get-AzureVM -ServiceName CloudDemo001 |ft
$name = ‘BOGDC01’
$userName = ‘admin’
$password = “WarMachineIsTheBest”
$vm = Get-AzureVM -ServiceName $servicename -Name $name
If ($vm.InstanceStatus -ne ‘ReadyRole’)
{
Write-Host (“VM is not running. InstanceStatus:” + $vm.instancestatus)
}
Else
{
$port = ($vm.VM.ConfigurationSets.Inputendpoints | Where { $_.LocalPort -eq 5986 }).Port
$vip = ($vm.VM.ConfigurationSets.Inputendpoints | Where { $_.LocalPort -eq 5986 }).Vip
$uri = (‘https://&#8217; + $vip + ‘:’ + $port)

$Credential = New-Object System.Management.Automation.PSCredential($username, $(ConvertTo-SecureString -String $password -AsPlainText -Force))
$SessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -NoMachineProfile
$PSSession = New-PSSession -ConnectionUri $uri -Credential $Credential -SessionOption $SessionOption

Enter-PSSession $PSSession
}

——————————————————-
Stop-AzureVM -ServiceName CloudDemo001 -Name BOGDC01
——————————————————-
Function Get-Uptime {
<#
.SYNOPSIS
Displays Uptime since last reboot
.PARAMETER  Computername
.EXAMPLE
Get-Uptime Server1
.EXAMPLE
“Server1”, “Server2″|Get-Uptime
.EXAMPLE
(Get-Uptime Sever1).”Time Since Last Reboot”
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,ValueFromPipeline=$true,Position=0)]
[STRING[]]$Computername
)

Begin {Write-Verbose “Version 1.00”}

Process {
$Now=Get-Date
$LastBoot=[System.Management.ManagementDateTimeConverter]::ToDateTime((Get-WmiObject win32_operatingsystem -ComputerName $computername).lastbootuptime)
$Result=@{ “Server”=$($Computername);
“Last Reboot”=$LastBoot;
“Time Since Reboot”=”{0} Days {1} Hours {2} Minutes {3} Seconds” -f ($Now – $LastBoot).days, `
($Now – $LastBoot).hours,($Now – $LastBoot).minutes,($Now – $LastBoot).seconds}
Write-Output (New-Object psobject -Property $Result|select Server, “Last Reboot”, “Time Since Reboot”)
}
}

Connect Office 365

Once you have you PC/PowerShell prepared, you can connect to Office 365, using a simple script as this, where you define your username, and thereafter you can simply click it. don’t forget, you use the dollar sign $ to generate PSvariables.

$User = “sysadmin@MyDomain.info”
$Pass = ConvertTo-SecureString “TheWarMachineIsTheBest.” -AsPlainText -Force
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $Pass
Import-Module MSOnline
Connect-msolservice -Credential $Cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
#Import-Module LyncOnlineConnector
#import-module microsoft.online.sharepoint.powershell
#$Session = New-CsOnlinesession -Credential $Cred
#Import-PSSession $Session
#[string]$tenant = get-msoldomain | where {$_.name -like “*.onmicrosoft.com” -and -not($_.name -like “*mail.onmicrosoft.com”)} | select name
#$tenant
#$tenant3 = $tenant -split(“=”)
#[string]$tenant4 = $tenant3[1]
#$tenant4
#$tenant5 = $tenant4 -split(“.on”)
#[string]$tenant6 = $tenant5[0]
#$url = “https://&#8221; + $tenant6 + “-admin.sharepoint.com”
#Connect-SPOService -Url $url -credential $Cred

Install PowerShell Options

The best powershell script that I should find in this learning path, was it that enabled my PowerShell with the capabilities to connect to Office 365, AzureAD, SkypeFBO, and Exchange Online.

this was found in the TechNet, but I’ve found it so interesting that I would like to share it. after you ran this, a menu will show, after that the modules can be installed simply selecting a number.

Go ahead. and try it

<#
.SYNOPSIS
Installs all required Powershell Modules, prompts user for needed info to connect to the different on premises and cloud services.
.DESCRIPTION
Allows easy user installation of powershell tools and connection strings.
.NOTES
Version       : 1.3 – Set IgnoreCA/CRL on Lync and Exchange Remote sessions to improve issues with non domain joined/VPN sessions (Thanks to Martin Bauer)
– Fixed the $prereq flag to clear once s/w installed correctly (weird connect to azure prerequisites menu prompt)
– Added S4B Online Powershell.  S4B On premises code is already compatible, just a menu update there (no new download yet!)
– Added Sharepoint Online Shell new revision 16.0.4017.1200 (http://www.microsoft.com/en-us/download/details.aspx?id=35588)
: 1.2 – Added 2 new options to set credentials per session globally for on premises and office 365
:     – Added Azure IaaS PowerShell to module list
:     – Added improved menu logic and menu reloads after every option
– Added logic for version checking on modules – will complete whenever updates occur
: 1.1 – Fixed the LyncOnlineConnector import line, added URL of blog article to this section.
: 1.0 – addressed MS Online Services Requirement for Azure AD on Windows 8.0, added more logging
Version history                   : .91 Fixed Lync Online installer to be quiet.
: .90 First version!
  Rights Required   : Administrative rights on any services
: Local Admin on machine to install software – elevated powershell is recommended, but
most installs prompt for elevation
Sched Task Required : No
Author/Copyright  : Chris Lehr – Multiple Modules borrowed from Pat Richard
Blog                  : http://blog.chrislehr.com/2015/04/install-powershelloptionsps1-script-to.html
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability

Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     : Only works on Windows 8/8.1 and Windows Server 2012 and Windows Server 2012 R2. This is by design. There are no
plans to support Windows Server 2008 R2.
Known issues    : Downloading files through a proxy is still somewhat of a kludge, especially if the proxy isn’t configured in IE.

.LINK
none yet
.EXAMPLE
.\Install-PowerShellOptions.ps1
  Description
———–
Runs script with default values.
#>
param(
# Defines the location for any downloaded files. Defaults to “c:\_install”. Additionally, log files generated by this script are located in a subfolder of TargetFolder called “logs”. TargetFolder does not support paths with spaces, but does support non-hidden UNC paths.
[Parameter(ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True, ParameterSetName = “Default”)]
[ValidatePattern(‘(?:[a-zA-Z]\:|\\\\[]\w\.+|\w-\\[\w.]+)\\(?:[\w]+\\)*\w[\w.]+’)]
[string] $TargetFolder = “$env:SystemDrive\_Install”
) # end of param block
function Write-Log {
<#
.SYNOPSIS
Extensive function to write data to either the console screen, a log file, and/or a Windows event log.
 .DESCRIPTION
Extensive function to write data to either the console screen, a log file, and/or a Windows event log. Data can be written as info, warning, error, and includes indentation, time stamps, etc.
 .NOTES
Version       : 2.7
Wish list      : Better error trapping
Rights Required   : Local administrator on server
Sched Task Required : No
Lync Server Version : N/A
Author/Copyright  :
Email/Blog/Twitter : pat@innervation.com  http://www.ehloworld.com @patrichard
Dedicated Post   :
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability
to use the script or documentation.
Acknowledgements   : Test for log names and sources
http://powershell.com/cs/blogs/tips/archive/2013/06/10/testing-event-log-names-and-sources.aspx
Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     :
Known issues    :
 .LINK
.EXAMPLE
.\
   Description
———–
.INPUTS
None. You cannot pipe objects to this script.
#>
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
param(
# The type of message to be logged. Alias is ‘type’.
[Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateSet(“Error”, “Warn”, “Info”)]
[ValidateNotNullOrEmpty()]
[string] $level = “Info”,
  # The message to be logged.
[Parameter(Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = “No message specified.”)]
[ValidateNotNullOrEmpty()]
[string] $Message,
  # Specifies that $message should not the sent to the log file.
[Parameter(Position = 2, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[switch] $NoLog,
  # Specifies to not display the message to the console.
[Parameter(Position = 3, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[switch] $NoConsole,
  # The number of spaces to indent the message in the log file.
[Parameter(Position = 4, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(1,30)]
[ValidateNotNullOrEmpty()]
[Int16] $Indent = 0,
  # Specifies what color the text should be be displayed on the console. Ignored when switch ‘NoConsoleOut’ is specified.
[Parameter(Position = 5, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateSet(“Black”, “DarkMagenta”, “DarkRed”, “DarkBlue”, “DarkGreen”, “DarkCyan”, “DarkYellow”, “Red”, “Blue”, “Green”, “Cyan”, “Magenta”, “Yellow”, “DarkGray”, “Gray”, “White”)]
[ValidateNotNullOrEmpty()]
[String] $ConsoleForeground = ‘White’,
  # Existing log file is deleted when this is specified. Alias is ‘Overwrite’.
[Parameter(Position = 6, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[Switch] $Clobber,
  # The name of the system event log, e.g. ‘Application’. Note that writing to the system event log requires elevated permissions.
[Parameter(Position = 7, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateSet(“Application”,”System”,”Security”,”Lync Server”,”Microsoft Office Web Apps”)]
[ValidateNotNullOrEmpty()]
[String] $EventLogName = “Application”,
  # The name to appear as the source attribute for the system event log entry. This is ignored unless ‘EventLogName’ is specified.
[Parameter(Position = 8, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateNotNullOrEmpty()]
[String] $EventSource = $($MyInvocation.ScriptName).Name,
  # The ID to appear as the event ID attribute for the system event log entry. This is ignored unless ‘EventLogName’ is specified.
[Parameter(Position = 9, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateRange(1,65535)]
[ValidateNotNullOrEmpty()]
[Int32] $EventID = 1,
  # The text encoding for the log file. Default is ASCII.
[Parameter(Position = 10, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateSet(“Unicode”,”Byte”,”BigEndianUnicode”,”UTF8″,”UTF7″,”UTF32″,”ASCII”,”Default”,”OEM”)]
[ValidateNotNullOrEmpty()]
[String] $LogEncoding = “ASCII”
)
try {
[string]$LogFolder = Split-Path $LogPath -Parent
if (-not(Test-Path $LogFolder)){New-Item $LogFolder -type Directory | Out-Null}
$msg = “{0} : {1} : {2}{3}” -f (Get-Date -Format “yyyy-MM-dd HH:mm:ss”), $Level.ToUpper(), (”  ” * $Indent), $Message
if (-not($NoConsole)){
switch ($level) {
“Error” {$Host.UI.WriteErrorLine(“$Message”)}
“Warn” {Write-Warning $Message}
“Info” {Write-Host $Message -ForegroundColor $ConsoleForeground}
}
}
if (-not($NoLog)){
if ($Clobber) {
$msg | Out-File -FilePath $LogPath -Encoding $LogEncoding -Force
} else {
$msg | Out-File -FilePath $LogPath -Encoding $LogEncoding -Append
}
}
  if ($EventLogName) {
if (-not $EventSource) {
[string] $EventSource = $([IO.FileInfo] $MyInvocation.ScriptName).Name
}
   if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) {
[Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName)
}
   switch ($Level) {
“Error” {$EntryType = “Error”}
“Warn”  {$EntryType = “Warning”}
“Info”  {$EntryType = “Information”}
Default  {$EntryType = “Information”}
}
Write-EventLog -LogName $EventLogName -Source $EventSource -EventId 1 -EntryType $EntryType -Message $Message
}
$msg = “”
}
catch {
Throw “Failed to create log entry in: ‘$LogPath’. The error was: ‘$_’.”
}
} # end function Write-Log
function Set-ModuleStatus {
<#
.SYNOPSIS
Imports a specified PowerShell module, with error checking.
 .DESCRIPTION
Imports a specified PowerShell module, with error checking.
 .NOTES
Version       : 1.5
Wish list      : Better error trapping
Rights Required   : None
Sched Task Required : No
Lync Server Version : N/A
Author/Copyright  : © Pat Richard, Lync MVP – All Rights Reserved
Email/Blog/Twitter : pat@innervation.com  http://www.ehloworld.com @patrichard
Dedicated Post   :
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability
to use the script or documentation.
Acknowledgements   :
Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     :
Known issues    :
 .LINK
.EXAMPLE
.\
   Description
———–
.INPUTS
None. You cannot pipe objects to this script.
#>
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
param (
[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = “No module name specified!”)]
[ValidateNotNullOrEmpty()]
[string] $name
)
PROCESS{
# Executes once for each pipeline object
# the $_ variable represents the current input object
if (-not(Get-Module -name “$name”)) {
if (Get-Module -ListAvailable | Where-Object Name -eq “$name”) {
Import-Module -Name “$name”
# module was imported
# return $true
} else {
# module was not available
# return $false
}
} else {
# Write-Output “$_ module already imported”
# return $true
}
} # end PROCESS
} # end function Set-ModuleStatus
function Test-IsProxyEnabled {
<#
.SYNOPSIS
Determines (the best it can) if a proxy is in place for Internet access.
 .DESCRIPTION
Determines (the best it can) if a proxy is in place for Internet access. If so, other functions that download files can better handle downloads.
 .NOTES
Version       : 1.1
Wish list      : Better error trapping
Rights Required   : Local administrator on server
Sched Task Required : No
Lync Server Version : N/A
Author/Copyright  : © Pat Richard, Lync MVP – All Rights Reserved
Email/Blog/Twitter : pat@innervation.com  http://www.ehloworld.com @patrichard
Dedicated Post   :
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability
to use the script or documentation.
Acknowledgements   :
Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     :
Known issues    :
 .LINK
.EXAMPLE
.\
   Description
———–
.INPUTS
None. You cannot pipe objects to this script.
#>
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
param ()
Write-Log -Message “Checking if a proxy is enabled” -NoConsole -Indent 1
# If this registry key doesn’t exist at all, it’s because IE has never been launched. We need to create it here so that download attempts and proxy checks don’t throw a silent error
if ((Get-Item “HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings”).Property -notcontains “ProxyEnable”){
Write-Log -Message “Internet Explorer has never been opened. Proxy registry values have yet to be set. Setting it to 0 now.” -NoConsole -Indent 1
New-ItemProperty “HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings” -Name ProxyEnable -Value 0 | Out-Null
}
if ((Get-ItemProperty “HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings” -name ProxyEnable -ErrorAction SilentlyContinue).ProxyEnable -ne 0){
Write-Log -Message “A proxy is required” -NoConsole -Indent 2
[string]$ProxyServer = (Get-ItemProperty “HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings” -name ProxyServer).ProxyServer
Write-Log -Message “Configured proxy: `”$ProxyServer`”” -NoConsole -Indent 2
  if (-not($PSDefaultParameterValues.ContainsKey(“Start-BitsTransfer:ProxyAuthentication”))){
Write-Log -Message “Prompting for credentials” -NoConsole -Indent 2
$ProxyCredentials = Get-Credential -Message “Enter Proxy authentication credentials for $ProxyServer” -UserName “${env:USERDOMAIN}\${env:UserName}”
if ($ProxyCredentials){
Write-Log -Message “Credentials entered” -NoConsole -Indent 2
Write-Log -Message “Adding default values for Start-BitsTransfer” -NoConsole -Indent 2
Write-Log -Message “Adding default value for ProxyAuthentication – `”Basic`”” -NoConsole -Indent 2
$PSDefaultParameterValues.Add(“Start-BitsTransfer:ProxyAuthentication”,”Basic”)
$ProxyUserName = $ProxyCredentials.username
Write-Log -Message “Adding default value for ProxyCredential – `”$ProxyUserName`”” -NoConsole -Indent 2
$PSDefaultParameterValues.Add(“Start-BitsTransfer:ProxyCredential”,$ProxyCredentials)
# Write-Log -Message “Adding default value for ProxyList – `”$ProxyServer`”” -NoConsole -Indent 1
# $PSDefaultParameterValues.Add(“Start-BitsTransfer:ProxyList”,$ProxyServer)
# Write-Log -Message “Adding default value for ProxyUsage – `”AutoDetect`”” -NoConsole -Indent 1
# $PSDefaultParameterValues.Add(“Start-BitsTransfer:ProxyUsage”,”AutoDetect”)
} else {
Write-Log -Level error -message “Credentials NOT entered. Following commands will likely fail” -NoConsole -Indent 2
}
}
} else {
Write-Log -Message “Proxy is not enabled” -NoConsole -Indent 2
# Clear the error queue in case the proxy registry key didn’t exist at all and threw an error.
$error.clear()
}
} # end function Test-IsProxyEnabled
function New-FileDownload {
<#
.SYNOPSIS
Downloads a file from a specified URL.
 .DESCRIPTION
Downloads a file from a specified URL. First, it verifies the file does not exist locally. Then ensures Internet access is available, then downloads the file.
 .NOTES
Version       : 1.3
Wish list      : Better error trapping
Rights Required   : Local administrator on server
Sched Task Required : No
Lync Server Version : N/A
Author/Copyright  : © Pat Richard, Lync MVP – All Rights Reserved
Email/Blog/Twitter : pat@innervation.com  http://www.ehloworld.com @patrichard
Dedicated Post   :
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability
to use the script or documentation.
Acknowledgements   :
Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     :
Known issues    :
 .LINK
.EXAMPLE
.\
   Description
———–
.INPUTS
None. You cannot pipe objects to this script.
#>
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
param(
# Complete path and file name to the file to be downloaded
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateNotNullOrEmpty()]
[string] $SourceFile,
  # The folder where the downloaded file should be placed. If not defined, it defaults to $TargetFolder.
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[string] $DestFolder,
  # The file name the downloaded file should be changed to. If not defined, file maintains it’s original name.
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[string] $DestFile,
  # Whether to download even if a local copy exists. This is useful for files that are updated often and need to be redownloaded.
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[switch] $IgnoreLocalCopy
)
[bool] $HasInternetAccess = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}’)).IsConnectedToInternet)
Test-IsProxyEnabled
# I should switch this to using a param block and pipelining from property name – just for consistency
 if (-not($DestFolder)){
$DestFolder = $TargetFolder
}
Set-ModuleStatus -name BitsTransfer
if (-not($DestFile)){
[string] $DestFile = ($SourceFile | Split-Path -leaf)
[Reflection.Assembly]::LoadWithPartialName(“System.Web”) | Out-Null
$DestFile = [System.Web.HttpUtility]::UrlDecode($DestFile)
}
if (Test-Path $DestFolder){
Write-Log -Message “Target folder `”$DestFolder`” exists – no need to create” -NoConsole -Indent 1
} else {
Write-Log -Message “Folder `”$DestFolder`” does not exist, creating…” -NoConsole
New-Item $DestFolder -type Directory | Out-Null
Write-Log -Message “Done!” -NoConsole -Indent 1
}
if ((Test-Path “$DestFolder\$DestFile”) -and (-not $IgnoreLocalCopy)){
if ($(((Get-Item $DestFolder\$DestFile).VersionInfo).FileVersion)){
Write-Log -Message “File `”$DestFile`” version $(((Get-Item $DestFolder\$DestFile).VersionInfo).FileVersion) exists locally – no need to download” -NoConsole
}else{
Write-Log -Message “File `”$DestFile`” exists locally – no need to download” -NoConsole
}
} else {
if ($HasInternetAccess){
Write-Log -Message “Internet access available” -NoConsole -Indent 1
if (-not $IgnoreLocalCopy){
Write-Log -Message “File `”$DestFile`” does not exist in `”$DestFolder`”” -NoConsole -Indent 1
} else {
Write-Log -Message “Forcing download of `”$DestFile`” to `”$DestFolder`”” -NoConsole
}
Write-Log -Message “Downloading `”$SourceFile`” to `”$DestFolder`”” -NoConsole -Indent 1
########################################################################################################
# NOTE: Default parameters may have been changed due to proxy settings. See Test-IsProxyEnabled function
########################################################################################################
# determine file size before downloading
<#
$clnt = New-Object System.Net.WebClient
$clnt.OpenRead($SourceFile) | Out-Null
$dlfilesize = [int] $($clnt.ResponseHeaders[“Content-Length”]/1mb)
# $dlfilesize
$clnt.Dispose()
#>
if ($dlfilesize){
Start-BitsTransfer -Source “$SourceFile” -Destination “$DestFolder\$DestFile” -Description “Downloading $DestFile ($dlfilesize MB)” -ErrorAction SilentlyContinue
}else{
Start-BitsTransfer -Source “$SourceFile” -Destination “$DestFolder\$DestFile” -Description “Downloading $DestFile” -ErrorAction SilentlyContinue
}
   if (Test-Path $DestFolder\$DestFile){
if ($(((Get-Item $DestFolder\$DestFile).VersionInfo).FileVersion)){
Write-Log -Message “Successfully downloaded $DestFolder\$DestFile version $(((Get-Item $DestFolder\$DestFile).VersionInfo).FileVersion)” -NoConsole -Indent 1
}else{
Write-Log -Message “Successfully downloaded $DestFolder\$DestFile” -NoConsole -Indent 1
}
} else {
Write-Log -Level error -message “Failed! File not downloaded!” -Indent 1
Write-Log -Message “Prompting user to abort/retry/ignore” -NoConsole
switch (New-Popup -message “A file download failure has occurred. What would you like to do?” -Title “Download error!” -Buttons “AbortRetryIgnore” -Icon Exclamation){
3{ # abort
Write-Log -Message “User has chosen to abort script” -NoConsole -Indent 1
Stop-Script
exit
}
4{ # retry
Write-Log -Message “User has chosen to retry” -NoConsole -Indent 1
Write-Log -Message “Building retry expression” -NoConsole -Indent 2
if ($IgnoreLocalCopy){
$DownloadRetry += ” -IgnoreLocalCopy”
}
if ($DestFile){
$DownloadRetry += ” -DestFile $Destfile”
}
if ($DestFolder){
$DownloadRetry += ” -DestFolder $DestFolder”
}
$DownloadRetryExp = “New-FileDownload -SourceFile $SourceFile”+ $DownloadRetry
Write-Log -Message “Retry expression is $DownloadRetryExp” -NoConsole -Indent 2
Invoke-Expression $DownloadRetryExp
}
5{ # ignore
Write-Log -Message “User has chosen to ignore” -NoConsole -Indent 1
}
}
}
} else {
Write-Log -Level warn -Message “Internet access not detected.”
Write-Log -Level warn -Message “This can be because there is no Internet connection,”
Write-Log -Level warn -Message “there is no DNS resolution,”
Write-Log -Level warn -Message “or a proxy is in place. Please resolve and try again.”
Write-Log -Level warn -Message “Alternatively, you can manually download the file ($SourceFile)”
Write-Log -Level warn -Message “and place it in $DestFolder and try again.”
}
}
} # end function New-FileDownload
function New-ProgramInstallation {
<#
.SYNOPSIS
Runs silent installation of programs, including install switches.
 .DESCRIPTION
Runs silent installation of programs, including install switches. Script can wait for processes and/or registry values to exist before continuing.
 .NOTES
Version       : 1.2
Wish list      : Better error trapping
Rights Required   : Local administrator on server
Sched Task Required : No
Lync Server Version : N/A
Author/Copyright  : © Pat Richard, Lync MVP – All Rights Reserved
Email/Blog/Twitter : pat@innervation.com  http://www.ehloworld.com @patrichard
Dedicated Post   :
Disclaimer       : You running this script means you won’t blame me if this breaks your stuff. This script is
provided AS IS without warranty of any kind. I disclaim all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for a particular
purpose. The entire risk arising out of the use or performance of the sample scripts and
documentation remains with you. In no event shall I be liable for any damages whatsoever
(including, without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use of or inability
to use the script or documentation.
Acknowledgements   :
Assumptions     : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations     :
Known issues    :
 .LINK
.EXAMPLE
New-ProgramInstallation -InstallFile “c:\installer.msi” -InstallSwitches “/qb”
   Description
———–
Runs installer.msi with the /qb switches
 .EXAMPLE
New-ProgramInstallation -InstallFile “c:\installer.msi” -InstallSwitches “/qb” -WaitForProcessName “MyProgramInstaller”
   Description
———–
Runs installer.msi with the /qb switches, and waits for the process called MyProgramInstaller to stop before continuing
 .EXAMPLE
New-ProgramInstallation -InstallFile “c:\installer.msi” -InstallSwitches “/qb” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{90150000-1151-0000-1000-0000000FF1CE}”
  Description
———–
Runs installer.msi with the /qb switches, and waits for the registry entry to be written before continuing
 .INPUTS
None. You cannot pipe objects to this script.
#>
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
param (
# Complete path and file name of the file to be executed.
[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = “No installation file specified”)]
[ValidateNotNullOrEmpty()]
[string] $InstallFile,
  # Any special command line switches to be used when executing the file.
[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string] $InstallSwitches,
  # If defined, the function will wait until the named process ends
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[string] $WaitForProcessName,
  # If defined, the function will wait until the named registry value exists
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[ValidatePattern(“^HKLM:|^HKCU:”)]
[string] $WaitForRegistryEntry,
  # If defined, the function will wait until the named path exists
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[string] $WaitForPath,
  # If specified, will display $LongInstallMessage to notify that this installation will take some time
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[switch] $LongInstall,
  # Text that is displayed if the installation will take a while.
[parameter(ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true)]
[string] $LongInstallMessage = “(this may take several minutes)”
)
$error.clear()
if (Test-Path $InstallFile){
Write-Log -Message “File exists” -NoConsole -Indent 1
# $DestFile = $InstallFile.Substring($InstallFile.LastIndexOf(“\”) + 1)
$DestFile = $($InstallFile | Split-Path -leaf)
if (-not $LongInstall){
Write-Log -Message “Installing `”$DestFile`””
}else{
Write-Log -Message “Installing `”$DestFile`” $LongInstallMessage”
}
$Install = $InstallFile+” “+$InstallSwitches
Write-Log -Message “Installation command line: `”$install`”” -NoConsole -Indent 1
    # Invoke-Command might work here if we don’t need to evaluate an expression
    Invoke-Expression $Install
# Start-Process -FilePath $InstallFile -ArgumentList $InstallSwitches -Wait
  if ($WaitForPath){
Write-Log -Message “Waiting for path `”$WaitForPath`” to exist” -NoConsole -Indent 1
do {Start-Sleep -Seconds 1} while (-not(Test-Path “$WaitForPath”))
Write-Log -Message “Path `”$WaitForPath`” exists” -NoConsole -Indent 1
}
  if ($WaitForRegistryEntry){
Write-Log -Message “Waiting for registry entry `”$WaitForRegistryEntry`” to be written” -NoConsole -Indent 1
do {Start-Sleep -Seconds 1} while (-not(Test-Path “$WaitForRegistryEntry”))
Write-Log -Message “Registry entry `”$WaitForRegistryEntry`” has been written” -NoConsole -Indent 1
}
  if ($WaitForProcessName){
Start-Sleep -s 1
Write-Log -Message “Waiting for process `”$WaitForProcessName`” to finish running” -NoConsole -Indent 1
Wait-Process -Name $WaitForProcessName
# do {Start-Sleep -Seconds 1} while (Get-Process -ProcessName “$WaitForProcessName” -ErrorAction SilentlyContinue)
Write-Log -Message “`”$WaitForProcessName`” is no longer running” -NoConsole -Indent 1
}
  if ($error){
Write-Log -Level Error -Message “Failed!” -Indent 1
Write-Log -Level error -Message $error
} else {
Write-Log -Message “Installed” -Indent 1
}
} else {
Write-Log -Level error -message “$DestFile does not exist. Unable to proceed.” -Indent 1
}
} # end function New-ProgramInstallation
$version = “1.3”
[string] $LogPath = “$TargetFolder\logs\$env:ComputerName” + ” {0:yyyy-MM-dd hh-mmtt}.log” -f (Get-Date)
[string] $LogDivider = “——————————“
$urlforAzureShell = “http://az412849.vo.msecnd.net/downloads04/azure-powershell.0.8.16.msi&#8221;
$urlforS4BShell = “” #unknown on 5/7/2015
Do {
Write-Log -Message $LogDivider -NoConsole
Write-Log -Message “Displaying main menu” -NoConsole
#Office 365 module Installation check
$SignIninstall = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  where { $_.displayname -match “Microsoft Online Services Sign-in Assistant” }
$SignInexpectedversion = “7.250.4556.0”
$AAdinstall = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  where { $_.displayname -match “Windows Azure Active Directory Module for Windows Powershell” }
$aadexpectedversion = “1.0.0”
$LYOInstall = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  where { $_.displayname -match “Microsoft Lync Online, Windows PowerShell Module” }
$LYOexpectedVersion = “5.0.8892.0”
$SPOInstall = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  where { $_.displayname -match “SharePoint Online Management Shell” }
$SPOexpectedVersion = “16.0.4017.1200”
$S4BInstall = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  where { $_.displayname -match “Skype for Business Online, Windows PowerShell Module” }
$S4BexpectedVersion = “6.0.9276.0”
$azureShellInstall = Get-ItemProperty HKLM:\SOFTWARE\Classes\Installer\Products\7A4D0A6FA7B10684CA58755AA6365B03 -ErrorAction SilentlyContinue
$AzureShellExpectedVersion = “0.8.16” #reports 524304 in the above reg path, but 0.8.16 once imported!!
$AzureShellExpectedVersionProgram = “524304”
## Need to add this checking in later and fix a few things – add the waitforegistry items, etc
$AADLoaded = (get-module msonline)
$LYOloaded = (get-module lynconlineconnector)
$SPOLoaded = (get-module Microsoft.Online.SharePoint.PowerShell)
$azureShellLoaded = (get-module Azure)
$S4BShellLoaded = (get-module )
# On premises install check not needed checking load only
$ADloaded = (get-module ActiveDirectory)
$EXLoaded = (get-module EXCHSESS)
$RTCLoaded = (get-module LYNCSESS)
# Check Microsoft Online Services Sign in Assistant status and set a flag for the execution logic and the menu option  (this one is silent)
if ($SIgnInInstall -and ($SignIninstall.displayversion -eq $SignInexpectedversion)) {
$SignInStatus = “Connect”
$SignInMenuUpdate = ”   Office 365 Sign in Assistant   Installed     $SignInexpectedversion”
} elseif ($SignInInstall -and ($SignIninstall.displayversion -ne $SignInexpectedversion)) {
$SignInStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$SignInStatus = “Install”
$SignInMenuUpdate = ”   Office 365 Sign in Assistant   Not Installed”
$prereq =”Prerequisites”
#######
}
# Check Windows Azure AD Shell status and set a flag for the execution logic and the menu option
if ($AADInstall -and ($aadinstall.displayversion -eq $aadexpectedversion)) {
$AADInstallOption = ”   Windows Azure Active Directory Installed     $aadexpectedversion”
$AADStatus = “Connect”
} elseif ($AADInstall -and ($aadinstall.displayversion -ne $aadexpectedversion)) {
$AADInstallOption = ”   Windows Azure Active Directory Update       $aadinstall.displayversion to $aadexpectedversion”
$AADStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$AADInstallOption = ”   Windows Azure AD PowerShell    Not Installed”
$AADStatus = “Install”
}
# Check Lync Online Shell status and set a flag for the execution logic and the menu option
if ($LYOInstall -and ($LYOinstall.displayversion -eq $LYOexpectedversion)) {
$LYOInstallOption = ”   Lync Online PowerShell         Installed     $LYOexpectedversion”
$LYOStatus = “Connect”
} elseif ($LYOInstall -and ($LYOinstall.displayversion -ne $LYOexpectedversion)) {
$LYOInstallOption = ”   Lync Online PowerShell         Update        $lyoinstall.displayversion to $LYOexpectedversion”
$LYOStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$LYOInstallOption = ”   Lync Online PowerShell         Not Installed”
$LYOStatus = “Install”
}
# Check S4B Online Shell status and set a flag for the execution logic and the menu option
if ($S4BInstall -and ($S4Binstall.displayversion -eq $S4Bexpectedversion)) {
$S4BInstallOption = ”   S4B Online PowerShell          Installed     $S4Bexpectedversion”
$S4BStatus = “Connect”
} elseif ($S4BInstall -and ($S4Binstall.displayversion -ne $S4Bexpectedversion)) {
$S4BInstallOption = ”   S4B Online PowerShell          Update        $S4Binstall.displayversion to $S4Bexpectedversion”
$S4BStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$S4BInstallOption = ”   S4B Online PowerShell          Not Installed”
$S4BStatus = “Install”
}
# Check SharePoint Online Shell status and set a flag for the execution logic and the menu option
if ($SPOInstall -and ($SPOinstall.displayversion -eq $SPOexpectedversion)) {
$SPOInstallOption = ”   SharePoint Online PowerShell   Installed     $SPOexpectedversion”
$SPOStatus = “Connect”
} elseif ($SPOInstall -and ($SPOinstall.displayversion -ne $SPOexpectedversion)) {
$spoinstalldisplayversion = $spoinstall.displayversion
$SPOStatus = “Connect”
$SPOInstallOption = ”   SharePoint Online PowerShell   Installed     $SPOexpectedversion”
# Upcoming feature, in place upgrade
# $SPOInstallOption = ”   SharePoint Online PowerShell   Update        $spoinstalldisplayversion to $SPOexpectedversion”
# $SPOStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$SPOInstallOption = ”   SharePoint Online PowerShell   Not Installed”
$SPOStatus = “Install”
}
# Check Active Directory Administration Tools status and set a flag for the execution logic and the menu option
if (get-module -list activedirectory) {

$ADInstallOption = ”   Active Directory RSAT Tools    Installed”
$ADStatus = “Connect”
} else {
$ADInstallOption = ”   Active Directory RSAT Tools    Not Installed”
$ADStatus = “Install”
}

# Check Azure PowerShell status and set a flag for the execution logic and the menu option
if ($AzureshellInstall -and ($azureshellinstall.version -eq $AzureshellexpectedversionProgram)) {
$AzureshellInstallOption = ”   Azure IaaS PowerShell          Installed     $Azureshellexpectedversion”
$AzureshellStatus = “Connect”
} elseif ($AzureShellInstall -and ($azureshellinstall.version -ne $AzureShellexpectedversion)) {
$AzureshellInstallOption = ”   Azure IaaS PowerShell          Update        $Azureshellexpectedversion”
$AzureshellStatus = “Upgrade”
#######
#  Waiting on updates
#######
} else {
$AzureshellInstallOption = ”   Azure IaaS PowerShell          Not Installed”
$AzureshellStatus = “Install”
}

if ($urlforS4BShell) {
$S4BOption = “6) $S4BStatus Skype for Business Online”
}

[string] $Menu = @”
   ┌──────────────────────────────────────────────────────────┐
|      Microsoft PowerShell Installer and Launcher v$version    |
└──────────────────────────────────────────────────────────┘
   $SignInMenuUpdate
$AADInstallOption
$LYOInstallOption
$SPOInstallOption
$ADInstallOption
$AzureshellInstallOption
$S4BInstallOption
Cloud PowerShell:
1) $AADStatus Azure Active Directory $prereq
2) $LYOStatus Lync/S4B Online
3) $SPOStatus SharePoint Online
4) Connect Exchange Online
5) $AzureShellStatus Azure IaaS
On Premises Remote PowerShell:
6) Connect Exchange
7) Connect Lync or S4B
8) $ADStatus Active Directory
 9)  Set Office 365 Identity for this Session
10) Set On Premises Identity for this Session
 99) Exit
Select an option.. [1-99]?
“@
 $MenuOption = Read-Host $Menu
switch ($MenuOption) {
1{ # Azure AD PowerShell Connect
if ($SignInStatus -eq “Connect”) {
# Do nothing
} elseif ($SignInStatus -eq “Upgrade”) {
#uninstall old version
                    # Need to run the uninstall string here
# Execute $SignIndinstall.UninstallString to uninstall current version
                } elseif ($SignInStatus -eq “Install” -and $prereq -eq “Prerequisites”) {
#install Sign in Assistant
#Install current version
write-host “in here”
if ($env:PROCESSOR_ARCHITECTURE -eq “AMD64”) {
Write-Host “Downloading Office Sign in Assistant for 64 bit..”
New-FileDownload -SourceFile $urlforMSSigninAssistant64
Write-Host “Installing MS Office Sign in Assistant 64 bit…”
Write-Log -Message “Installing MS Office Sign in Assistant 64 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforMSSigninAssistant64 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{D8AB93B0-6FBF-44A0-971F-C0669B5AE6DD}”
$prereq = “”
} else {
Write-Host “Downloading Office Sign in Assistant for 64 bit..”
New-FileDownload -SourceFile $urlforMSSigninAssistant32
Write-Host “Installing MS Office Sign in Assistant 32 bit…”
Write-Log -Message “Installing MS Office Sign in Assistant 32 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforMSSigninAssistant32 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{D8AB93B0-6FBF-44A0-971F-C0669B5AE6DD}”
$prereq = “”
}
}
# If pre-req’s are met, go for it
if ($AADStatus -eq “Connect”) {
Import-Module MSOnline
Write-Host “Connecting to Azure AD…”
if ($GlobalCloudCredential) {

Connect-MsolService -Credential $GlobalCloudCredential
} else {
$AADcredential = get-credential -message “Enter your Azure AD Admin Credentials”
Connect-MsolService -Credential $AADcredential
}
} elseif ($AADStatus -eq “Upgrade”) {

                # Need to run the uninstall string here
# Execute $AAdinstall.UninstallString to uninstall current version
#Install current version
            } elseif ($AADStatus -eq “Install”) {
#Install current version
Write-Host “Downloading Azure AD PowerShell…”
New-FileDownload -SourceFile $urlforAadShell
Write-Host “Installing Azure AD PowerShell…”
Write-Log -Message “Installing Azure AD PowerShell” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforAadShell | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{43CC9C53-A217-4850-B5B2-8C347920E500}”
Write-Host “Install Complete, re-select to connect!”
}

}
2{ # Lync Online PowerShell Connect
if ($LYOStatus -eq “Install”) {
# Lync Online PowerShell Install
Write-Host “Downloading Lync Online PowerShell…”
Write-Log -Message “Lync Online PowerShell install selected” -NoConsole -Indent 2
New-FileDownload -SourceFile $urlforLyoShell
Write-Host “Installing Lync Online PowerShell…”
Write-Log -Message “Lync Online PowerShell install beginning” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforLyoShell | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{3DA37B25-64F5-40D6-BB41-D0AB877A4821}”
} elseif ($LYOStatus -eq “Connect”) {
import-module LyncOnlineConnector
Write-Host “Connecting to Lync Online…”
if ($GlobalCloudCredential) {
$LYOsession = New-CsOnlineSession -Credential $GlobalCloudCredential
} else {
$LYOcredential = get-credential -message “Enter your Lync Online Admin Credentials”
$LYOsession = New-CsOnlineSession -Credential $LYOcredential
}
Import-PSSession $LYOsession
}
}
3{ # SharePoint Online PowerShell Connect
if ($SPOStatus -eq “Install”) {
Write-Host “Downloading SharePoint Online PowerShell…”
Write-Log -Message “SharePoint PowerShell install selected” -NoConsole -Indent 2
if ($env:PROCESSOR_ARCHITECTURE -eq “AMD64”) {
New-FileDownload -SourceFile $urlforsposhell64
Write-Host “Installing SharePoint Online PowerShell for 64 bit…”
Write-Log -Message “Installing SharePoint Online PowerShell for 64 bit” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforsposhell64 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95160000-115B-0409-1000-0000000FF1CE}”
} else {
New-FileDownload -SourceFile $urlforsposhell32
Write-Host “Installing SharePoint Online PowerShell for 32 bit…”
Write-Log -Message “Installing SharePoint Online PowerShell for 32 bit” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforsposhell32 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95160000-115B-0409-1000-0000000FF1CE}”
}

            } elseif ($SPOStatus -eq “Upgrade”) {
# Upcoming feature, in place upgrade
# Upcoming feature, in place upgrade
# Upcoming feature, in place upgrade
<# Write-Host “Upgrading SharePoint Online PowerShell…”
Write-Log -Message “SharePoint PowerShell upgrade selected” -NoConsole -Indent 2
if ($env:PROCESSOR_ARCHITECTURE -eq “AMD64”) {
#Uninstall old x64 version
Write-Host “Downloading SharePoint Online PowerShell…”
New-FileDownload -SourceFile $urlforsposhell64
Write-Host “Installing SharePoint Online PowerShell for 64 bit…”
Write-Log -Message “Installing SharePoint Online PowerShell for 64 bit” -NoConsole -Indent 2
# Update the wait for key
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforsposhell64 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95160000-115B-0409-1000-0000000FF1CE}”
} else {
#Uninstall old x86 version
Write-Host “Downloading SharePoint Online PowerShell…”
New-FileDownload -SourceFile $urlforsposhell32
Write-Host “Installing SharePoint Online PowerShell for 32 bit…”
Write-Log -Message “Installing SharePoint Online PowerShell for 32 bit” -NoConsole -Indent 2
# Update the wait for key
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforsposhell32 | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{95160000-115B-0409-1000-0000000FF1CE}”
}
#>
} elseif ($SPOStatus -eq “Connect”) {
$SPOTenantID = read-host -Prompt “Enter your Office 365 tenantID (The name before the .onmicrosoft.com)”
import-module Microsoft.Online.SharePoint.PowerShell
Write-Host “Connecting to SharePoint Online…”
Write-Log -Message “Sharepoint Online Connection String – $spoconnectionstring” -NoConsole -Indent 2
                $SPOConnectionString = “https://&#8221; + $SPOTenantID + “-admin.sharepoint.com”
if ($GlobalCloudCredential) {
Connect-SPOService -Url $SPOConnectionString -Credential $GlobalCloudCredential
} else {
$SPOcredential = get-credential -message “Enter your SharePoint Online Admin Credentials”
Connect-SPOService -Url $SPOConnectionString -Credential $SPOcredential
}
}
}
        4{ # Exchange Online PowerShell Connect
Write-Host “Connecting to Exchange Online…”
if ($GlobalCloudCredential) {
$EXOSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $globalcloudcredential -Authentication Basic -AllowRedirection
} else {
$EXOcredential = get-credential -message “Enter your Exchange Online Admin Credentials”
$EXOSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $EXOCredential -Authentication Basic -AllowRedirection
}
Import-PSSession $EXOsession
}
        5{ #Azure iAAS PowerShell
if ($AzureShellStatus -eq “Install”) {
Write-Host “Downloading Azure IaaS PowerShell…”
Write-Log -Message “Azure IaaS PowerShell install selected” -NoConsole -Indent 2
New-FileDownload -SourceFile $urlforAzureShell
Write-Host “Installing Azure IaaS PowerShell…”
Write-Log -Message “Installing Azure IaaS PowerShell” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforAzureShell | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Classes\Installer\Products\7A4D0A6FA7B10684CA58755AA6365B03”
} elseif ($AzureShellStatus -eq “Connect”) {
Write-Host “Connecting to Azure IaaS…”

if ($GlobalCloudCredential) {
Add-Azureaccount -Credential $GlobalCloudCredential
} else {
$AzureShellcredential = get-credential -message “Enter your Azure IaaS Admin Credentials”
Add-Azureaccount -Credential $AzureShellcredential
}
}
}

  <#6{ # S4B Online PowerShell Connect
if ($S4BOStatus -eq “Install”) {
# S4B Online PowerShell Install
Write-Host “Downloading S4B Online PowerShell…”
Write-Log -Message “S4B Online PowerShell install selected” -NoConsole -Indent 2
New-FileDownload -SourceFile $urlforS4BShell
Write-Host “S4B S4B Online PowerShell…”
Write-Log -Message “Lync Online PowerShell install beginning” -NoConsole -Indent 2
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforS4BShell | Split-Path -leaf)” -InstallSwitches “/passive” -WaitForRegistryEntry “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{D7334D5D-0FA2-4DA9-8D8A-883F8C0BD41B}”
} elseif ($S4BStatus -eq “Connect”) {
import-module SkypeOnlineConnector  #
Write-Host “Connecting to S4B Online…”
if ($GlobalCloudCredential) {
$S4Bsession = New-CsOnlineSession -Credential $GlobalCloudCredential
} else {
$S4Bcredential = get-credential -message “Enter your S4B Online Admin Credentials”
$S4Bsession = New-CsOnlineSession -Credential $S4Bcredential
}
Import-PSSession $S4Bsession
}
}
#>
#
# On Premises
#
6{ # Exchange On Premises PowerShell Connect
$EXServer = read-host -Prompt “Enter Exchange Server Name to connect to”
$EXConnectionUri = “http://&#8221; + $EXserver + “/PowerShell/”
$exsessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
if ($GlobalOnPremisesCredential) {
$EXSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $EXConnectionURI -Authentication Kerberos -Credential $GlobalOnPremisesCredential -SessionOption $exsessionOption
} else {
$EXcredential = get-credential -message “Enter your Exchange Admin Credentials”
$EXSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $EXConnectionURI -Authentication Kerberos -Credential $EXcredential -Name “EXCHSESS” -SessionOption $exsessionOption
}
Import-PSSession $EXsession
}
7{ # Lync/S4B On Premises PowerShell Connect
$LyncServer = read-host -Prompt “Enter Lync or S4B Front End Server Name to connect to”
$LyncConnectionUri = “https://&#8221; + $LyncServer + “/OCSPowerShell/”
$LyncsessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
if ($GlobalOnPremisesCredential) {
$LyncSession = New-PSSession -ConnectionUri $LyncConnectionURI -Authentication Negotiate -Credential $globalOnPremisesCredential -SessionOption $LyncsessionOption
} else {
$LyncCredential = get-credential -message “Enter your Lync Admin Credentials”
                $LyncSession = New-PSSession -ConnectionUri $LyncConnectionURI -Authentication Negotiate -Credential $LyncCredential -Name “LYNCSESS” -SessionOption $LyncsessionOption
}
Import-PSSession $LyncSession
}
8{ # Active Directory On Premises PowerShell Connect
if ($ADstatus -eq “Install”) {
Write-Host “Downloading AD Remote Admin Tools”
Write-Log -Message “AD Remote Admin Tools install selected” -NoConsole -Indent 2
$ADStatus =”Connect”
if ((Get-WmiObject -Class win32_operatingsystem).caption -match “Windows 8 “) {
if ($env:PROCESSOR_ARCHITECTURE -eq “AMD64”) {
New-FileDownload -SourceFile $urlforRSAT64
Write-Host “Installing AD Remote Admin Tools for Windows 8.0 64 bit…”
Write-Log -Message “Installing AD Remote Admin Tools for Windows 8.0 64 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforRSAT64 | Split-Path -leaf)” -InstallSwitches “/quiet /promptrestart”
& dism.exe /Online /Enable-Feature /FeatureName:RemoteServerAdministrationTools  /FeatureName:RemoteServerAdministrationTools-Roles /FeatureName:RemoteServerAdministrationTools-Roles-AD  /FeatureName:RemoteServerAdministrationTools-Roles-AD-Powershell
} else {
New-FileDownload -SourceFile $urlforRSAT32
Write-Host “Installing AD Remote Admin Tools for Windows 8.0 32 bit…”
Write-Log -Message “Installing AD Remote Admin Tools for Windows 8.0 32 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlforRSAT32 | Split-Path -leaf)” -InstallSwitches “/quiet /promptrestart”
& dism.exe /Online /Enable-Feature /FeatureName:RemoteServerAdministrationTools  /FeatureName:RemoteServerAdministrationTools-Roles /FeatureName:RemoteServerAdministrationTools-Roles-AD  /FeatureName:RemoteServerAdministrationTools-Roles-AD-Powershell
}
} elseif ((Get-WmiObject -Class win32_operatingsystem).caption -match “Windows 8.1”) {
if ($env:PROCESSOR_ARCHITECTURE -eq “AMD64”) {
New-FileDownload -SourceFile $urlfor81RSAT64
Write-Host “Installing AD Remote Admin Tools for Windows 8.1 64 bit…”
Write-Log -Message “Installing AD Remote Admin Tools for Windows 8.1 64 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlfor81RSAT64 | Split-Path -leaf)” -InstallSwitches “/quiet /promptrestart”
& dism.exe /Online /Enable-Feature /FeatureName:RemoteServerAdministrationTools  /FeatureName:RemoteServerAdministrationTools-Roles /FeatureName:RemoteServerAdministrationTools-Roles-AD  /FeatureName:RemoteServerAdministrationTools-Roles-AD-Powershell
} else {
New-FileDownload -SourceFile $urlfor81RSAT32
Write-Host “Installing AD Remote Admin Tools for Windows 8.1 32 bit…”
Write-Log -Message “Installing AD Remote Admin Tools for Windows 8.1 32 bit” -NoConsole -Indent 3
New-ProgramInstallation -InstallFile “$TargetFolder\$($urlfor81RSAT32 | Split-Path -leaf)” -InstallSwitches “/quiet /promptrestart”
& dism.exe /Online /Enable-Feature /FeatureName:RemoteServerAdministrationTools  /FeatureName:RemoteServerAdministrationTools-Roles /FeatureName:RemoteServerAdministrationTools-Roles-AD  /FeatureName:RemoteServerAdministrationTools-Roles-AD-Powershell
                }
            } elseif ($ADstatus -eq “Connect”) {
import-module ActiveDirectory
}
}
}
9{ # Set Cloud Credential
write-host “Collecting Office 365 credentials  for this session”
$GlobalCloudCredential = Get-Credential -Message “Please enter your global admin credentials for all Office 365 services”
}
        10{ # Set On premises Credential
write-host “Collecting on premises credentials for this session”
$GlobalOnPremisesCredential = Get-Credential -Message “Please enter your Enterprise Admin and/or Exchange/Lync Admin for On Premises Services”
}
}
} while ($MenuOption -notmatch {^99$|^x$})

Tools for troubleshoot network connections

Hi everyone,

Today I wish to list a set of cmd line tools to diagnose and repair your network connections, but I want to invite you to explore the PowerShell Cmd-Lets to diagnose your connectivity.

  • Ipconfig (a.k.a Get-NetIpAddress) let you know what IP address is using your machine, if you see an 127.0.0.1 as your IP, your machine probably is network disconnected. also if you are getting a 169.254.x.x this is called an APIPA address, that means that you are connected as well, but you are out of network because the DHCP server should be down.
  • Ping (a.k.a Test-NetConnection) allows to check an echo request to a desired host. this lets you know if you or your counterpart are capable to respond to network traffic
  • Tracert (a.k.a Get-NetRoute) This one lets you know how are jumping the packages between routers and switches to reach the destination. this tools also lets us to know how often the times from jump to jump are.
  • NSLookup (a.k.a. Resolve-DnsName) brings back the IP address of a desired host.

Also you can use another GUI tools as Event Viewer, Message analyzer, and Windows Network diagnostics. but you can try a Get-Eventlog -Logname System -EntryType Error -Newest 5

Regards.