Loading...

Follow Microsoft Technologies Blog – Cloud on Feedspot

Continue with Google
Continue with Facebook
or

Valid

We had a requirement to Add all Skype for Business Online users to Active directory group on daily basis.

This is required because we want to implement a Group Policy for ALL Skype for Business Online users but not  for on-premise Lync users.

Our environment is Hybrid and Migration is in progress.

Script will run daily and compare the Active Directory group with current Skype for Business Online users.

users will be added and removed from the group based on that comparison.

Prerequisite:

  • Skype Module
  • Active directory Module

To get all Skype for business users, script uses below cmdlet

$Allskobonlineusers = Get-CsUser -Filter {HostingProvider -eq “sipfed.online.lync.com”} | Select -ExpandProperty UserPrincipalName

To speed up the addition and removal process, we have coded in a manner that 100 users can be added or removed at ones.

Script has been parameterized

————————————————————————————————————————————–

param ( 

[string]$Group = $(Read-host “Enter AD group”), 

[string]$smtpserver = $(Read-host “Enter SMTP Server”), 

[string]$from = $(Read-host “Enter From Address”), 

[string]$erroremail = $(Read-host “Enter Address for Report and Errors”),

$count = $(Read-host “Enter threshold for addition and removal”)

)

—————————————————————————————————————————————–

$group –> AD group that you want to populate with Skype for Business Online users(just add one user manually for the first RUN)

$smtpserver  –> SMTP relay server for sending Alert in case script fails and also sending log via email.

$from –> Address from which you want to send email alerts.

$erroremail –> Recipient address to which emails are delivered.

$count –> This is important as if there is some anomaly, it will protect the addition or removal of false positive members.

For our environment We have set it to 500 as no more than that are provisioned or terminated (Skype for Business).

Note: Script will recycle logs after 60 days , if you want to change it than change the below variable at the end of the script.

$limit = (Get-Date).AddDays(-60) #for report recycling


Download the script from Powershell Gallery and execute it as shown, it can be scheduled to run daily from Task scheduler.

https://www.powershellgallery.com/packages/SKOBOnlineUsers2ADGroup

if you will use powershell gallery than script will download under C:\Program Files\WindowsPowerShell\Scripts (you can copy it to the location that you desire)

<#     
    .NOTES 
    =========================================================================== 
     Created with:     ISE 
     Created on:       4/16/2019 1:46 PM 
     Created by:       Vikas Sukhija 
     Organization:      
     Filename:         SKOBOnlineUsers2ADGroup.ps1 
    =========================================================================== 
    .DESCRIPTION 
        This script will add all SKOB users to AD group 
#> 
####################Load All Functions############################## 
param ( 
  [string]$Group = $(Read-host "Enter AD group"), 
  [string]$smtpserver = $(Read-host "Enter SMTP Server"), 
  [string]$from = $(Read-host "Enter From Address"), 
  [string]$erroremail = $(Read-host "Enter Address for Report and Errors"), 
  $count = $(Read-host "Enter threshold for addition and removal") 
) 
 
function Write-Log 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [array]$Name, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$Ext, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$folder, 
     
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, 
     
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$Message, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$path, 
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')] 
    [ValidateSet('Information','Warning','Error')] 
    [string]$Severity = 'Information', 
     
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG 
  ) 
  switch ($PsCmdlet.ParameterSetName) { 
    "Create"{ 
      $log = @() 
      $date1 = Get-Date -Format d 
      $date1 = $date1.ToString().Replace("/", "-") 
      $time = Get-Date -Format t 
     
      $time = $time.ToString().Replace(":", "-") 
      $time = $time.ToString().Replace(" ", "") 
     
      foreach ($n in $Name) 
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} 
      return $log 
    } 
    "Message"{ 
      $date = Get-Date 
      $concatmessage = "|$date" + "|   |" + $Message +"|  |" + "$Severity|" 
      switch($Severity){ 
        "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} 
        "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} 
        "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} 
      } 
       
      Add-Content -Path $path -Value $concatmessage 
    } 
  } 
} 
 
