Wednesday, 12 July 2017

Add or Remove member from a Group using Microsoft Graph .NET Client Library

Managing Group membership of Azure AD Group and Office 365 Group is one of a routine task for every Office 365 Admin. We can easily add or remove user from group using Microsoft Graph api. In this post, I am going to share C# .NET Client Library code to add and remove membership of an user.

Add member to a Group using Microsoft Graph .NET SDK:

private static void AddGroupMember(string groupId, User user) 
{ 
  var client = new GraphServiceClient(new DelegateAuthenticationProvider( 
      (requestMessage) => 
      { 
          requestMessage.Headers.Add("Authorization", "Bearer " + "<Access Token>"); 
          return Task.FromResult(0); 
  
      })); 

  client.Groups[groupId].Members.References.Request().AddAsync(user); 
}
For more info : Add member - Documentation - Microsoft Graph

Remove member from a Group using Microsoft Graph C# Client Library:

private static void RemoveGroupMember(string groupId, string memberId) 
{ 
  var client = new GraphServiceClient(new DelegateAuthenticationProvider( 
      (requestMessage) => 
      { 
          requestMessage.Headers.Add("Authorization", "Bearer " + "<Access Token>"); 
          return Task.FromResult(0); 
  
      })); 

 client.Groups[groupId].Members[memberId].Reference.Request().DeleteAsync(); 
}
For more info: Remove member - Documentation - Microsoft Graph
Read More...

Thursday, 22 June 2017

List All Checked Out Files Using PowerShell

As a SharePoint administrator, if you are in need to find and get the list of all checked out files from a SharePoint document library, we can easily retrieve it by using client object model (CSOM) in Powershell.

The following Powershell script find and lists all the documents in a SharePoint Online document library which are checkout by current user and all other users.
#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
  
$siteUrl="https://spotenant.sharepoint.com/sites/testsite"
$UserName = "admin@spotenant.onmicrosoft.com"
$SecPwd = $(ConvertTo-SecureString 'adminPassword' -asplaintext -force) 
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecPwd) 
$ctx.credentials = $credentials
$ctx.Load($ctx.Web)
$ctx.ExecuteQuery()
$list=$ctx.Web.Lists.GetByTitle("Documents")
$ctx.Load($list)
$ctx.ExecuteQuery()
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml ="<View Scope='RecursiveAll' />";
$allItems=$list.GetItems($camlQuery)
$ctx.Load($allItems)
$ctx.ExecuteQuery()
 
foreach($item in $allItems)
{

$file = $ctx.Web.GetFileByServerRelativeUrl($item["FileRef"]);
$ctx.Load($file)
$ctx.Load($file.ListItemAllFields)
$CheckedOutByUser=$file.CheckedOutByUser     
$ModifiedBy=$file.ModifiedBy
$ctx.Load($CheckedOutByUser)
$ctx.Load($ModifiedBy)
try
{
$ctx.ExecuteQuery()
if($CheckedOutByUser.LoginName -ne $null){
Write-Host "##############"
Write-Host "File:" $file.Name
Write-Host "Url:" $item["FileRef"]
Write-Host "CheckedOutBy:" $CheckedOutByUser.LoginName
Write-Host "Last Modified By:" $ModifiedBy.LoginName
Write-Host "##############"
Write-Host ""
}}
catch{}
}
In the above powershell script first we are retrieving all the files from library and check every file if it is checked out by user or not, this process may time consuming in large document library, so alternatively we can use filter in caml query itself and retrieve checked out files alone.
#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
  
$siteUrl="https://spotenant.sharepoint.com/sites/testsite"
$UserName = "admin@spotenant.onmicrosoft.com"
$SecPwd = $(ConvertTo-SecureString 'adminPassword' -asplaintext -force)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecPwd) 
$ctx.credentials = $credentials
$ctx.Load($ctx.Web)
$ctx.ExecuteQuery()
$list=$ctx.Web.Lists.GetByTitle("Documents")
$ctx.Load($list)
$ctx.ExecuteQuery()
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml ="<View Scope='RecursiveAll'><Query><Where><IsNotNull><FieldRef Name='CheckoutUser' /></IsNotNull></Where></Query></View>";
$allItems=$list.GetItems($camlQuery)
$ctx.Load($allItems)
$ctx.ExecuteQuery()
 
foreach($item in $allItems)
{
$file = $ctx.Web.GetFileByServerRelativeUrl($item["FileRef"]);
$ctx.Load($file)
$CheckedOutByUser=$file.CheckedOutByUser     
$ModifiedBy=$file.ModifiedBy
$ctx.Load($CheckedOutByUser)
$ctx.Load($ModifiedBy)
$ctx.ExecuteQuery()

Write-Host "##############"
Write-Host "File:" $file.Name
Write-Host "Url:" $item["FileRef"]
Write-Host "CheckedOutBy:" $CheckedOutByUser.LoginName
Write-Host "Last Modified By:" $ModifiedBy.LoginName
Write-Host "##############"
Write-Host ""
}
Read More...