function ProgressBar 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true)] 
    $Title, 
    [Parameter(Mandatory = $true)] 
    [int]$Timer 
  ) 
     
  For ($i = 1; $i -le $Timer; $i++) 
  { 
    Start-Sleep -Seconds 1; 
    Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /10 * 100) 
  } 
} 
#################Check if logs folder is created################## 
$logpath  = (Get-Location).path + "\logs"  
$testlogpath = Test-Path -Path $logpath 
if($testlogpath -eq $false) 
{ 
  ProgressBar -Title "Creating logs folder" -Timer 10 
  New-Item -Path (Get-Location).path -Name Logs -Type directory 
} 
 
 
##########################Load variables & Logs#################### 
 
$log = Write-Log -Name "log_SKOBONline2ADgroup" -folder logs -Ext log 
 
$group  
$smtpserver 
$from 
$erroremail 
$count 
 
########################mainScript################################ 
Write-Log -Message "Start Script" -path $log  
try{ 
  Import-Module -Name activedirectory 
  Write-Log -Message "AD Module Loaded" -path $log 
} 
catch{ 
  $exception = $_.Exception 
  Write-Log -Message "Error loading AD Module Loaded" -path $log -Severity Error  
  Write-Log -Message $exception -path $log -Severity error 
  Send-MailMessage -SmtpServer $smtpserver -To $erroremail -From $from -Subject "Error has occured loading AD Module - SKOBOnlineUsers2ADGroup" -Body $($_.Exception.Message) 
  Exit 
} 
 
$Allskobonlineusers = Get-CsUser -Filter {HostingProvider -eq "sipfed.online.lync.com"} | Select -ExpandProperty UserPrincipalName 
Write-Log -Message "Fetched all SKOB users" -path $log  
 
  $allUPN = Get-ADGroup  $group -Properties Member |  
  Select-Object -ExpandProperty Member | 
  Get-ADUser | 
  Select-Object -ExpandProperty UserPrincipalName 
  Write-Log -Message "Fetched all UPN from $group" -path $log 
 
###############Comaore to get adds/removes######################## 
$change = Compare-Object -ReferenceObject $Allskobonlineusers -DifferenceObject $allUPN  
 
$Removal = $change | 
Where-Object -FilterScript {$_.SideIndicator -eq "=>"} | 
Select-Object -ExpandProperty InputObject 
 
$Addition = $change | 
Where-Object -FilterScript {$_.SideIndicator -eq "<="} | 
Select-Object -ExpandProperty InputObject 
 
$removalcount = $Removal.count 
$additioncount = $Addition.count 
Write-Log -Message "Count of removal is $removalcount" -path $log 
Write-Log -Message "Count of Addition is $additioncount" -path $log 
 
if(($Removal.count -gt $count) -or ($Addition.count -gt $count)){ 
  Write-Log -Message "Count of is greater than $count" -path $log -Severity Warning 
  Write-Log -Message "Script Terminated" -path $log -Severity error 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Count of is greater than $count - SKOBOnlineUsers2ADGroup" -Body "Count of is greater than $count - SKOBOnlineUsers2ADGroup" 
  break 
} 
else 
{ 
  Write-Log -Message "Processing --------------- removals" -path $log 
  $collremoves=@() 
  $Removal | ForEach-Object -Process { 
    $upn = $_ 
    Write-Log -Message "Removing $upn from $group" -path $log 
    $getuser = Get-ADUser -Filter {UserPrincipalName -eq $upn}  
    $collremoves+=$getuser.samaccountname 
    } 
  Write-Log -Message "Collected all Removals" -path $log 
   
  $val=0 
  $collremovescoll = @() 
  for($i=0;$i -lt $collremoves.count){ 
    While($val -ne "100"){ 
      $collremovescoll+=$collremoves[$val + $i] 
      $val++ 
    } 
    if($val -eq "100"){ 
      $val=0 
      $i=$i+100 
      $collremovescoll = $collremovescoll | where{$_} 
      Write-Log -Message "Remove Members ....$collremovescoll" -path $log 
        Remove-ADGroupMember -identity $group -Members $collremovescoll -Confirm:$false 
        $collremovescoll=@() 
    } 
  } 
   
   
  Write-Log -Message "Processing ---------------- Additions" -path $log 
  $colladditions=@() 
  $Addition | ForEach-Object -Process { 
    $upn = $_ 
    Write-Log -Message "Adding $upn to $group" -path $log 
    $getuser = Get-ADUser -Filter {UserPrincipalName -eq $upn}  
    $colladditions+=$getuser.samaccountname 
    } 
  Write-Log -Message "Collected all Additions" -path $log 
   
  $val=0 
  $colladditionscoll = @() 
  for($i=0;$i -lt $colladditions.count){ 
    While($val -ne "100"){ 
      $colladditionscoll+=$colladditions[$val + $i] 
      $val++ 
    } 
    if($val -eq "100"){ 
      $val=0 
      $i=$i+100 
      $colladditionscoll = $colladditionscoll | where{$_} 
        Write-Log -Message "ADD Members ....$colladditionscoll" -path $log 
        ADD-ADGroupMember -identity $group -Members $colladditionscoll -Confirm:$false 
        $colladditionscoll=@() 
    } 
  } 
} 
 
########################Recycle reports & logs############## 
$path1 = $logpath 
$limit = (Get-Date).AddDays(-60) #for report recycling 
Get-ChildItem -Path $path1 | 
Where-Object -FilterScript {$_.CreationTime -lt $limit} | 
Remove-Item -Recurse -Force 
 
Write-Log -Message "Script Finished" -path $log 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Transcript Log - SKOBOnlineUsers2ADGroup" -Body "Transcript Log - SKOBOnlineUsers2ADGroup" -Attachments $log 
 
##############################################################

Thanks for reading and downloading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

This requirement came from our management to extract the Teams report across our tenant.

Fortunately in the latest team module released by Microsoft, you can extract all the Teams across the Tenant and its not like the older module where you can get only the Teams you own.

Here is the requirement:

  • All Teams across the Tenant
  • It should show if Team is public or private, Name, Sharepoint Url
  • Show Count Public and Private (Total count)

Extract the below script and run in Powershell as shown below.

https://gallery.technet.microsoft.com/scriptcenter/Teams-Report-for-Office-2e7a7b82

or you can get this Script from PowerShell gallery (Install-Script -Name TeamsReport)

https://www.powershellgallery.com/packages/TeamsReport

Change below parameters under logs and variables

$smtpserver = “SMTPserver”

$from = “donotreply@labtest.com”

$erroremail = “Reports@labtest.com”

Below are the prerequisites to run this script as all the above requirements for the report can not be fulfilled just by using Teams module, we need to extract some stuff from the office 365 group object or you can say Exchange unified group.

  • Latest team module

Install-Module -Name MicrosoftTeams -RequiredVersion 0.9.5

https://www.powershellgallery.com/packages/MicrosoftTeams/0.9.5

  • Exchange Online Shell

Script will first connect to teams to extract all the Teams in the tenant and than all unified groups from Exchange online.

Ones these are fetched, these are compared to each other via groupid as anchor to extract the report as needed.

Logs and report folder are created if these do not exist, for storing log and html report.

HTML report will not only be saved under the report folder but is sent via email.

Logs and report retention is set to 60 days and can be changed by editing the limit value towards the end of the script.

<#     
    .NOTES 
    =========================================================================== 
    Created on:       4/02/2019 2:26 PM 
    Created by:       Vikas Sukhija 
    Organization:      
    Filename:         TeamsReport.ps1 
    =========================================================================== 
    .DESCRIPTION 
    This will report on AL teams across the tenant 
    Requires: Latest teams module and Exchaneg online Shell 
#> 
############Script Parameters############## 
param ( 
  [string]$userId = $(throw "userid is required"),  
  [string]$password = $(throw "password is required") 
) 
#############Load Functions################# 
$error.clear() 
try { $null = Stop-Transcript } 
catch { $error.clear() } 
 
function Write-Log 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [array]$Name, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$Ext, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$folder, 
     
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, 
     
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$Message, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$path, 
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')] 
    [ValidateSet('Information','Warning','Error')] 
    [string]$Severity = 'Information', 
     
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG 
  ) 
  switch ($PsCmdlet.ParameterSetName) { 
    "Create" 
    { 
      $log = @() 
      $date1 = Get-Date -format d 
      $date1 = $date1.ToString().Replace("/", "-") 
      $time = Get-Date -format t 
     
      $time = $time.ToString().Replace(":", "-") 
      $time = $time.ToString().Replace(" ", "") 
     
      foreach ($n in $Name) 
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} 
      return $log 
    } 
    "Message" 
    { 
      $date = Get-Date 
      $concatmessage = "|$date" + "|   |" + $Message +"|  |" + "$Severity|" 
      switch($Severity){ 
        "Information"{Write-Host $concatmessage -ForegroundColor Green} 
        "Warning"{Write-Host $concatmessage -ForegroundColor Yellow} 
        "Error"{Write-Host $concatmessage -ForegroundColor Red} 
      } 
       
      Add-Content -Path $path -Value $concatmessage 
    } 
  } 
} 
 