Wednesday, 21 June 2017

Get All List Items in Library using PowerShell with CSOM

In this article, I am going write a simple Powershell script using client object model (CSOM) to find and retrieve all files from a document library in SharePoint Online. To use csom in Powershell, we need to load the required Microsoft SharePoint Online SDK assembly files.

The below Powershell script simply load and list all the files from given document library in a SharePoint Online site. You need to replace sharepoint site url, list name and required admin credentials with your own details.
#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
 
$siteUrl="https://spotenant.sharepoint.com/sites/testsite"
$UserName = "admin@spotenant.onmicrosoft.com"
$SecPwd = $(ConvertTo-SecureString 'adminPassword' -asplaintext -force) 
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecPwd) 
$ctx.credentials = $credentials
$ctx.Load($ctx.Web)
$ctx.ExecuteQuery()
$list=$ctx.Web.Lists.GetByTitle("Documents")
$ctx.Load($list)
$ctx.ExecuteQuery()
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml ="<View Scope='RecursiveAll' />";
$allItems=$list.GetItems($camlQuery)
$ctx.Load($allItems)
$ctx.ExecuteQuery()

foreach($item in $allItems)
{
Write-Host "##############"
Write-Host $item["FileRef"]
$file = $ctx.Web.GetFileByServerRelativeUrl($item["FileRef"]);
$ctx.Load($file)
$ctx.Load($file.ListItemAllFields)
$Author=$file.Author
$CheckedOutByUser=$file.CheckedOutByUser     
$ModifiedBy=$file.ModifiedBy
$ctx.Load($Author)
$ctx.Load($CheckedOutByUser)
$ctx.Load($ModifiedBy)
try
{
$ctx.ExecuteQuery()
Write-Host "File:" $file.Name 
Write-Host "Author:" $Author.LoginName
Write-Host "ModifiedBy:" $ModifiedBy.LoginName
if($CheckedOutByUser.LoginName -ne $null){
Write-Host "CheckedOutBy:" $CheckedOutByUser.LoginName
}}
catch{}
Write-Host "##############"
Write-Host ""
}
Along with file name and file relative url, the above script also retrieves useful information such as Author name of the file, modified username and if the file was checked out, it also returns the name of the user who currently checked-out the file and yet to checked-in.
Read More...

Thursday, 15 June 2017

Hide Office 365 Group from GAL using Powershell

Hiding Office 365 Group from Global Address List (GAL) is one of the tedious job as there is no Admin UI to hide group mail from GAL. When you create an office 365 group it will not be hidden from GAL by default either it is public or private group. Currently Office 365 team accepted the user voice request to hide private groups from GAL by default. But for now, Powershell is the only option for Administrators to hide and show the groups from the GAL.

We can use the Exchange Online Powershell cmdlet Set-UnifiedGroup to hide group mail address from GAL. Before proceed, Connect Exchange Online Powershell module and use the following command.
Set-UnifiedGroup <group> -HiddenFromAddressListsEnabled $true
Actually we are setting the attribute HiddenFromAddressListsEnabled as true to hide group mail id from global address list. You can use the following command if you want set this property for all of your Office 365 Groups.
Get-UnifiedGroup | Set-UnifiedGroup -HiddenFromAddressListsEnabled $true
Normally you might want to hide only private groups. You can use below command to hide all the private groups from GAL:
Get-UnifiedGroup | Where-Object {$_.AccessType -eq 'Private'} | Set-UnifiedGroup -HiddenFromAddressListsEnabled $true
We can also list the groups that are disabled from address book using below powershell command:
Get-UnifiedGroup | Where-Object {$_.HiddenFromAddressListsEnabled -eq $true} | Select Alias,HiddenFromAddressListsEnabled
Hiding a Group from the GAL will only removes the availability of group in address list from external users, but it does not prevent other users to send email to the Group if they already know the address. If you want to restrict other users (other than group members) from sending message to the group, you need to set one more property - AcceptMessagesOnlyFromSendersOrMembers.
Set-UnifiedGroup <group> -AcceptMessagesOnlyFromSendersOrMembers <group>
If you want a group to accept messages from more than one group (multiple groups), you can give the group names as comma separated values in the above command.
Set-UnifiedGroup <group> -AcceptMessagesOnlyFromSendersOrMembers <group>,<group2>
Read More...

Wednesday, 24 May 2017

How to allow external sender for Office 365 Groups using Powershell

Office 365 Group is a back end service for Microsoft Teams, Planner, and etc. By default Office 365 Groups are not configured to receive external messages either it is public or private group. But most of organizations using Teams, Planner and even standalone Office 365 Groups for external collaboration and conversation, so receiving mails from external domain users is inevitable.

We can use the Exchange Online Powershell cmdlet Set-UnifiedGroup to set the people outside the organization to send mail to a specific group. Before proceed, Connect Exchange Online Powershell module and use the following command to allow external sender.
Set-UnifiedGroup <group> -RequireSenderAuthenticationEnabled $false
Actually we need to set the attribute RequireSenderAuthenticationEnabled as false to remove the authentication check of external senders. You can use the below command if you want set this property for all the Office 365 Groups.
Get-UnifiedGroup | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false
You can use below command if you want allow guest users only for all public groups:
Get-UnifiedGroup | Where-Object {$_.AccessType -eq 'Public'} | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false
We can list all the groups with external sender access property using below powershell:
Get-UnifiedGroup | Select Alias,AccessType,RequireSenderAuthenticationEnabled
The below command lists only office 365 groups with guest sender access enabled.
Get-UnifiedGroup | Where-Object {$_.RequireSenderAuthenticationEnabled -eq $false} | Select Alias,RequireSenderAuthenticationEnabled
You can also enable via UI using Office 365 Admin center: Office 365 Portal -> Peoples -> Edit Group and set the option "Let people outside the organization email the group"

allow guest sender access for Office 365 Groups
Read More...

Thursday, 23 March 2017

Enable or Disable In-Place Archive in Exchange Online using Powershell

In Exchange Online, users can have additional mailbox storage space by enabling In-Place Archive. Archive mailboxes also provide an alternate storage location in which to store historical messaging data. You can easily enable or disable In-Place Archive through Exchange Admin Center (EAC), but you should go with Powershell if you want to quickly enable the archive mailbox for all mailboxes in your organization.

Enable In-Place Archive for a mailbox

You can use Enable-Mailbox cmdlet to enable archiving for existing mailbox. You may already used Enable-Mailbox cmdlet to create mailbox for existing users who don't already have mailbox, you can use the same cmdlet to enable In-Place Archive by passing an extra parameter -Archive.

Before proceed, Connect Exchange Online Powershell module and use the following command to enable mailbox archiving.
Enable-Mailbox -Identity <mailbox user id> -Archive
The following command creates an In-Place archive for the existing user AlexD who already has a mailbox.
Enable-Mailbox -Identity AlexD -Archive

Disable In-Place Archive in a mailbox

As like enable archiving, you can use Disable-Mailbox cmdlet to disable archive feature in a mailbox. Use the below command to disable mailbox archive:
Disable-Mailbox -Identity <mailbox user id> -Archive
The below command removes archiving feature from the user AlexD's mailbox.
Disable-Mailbox -Identity AlexD -Archive
Read More...

Wednesday, 15 February 2017

Read Multiple Users Profile Properties From SharePoint Online Using CSOM

This post is follow-up of the article http://www.morgantechspace.com/2016/09/read-sharepoint-user-profile-properties-csom.html, in previous post I have clearly explained about how to read current user profile properties, specific user (other user) properties and how to read only required profile properties using client object model (CSOM). One of our user asked the question "How to get a specific profile property (path to profile picture for example) for all of my Sharepoint's website users in one request", so I am writing this post to help every users.

Summary

Get All Profile Properties for Multiple SharePoint Online Users

In the below C# code, I have passed only list of SharePoint Online users, you can fetch all SharePoint Online users using your own best method and use it in below code. You can read users using Azure AD powershell cmdlet Get-MsolUser or you can fetch from your own csv file.
public static void GetMultipleUsersProfileProperties()
{
    string siteUrl = "https://spotenant-admin.sharepoint.com";

    var passWord = new SecureString();
    foreach (char c in "pass@word1".ToCharArray()) passWord.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@spotenant.onmicrosoft.com", passWord);
           
    // Connect to the sharepoint site client context.
    ClientContext clientContext = new ClientContext(siteUrl);
    clientContext.Credentials = credentials;

    // Get the PeopleManager object.
    PeopleManager peopleManager = new PeopleManager(clientContext);

    // Get multiple users
    List<string> Users = new List<string> { "admin@spotenant.onmicrosoft.com",
"alexw@spotenant.onmicrosoft.com", "benw@spotenant.onmicrosoft.com" };

    var results = new Dictionary<string, PersonProperties>();
    foreach (var user in Users)
    {
        string loginName = "i:0#.f|membership|" + user;  //claim format login name
        var personProperties = peopleManager.GetPropertiesFor(loginName);
        clientContext.Load(personProperties, p => p.AccountName, p => p.DisplayName,
                           p => p.UserProfileProperties);
        results.Add(loginName, personProperties);
    }
    clientContext.ExecuteQuery();

    foreach (var kvp in results)
    {
        if (kvp.Value.ServerObjectIsNull.HasValue && !kvp.Value.ServerObjectIsNull.Value)
        {
            Console.WriteLine(kvp.Value.DisplayName);
            Console.WriteLine("---------------------------------");
            foreach (var property in kvp.Value.UserProfileProperties)
            {
                Console.WriteLine(string.Format("{0}: {1}",
                    property.Key.ToString(), property.Value.ToString()));
            }                    
        }
        else
        {
            Console.WriteLine("User not found:"+kvp.Key);
        }
        Console.WriteLine("------------------------------");
        Console.WriteLine("          ");
    }
}