function LaunchEOL 
{ 
  param 
  ( 
    $cred 
  ) 
     
  $UserCredential = $cred 
     
  $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection 
     
  Import-PSSession $Session -Prefix "EOL" -AllowClobber 
} 
Function RemoveEOL 
{ 
  $Session = Get-PSSession | where { $_.ComputerName -like "outlook.office365.com" } 
  Remove-PSSession $Session 
} 
##########################Load variables & Logs#################### 
$log = Write-Log -Name "MSTeamOwnerReport" -folder logs -Ext log 
$output1 = Write-Log -Name "MSTeamOwner" -folder Report -Ext html 
 
$smtpserver = "SMTPserver" 
$from = "donotreply@labtest.com" 
$erroremail = "Reports@labtest.com" 
$collection =@() 
 
#####################Create folder and credential from arguments############### 
$logpath  = (Get-Location).path + "\logs"  
$testlogpath = Test-Path -Path $logpath 
if($testlogpath -eq $false) 
{New-Item -Path (Get-Location).path -Name Logs -Type directory} 
 
$reportpath = (Get-Location).path + "\Report" 
$testReportpath = Test-Path -Path $reportpath 
if($testReportpath -eq $false) 
{New-Item -Path (Get-Location).path -Name Report -Type directory} 
 
$pwd = $password | ConvertTo-SecureString -asPlainText -Force 
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd 
##########Start Script main############## 
 
Write-Log -Message "Script....Started" -path $log 
try 
{ 
  Connect-MicrosoftTeams -Credential $Credential 
  Write-Log -Message "Connected to teams Module" -path $log 
} 
catch 
{ 
  $exception = $($_.Exception.Message) 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error Connecting MS Team Module MS Team Report" -Body $($_.Exception.Message) 
  Write-Log -Message "Exception occured connecting Teams module $exception" -path $log -Severity Error 
  Exit 
} 
try 
{ 
  Write-Host "Connecting to EOL" -ForegroundColor Green 
  LaunchEOL -cred $Credential 
  Write-Log -Message "Connected to Exchange Online" -path $log 
} 
catch 
{ 
  $exception = $($_.Exception.Message) 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error - EOL Connection MS Team Report" -Body $($_.Exception.Message) 
  Write-Log -Message "Exception occured connecting EOL Shell $exception" -path $log -Severity Error 
  Exit 
} 
 
$collTeam = Get-Team | select DisplayName, GroupId, Description 
Write-Log -Message "feteched All Teams" -path $log 
Disconnect-MicrosoftTeams 
$collUnifiedGroup = get-EOLunifiedgroup -resultsize unlimited | select Name, AccessType, ExternalDirectoryObjectId, WhenCreated, ManagedByDetails, SharePointSiteUrl 
Write-Log -Message "feteched All Unified Groups" -path $log 
RemoveEOL 
Foreach($team in $collTeam) 
{ 
  $mcoll = "" | select Name, Description, GroupId, AccessType, WhenCreated, SharePointSiteUrl, ManagedByDetails 
  $teamdispname = $team.DisplayName 
  Write-Log -Message "Processing.............$teamdispname" -path $log 
  $mcoll.Name = $team.DisplayName 
  $mcoll.Description = $team.Description 
  $mcoll.GroupId = $team.groupId 
  foreach($ugroup in $collUnifiedGroup) 
  { 
    if($team.GroupId -eq $ugroup.ExternalDirectoryObjectId) 
    { 
      $mcoll.AccessType = $ugroup.AccessType 
      $mcoll.WhenCreated = $ugroup.WhenCreated 
      $mcoll.SharePointSiteUrl = $ugroup.SharePointSiteUrl 
      $mcoll.ManagedByDetails = $ugroup.ManagedByDetails 
    } 
  } 
   
  $collection += $mcoll 
} 
 
############Format HTML########### 
$HTMLFormat = "" 
################################ 
$count = $collection.count 
$privateteams = $collection | where{$_.AccessType -eq "Private"} 
$publicteams = $collection | where{$_.AccessType -eq "Public"} 
$privateteamscount = $privateteams.count 
$publicteamscount = $publicteams.count 
 
Write-Log -Message "Converting to HTML" -path $log 
$collection | 
ConvertTo-Html -Head $HTMLFormat -Body "<H2><Font Size = 4,Color = DarkCyan>Microsoft Teams = $count, Private Teams = $privateteamscount, Public Teams = $publicteamscount  </Font></H2>" -AS Table | 
Set-Content $output1 
 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "MS Team Report" -Body "MS Team Report" -Attachments $output1 
Write-Log -Message "Report Sent to $erroremail" -path $log 
########################Recycle reports & logs############## 
$path1 = (Get-Location).path + "\report" 
$path2 = (Get-Location).path + "\Logs" 
$limit = (Get-Date).AddDays(-60) #for report recycling 
Get-ChildItem -Path $path1 | 
Where-Object -FilterScript {$_.CreationTime -lt $limit} | 
Remove-Item -Recurse -Force 
 
Get-ChildItem -Path $path2 | 
Where-Object -FilterScript {$_.CreationTime -lt $limit} | 
Remove-Item -Recurse -Force 
Write-Log -Message "Script....Finished" -path $log 
##############################################################################

Thanks for reading and downloading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

This is small blog post but interesting one.

Our SharePoint Support team got the request to Change the Title of the particular Site.(Modern Team Site)

When going to Site Settings they were not getting the option to Change the Title which they get with other Sites.

On other SharePoint online sites they see as below:(Classic Team Sites, Publishing Sites etc)

Reason is obvious, Modern Team sites that user creates are integrated to Office 365 group (we can call them as office 365 group site as well). In order to change the Name of office 365 group sites, you need to rename the office 365 group.

These sites are office 365 groups driven, uses Groups#0 template, all these kind of changes should be made on the group object rather that SharePoint Site itself.

Other such example is updating the owner of such site, that should also be done on Office 365 group object.

Go to Portal.office.com –> Admin –>Groups –> Search for office 365 group 

Click on it & Edit Name

To Update the owner of the Office 365 group site, follow the same process, instead of Name, hit edit on Owners.

Now wait for few hours, Modern team Site title will get renamed and Owners will also get updated. (It can take upto 1 hr or more for changes to take effect)

Note: Url wil not change when renaming the Site Name, which is same behavior as any other sites on SharePoint.

Thanks for reading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

This is an interesting topic and I wanted to write something about it from a long time but it has skipped some how.

Yesterday I have seen some Admin asking about it on the forums as their users are not able to manage Distribution lists in exchange online via outlook.

They are in hybrid environment & are synchronizing the groups from On-premise Active directory thru AD connect.

We have also faced the Similar issue and below is the solution that we have implemented in our environment and its pretty effective.

  • Push the below shortcut to users machine.(with the tool that you use in your environment, SCCM or other)

C:\windows\system32\rundll32.exe dsquery,OpenQueryWindow

  • Name it as something relevant “DL management

  • Owner should have Write Members permissions on the group (By default primary owner has it)

By default if Manager can update membership list is set than owner mentioned here automatic has write member permissions.

  • For other owners you can make a process where they can request that access thru your IT L1 team.

Ones above steps are completed, here are the steps that Distribution group owners needs to perform for adding & removing members for the group they own.

Users Steps:

  1. Users will hit DL management icon that has been published by you.
  2. Search for group (click find now)

  1. Double click on group (ADD and remove members)

I hope this blog post will assist many office 365 admins as they might be managing hybrid environments and facing the frustration from users about Distribution group management.

Thanks for reading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

This is a long pending post from my side about approval work flows that I wanted to post but didn’t got a chance as some how other priority topics knocked my mind.

My last post about approval flow was Microsoft Flow Approval – Email Send with options but what important thing missing was, it lacks comments when item is approved or rejected.