Get Specific Profile Properties for Multiple SharePoint Online Users

The below csom based C# code read only specific set of properties for set of SharePoint Online users.
public static void GetSpecificProfilePropertiesForAllUsers()
{
    string siteUrl = "https://spotenant-admin.sharepoint.com";

    var passWord = new SecureString();
    foreach (char c in "pass@word1".ToCharArray()) passWord.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@spotenant.onmicrosoft.com", passWord);

    // Connect to the sharepoint site client context.
    ClientContext clientContext = new ClientContext(siteUrl);
    clientContext.Credentials = credentials;

    // Get the PeopleManager object.
    PeopleManager peopleManager = new PeopleManager(clientContext);

    // Get multiple users - you can provide all users by fetching with different service
    // Ex: from Get-MsolUser powershell cmdlet
    List<string> Users = new List<string> { "admin@spotenant.onmicrosoft.com",
"alex2w@spotenant.onmicrosoft.com", "benw@spotenant.onmicrosoft.com" };

    var results = new Dictionary<string, IEnumerable<string>>();
    foreach (var user in Users)
    {
        string loginName = "i:0#.f|membership|" + user;  //claim format login name
        // Retrieve specific properties by using the GetUserProfilePropertiesFor method.  
        string[] profilePropertyNames = new string[] { "PersonalSpace", "PictureURL", "SPS-JobTitle" };
        UserProfilePropertiesForUser profilePropertiesForUser = new UserProfilePropertiesForUser(
            clientContext, loginName, profilePropertyNames);

        IEnumerable<string> profilePropertyValues = peopleManager.GetUserProfilePropertiesFor(profilePropertiesForUser);

        // Load the request for the set of properties. 
        clientContext.Load(profilePropertiesForUser);
        results.Add(loginName, profilePropertyValues);
    }
    clientContext.ExecuteQuery();

    foreach (var kvp in results)
    {
        if (kvp.Value != null && kvp.Value.Count() > 0)
        {
            Console.WriteLine("User :" + kvp.Key);
            // Returned collection contains only property values 
            foreach (var value in kvp.Value)
            {
                Console.WriteLine(value);
            }
        }
        else
        {
            Console.WriteLine("User not found:" + kvp.Key);
        }
    }
}
Read More...

Tuesday, 14 February 2017

Disable AD User based on specific attribute using Powershell

In this article, I am going write powershell script to disable Active Directory user account by using user's specific property like employeeNumber, employeeID, etc...You can disable an ad user account by using the Active Directory powershell cmdlet Disable-ADAccount.
Disable-ADAccount -Identity <adaccount>
The Identity parameter specifies the Active Directory user that you want to disable. You can identify an account by its distinguished name (DN), GUID, security identifier (SID), or samAccountName.

Using the above command, you can not find user by using other AD attributes. So, we need to use another cmdlet Get-ADUser to find user using specific attribute and then we can pipe the result to Disable-ADAccount command to disable.

The following command search an AD user by user's EmployeeID using SQL like filter and disable the user.
Import-Module ActiveDirectory
Get-ADUser -Filter 'employeeID -like "1200547"' | Disable-ADAccount
You can also find an user by using well-known LDAP Filter. The following command find user by LDAP filter using user's EmployeeID and disable the user.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(employeeID=1200547)'  | Disable-ADAccount

Disable Bulk AD Users from CSV by User's EmployeeID

The following powershell script import AD users from csv file and disable by using user's EmployeeID property. Consider the CSV file Users.csv which contains set of AD users to disable with the attribute EmployeeID as one of the csv column header.
Import-Module ActiveDirectory
Import-Csv "C:\Users.csv" | ForEach-Object {
$employeeID = $_."EmployeeID"
Get-ADUser -LDAPFilter "(employeeID=$employeeID)"  | Disable-ADAccount
Write-Host "User $employeeID disabled"
}
Read More...