My assumption in this post is that you are already aware about SharePoint List and how to add a Microsoft flow When item is created or modified.

Select the action after you have already triggered your flow, Search for the term Approval.

Select the Start an Approval Action.

You have two options here, either everyone must approve before it is counted as approved or First one to respond as approved.

Next action is to use Switch Case and capture the response of Approve and Reject action.

Here is how you will receive the approval email. (only thing with this approval activity which is different from Email with options flow is that it can not be sent from your organizational email address)

As an approver , when I will hit approve or reject, I will get option to submit with comments.

We can also login to Microsoft flow portal and do approvals or rejections from there.

Another big benefit is you can even use your mobile device and have Flow App to perform these operations, it even sends you push notifications.

You can build your flow further and add other actions after Approval/Reject Switch Case that you have seen above,

For example adding a send mail action after approval and adding the comments from the approver on it.

You can use this technique to add Approval flow with comments in your Flow with one caveat that email will always arrive from Maccount@microsoft.com but there are other benefits like you can approve the request from the Flow Portal and also from Flow mobile App.

Thanks for reading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

We have created VDI automation using Microsoft flow, PowerApps, Sharepoint and Powershell scripts.

Yes, you heard it right, VDI automation by combining office 365 tool set.

This post is not about the above automation but some part of it.

Here is the High level of what has been done.

  • PowerAPPS has been used for creating a form that user fills to request VDI.
  • Sharepoint list to store the requested input.
  • Microsoft flow for running approval work flow.
  • PowerShell scripts for all the backend work for sending welcome email & VDI creation.

Recently there was one request missed by the Approval team so they wanted if we can send a daily email of any requests that are still pending and their attention is required.

This post is about how to monitor the SharePoint list with particular status and if found send a alert.

First Step is use the Recurrence as the trigger…

Now initialize the array as you need to count number of items and if number is greater than zero, you can generate the alert.

After this use get items activity to get sharepoint List items and filter it by status (you might have different column or status in your automation)

See below filter Query that is relevant to our List but may not be relevant in your case (so change it accordingly)

ADD two parallel branches to it, one will collect the number of items (ID) and other will terminate the flow if above step is failed.

Configure the terminate activity as below.(if get items activity is failed)

Now add a condition if length of array is greater than 0 than send the Alert Email else terminate the flow as success.

In the email alert you can use the variables like compose so that you can send the SharePoint list items IDs that needs attention.

Here is the full flow snapshot (how it looks like after completion)

I hope this will assist you in some way or the other if you are doing some flow based automation.

Note: I have used terminate with success to gracefully exit the flow where possible as this technique reduces unnecessary flow failure alerts.

Thanks for reading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

When Microsoft published that they will be retiring the office 365 Discovery Service API, We have logged a ticket with their support team and were able to get the Application ids that are not compliant with it.

We will be retiring the Office Discovery Service API from Office 365 as of November 1, 2019. You are receiving this message because our reports indicate that your organization uses one or more Office 365 applications that utilize the Office Discovery Service API.

Now next thing was to find the application names which was not much of a challenge and we were able to find it by searching the Application ID under portal.azure.com –> Azure Active Directory –> Enterprise Applications.

Now we know the applications but we want to export the user list that is involved which we were not able to accomplish thru the GUI.

Here are the steps that needs to be followed for exporting the user list of the Application.

  1. Connect to AzureAd via PowerShell.

2. From the GUI you have already got the object Id of the Application.

$a=Get-AzureADServicePrincipal -ObjectId 6053420-6f93-5342-b825-e6786981298e

3. You can now export all the Principals that are involved in this Application by using Get-AzureADServiceAppRoleAssignment

Get-AzureADServiceAppRoleAssignment -ObjectId $a.ObjectId |select PrincipalDisplayName | Export-Csv C:\Data\adobe.csv -NoTypeInformation

By following these 3 steps I was able to extract the User list and was able to supply it to the stake holders as per their requirement.

If you are in same situation as I was than follow the above steps and provide back the report.

Thanks for reading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

This script that I am sharing today has been requested by our PowerAPPS and flow team to generate a daily report for all PowerApps and Microsoft flows running in the environment.

Modules required for running this script:

  • MSOL module
  • PowerApps module

You can can install MSOL module using below powerShell command

 Install-Module MSOnline

and PowerAPPS module using below commands.

Install-Module -Name Microsoft.PowerApps.Administration.PowerShell
 Install-Module -Name Microsoft.PowerApps.PowerShell -AllowClobber

Download and Extract the Script solution from below link.

https://gallery.technet.microsoft.com/scriptcenter/PowerApps-and-Flow-Report-27a36e03

Open the PowerAPPSandFlowList.ps1 and update the following parameters inside it.(under variables section)

$smtpserver = “smtpserver”
$from = “DoNotReply@labtest.com”
$erroremail = “Reports@labtest.com” #(to which erros /logs and reports will be sent)

#####################userid/password#####################

userId = ‘sukhijavikas@labtest.com’ # User id that has rights to powerapps enviornment (powerapps p2 license & Enviornment admin access is required) and can also run MSOL comamnds.

Now run encrypt.bat and enter the password of $Userid so that script can be used without entering password again and can be scheduled via task scheduler.


After above is completed, you can run PowerAppsandFlowList.bat or schedule it to generate the HTML report for all flows and PowerApps in the enviornment.

Reports will be sent on email as well as will be saved in report folder.

PowerShell
<#     
    .NOTES 
    =========================================================================== 
    Created with:     ISE 
    Created on:       01/10/2019 1:46 PM 
    Created by:       Vikas Sukhija 
    Organization:      
    Filename:         PowerAppsandFlowList.ps1 
    =========================================================================== 
    .DESCRIPTION 
    Extract and publish all the powerapps and flows in the enviornment 
#> 
function Write-Log 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [array]$Name, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$Ext, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$folder, 
     
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, 
     
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$Message, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$path, 
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')] 
    [ValidateSet('Information','Warning','Error')] 
    [string]$Severity = 'Information', 
     
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG 
  ) 
  switch ($PsCmdlet.ParameterSetName) { 
    "Create" 
    { 
      $log = @() 
      $date1 = Get-Date -Format d 
      $date1 = $date1.ToString().Replace("/", "-") 
      $time = Get-Date -Format t 
     
      $time = $time.ToString().Replace(":", "-") 
      $time = $time.ToString().Replace(" ", "") 
     
      foreach ($n in $Name) 
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} 
      return $log 
    } 
    "Message" 
    { 
      $date = Get-Date 
      $concatmessage = "|$date" + "|   |" + $Message +"|  |" + "$Severity|" 
      switch($Severity){ 
        "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} 
        "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} 
        "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} 
      } 
       
      Add-Content -Path $path -Value $concatmessage 
    } 
  } 
} 
function ProgressBar 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true)] 
    $Title, 
    [Parameter(Mandatory = $true)] 
    [int]$Timer 
  ) 
     
  For ($i = 1; $i -le $Timer; $i++) 
  { 
    Start-Sleep -Seconds 1; 
    Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /10 * 100) 
  } 
} 
function LaunchMSOL  
{ 
  param 
  ( 
    $UserCredential 
  ) 
  Import-Module msonline 
  Write-Host "Enter MS Online Credentials" -ForegroundColor Green 
  Connect-MsolService -Credential $UserCredential 
} 
     
Function RemoveMSOL {Write-Host "Close Powershell Window - No disconnect available" -ForegroundColor yellow} 
#################Check if logs folder is created################## 
$logpath  = (Get-Location).path + "\logs"  
$testlogpath = Test-Path -Path $logpath 
if($testlogpath -eq $false) 
{ 
  ProgressBar -Title "Creating logs folder" -Timer 10 
  New-Item -Path (Get-Location).path -Name Logs -Type directory 
} 
 
$reportpath = (Get-Location).path + "\Report" 
$testReportpath = Test-Path -Path $reportpath 
if($testReportpath -eq $false) 
{ 
  ProgressBar -Title "Creating Report folder" -Timer 10 
  New-Item -Path (Get-Location).path -Name Report -Type directory 
} 
 
##########################Load variables & Logs#################### 
$log = Write-Log -Name "process_PowerappsFlowListReport" -folder logs -Ext log 
$output1 = Write-Log -Name "PowerAppsList" -folder Report -Ext html 
$output2 = Write-Log -Name "FlowList" -folder Report -Ext html 
$collection1 = @() 
$collection = @() 
 
$smtpserver = "smtpserver" 
$from = "DoNotReply@labtest.com" 
$erroremail = "sukhijavikas@labtest.com" 
 
#####################userid/password########################## 
$userId = 'sukhija@labtest.com' 
$encrypted1 = Get-Content .\password1.txt 
$pwd = ConvertTo-SecureString -string $encrypted1 
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd 
 
##########Start Script main############## 
Start-Transcript -Path $log 
 
############Format HTML########### 
$HTMLFormat = "" 
################################ 
 
try 
{ 
  Add-PowerAppsAccount -Username $userId -Password $pwd 
  LaunchMSOL -UserCredential $Credential 
} 
catch 
{ 
  Write-Host "$($_.Exception.Message)" -foregroundcolor red 
  Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error - Loading PowerAPPS and Flow Module" -Body $($_.Exception.Message) 
  break 
} 
 
 
$collection1 = Get-AdminPowerApp | select DisplayName, AppName, Owner, EnvironmentName, CreatedTime, LastModifiedTime 
 
$collection1 | ForEach-Object{ 
  $coll = "" | select DisplayName, AppName, Owner, EnvironmentName, CreatedTime, LastModifiedTime 
  $coll.DisplayName = $_.DisplayName 
  $coll.AppName = $_.AppName 
  $coll.Owner = $_.Owner.UserPrincipalName 
  $coll.EnvironmentName = $_.EnvironmentName 
  $coll.CreatedTime = $_.CreatedTime 
  $coll.LastModifiedTime = $_.LastModifiedTime 
  $collection += $coll 
} 
 
$count = $collection.count 
$collection | 
ConvertTo-Html -Head $HTMLFormat -Body "<H2><Font Size = 4,Color = DarkCyan>All PowerApps = $count</Font></H2>" -AS Table | 
Set-Content $output1 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "PowerApps - Report"  -Attachments $output1 
#########################fetch all flows############################### 
$collection1 = @() 
$collection = @() 
 
$collection1 = Get-AdminFlow | select DisplayName, FlowName, CreatedBy, EnvironmentName, Enabled,CreatedTime, LastModifiedTime 
 
$collection1 | ForEach-Object{ 
  $coll = "" | select DisplayName, FlowName, CreatedBy, EnvironmentName, Enabled,CreatedTime, LastModifiedTime 
  $coll.DisplayName = $_.DisplayName 
  $coll.FlowName = $_.FlowName 
  $objectid = $_.CreatedBy.objectid 
  $msoluser = Get-MsolUser -ObjectId $objectid  -ErrorAction SilentlyContinue 
  Write-Host "Processing ..................."$msoluser.UserPrincipalName"" 
  $coll.CreatedBy = $msoluser.UserPrincipalName 
  $coll.Enabled = $_.Enabled 
  $coll.EnvironmentName = $_.EnvironmentName 
  $coll.CreatedTime = $_.CreatedTime 
  $coll.LastModifiedTime = $_.LastModifiedTime 
  $collection += $coll 
} 
 
$count = $collection.count 
$collection | 
ConvertTo-Html -Head $HTMLFormat -Body "<H2><Font Size = 4,Color = DarkCyan>All Flows = $count</Font></H2>" -AS Table | 
Set-Content $output2 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Flow - Report"  -Attachments $output2 
RemoveMSOL 
 
########################Recycle reports & logs############## 
$path1 = (Get-Location).path + "\report" 
$path2 = (Get-Location).path + "\logs"  
 
$limit = (Get-Date).AddDays(-60) #for report recycling 
Get-ChildItem -Path $path1 | 
Where-Object {$_.CreationTime -lt $limit} | 
Remove-Item -recurse -Force 
 
Get-ChildItem -Path $path2 | 
Where-Object {$_.CreationTime -lt $limit} | 
Remove-Item -recurse -Force 
 
Get-Date 
Write-Host "Script finished" -ForegroundColor green 
Stop-Transcript 
Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Transcript Log - PowerAppsFlowReport" -Body "Transcript Log - SPowerAppsFlowReport" -Attachments $log 
##############################################################################

Thanks for reading and downloading

Sukhija Vikas

http://SysCloudPro.com

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Separate tags by commas
To access this feature, please upgrade your account.
Start your free month
Free Preview