Wednesday, 28 December 2016

Create all day event using Microsoft Graph Api

I have just developed a small application to import holiday list from csv file into every Office 365 users Outlook calendar. I have already created an Azure AD Application and set the required permission "Read and write calendars in all mailboxes". I am using following graph api endpoint to post my new calendar event.
https://graph.microsoft.com/v1.0/me/events
Json Body to add new Christmas Holiday event (2016-12-25):
{  
  "originalStartTimeZone": "UTC",
  "originalEndTimeZone": "UTC",
   "Subject":"Christmas Holiday",
   "Start":{  
      "DateTime":"2016-12-25T00:00:00",
      "TimeZone":"UTC"
   },
   "End":{  
      "DateTime":"2016-12-26T00:00:00",
      "TimeZone":"UTC"
   },
"iCalUId": "iCalUId-value",
"IsAllDay":true,
} 
To a create holiday event, we need to make sure that the event should occur in whole day (12 AM to 12 PM), to achieve this we need to set the parameter isAllDay=true and we have to set the start and end properties of the event to midnight of the day when event occurs (2016-12-25T00:00:00) and midnight of the next day of the event (2016-12-26T00:00:00).

If you set the event without giving the parameter "IsAllDay":true, the event may spread over two days due to time zone problem. So, don't forgot to set the property IsAllDay as true to create all day event like holiday.

Html Javascript Code : Create Holiday Calendar Event

var jsonBody = '{  
  "originalStartTimeZone": "UTC",
  "originalEndTimeZone": "UTC",
   "Subject":"Christmas Holiday",
   "Start":{  
      "DateTime":"2016-12-25T00:00:00",
      "TimeZone":"UTC"
   },
   "End":{  
      "DateTime":"2016-12-26T00:00:00",
      "TimeZone":"UTC"
   },
"iCalUId": "iCalUId-value",
"IsAllDay":true,
}'


var httpRequest = new XMLHttphttpRequestuest();
httpRequest.open("POST", "https://graph.microsoft.com/v1.0/me/events");
httpRequest.sethttpRequestuestHeader("authorization", "Bearer " + accessToken);
httpRequest.sethttpRequestuestHeader("content-type", "application/json");
httpRequest.onload = function (e) {
    if (httpRequest.readyState === 4) {
        if (httpRequest.status === 201) {
            console.log(httpRequest.response);
        }
    }
};
httpRequest.onerror = function (e) {
    // Handle error
};
httpRequest.send(jsonBody);

Monday, 26 December 2016

List all the OneDrive for Business users in Office 365 - Powershell

We can get the list of users with OneDrive for Business feature provisioned by using SharePoint Online UserProfileService with Powershell. As you know SharePoint is base for OneDrive as like some other services (Office 365 Groups, Planner, Teams, and etc..), so it's users basic profile information obviously will be stored in SharePoint. You can get all the SharePoint Online users using SharePoint UserProfileService and look for the Personal Space object, users who have OneDrive for Business site alone have value for this property and other users do not have this property.

Steps to Export OneDrive for Business Provisioned Users:

  • Fetch all SharePoint Online users using UserProfileService.
  • Find if OneDrive is provisioned or not.
  • Export my site collections to text file.
Note: Replace the variable <your tenant name> with your Office 365 tenant name in all the occurrences and provide your own admin credentials.
# Specify sharepoint online admin url 
$adminURL = "https://<your tenant name>-admin.sharepoint.com"

# Specify the location where the list of OneDrive sites should be saved
$LogFile = 'C:\OneDrivesites.txt'

#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")

#Provide your global admin credentials.
$UserName = "admin@<your tenant name>.onmicrosoft.com"
$SecPwd = $(ConvertTo-SecureString 'password' -asplaintext -force) 
$adminCreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecPwd) 

# Set User Profile Service path using SPO admin URL 
$proxyaddr = "$adminURL/_vti_bin/UserProfileService.asmx?wsdl"
# Create a new webservice proxy to access UserProfileService
$UserProfileService= New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False
$UserProfileService.Credentials = $adminCreds

# Set authentication cookies
$strAuthCookie = $adminCreds.GetAuthenticationCookie($adminURL)
$uri = New-Object System.Uri($adminURL)
$container = New-Object System.Net.CookieContainer
$container.SetCookies($uri, $strAuthCookie)
$UserProfileService.CookieContainer = $container

# Sets the first User profile, at index -1
$UserProfileResult = $UserProfileService.GetUserProfileByIndex(-1)

Write-Host "Starting- This could take a while."

$NumProfiles = $UserProfileService.GetUserProfileCount()
$i = 1

# As long as the next User profile is NOT the one we started with (at -1)...
While ($UserProfileResult.NextValue -ne -1) 
{
Write-Host "Checking profile $i of $NumProfiles" -foreground Yellow

# Look for the Personal Space object in the User Profile and retrieve it
# (PersonalSpace is the name of the path to a user's OneDrive for Business site. 
# Users who have not yet created a  OneDrive for Business site might not have this property)
$Prop = $UserProfileResult.UserProfile | Where-Object { $_.Name -eq "PersonalSpace" } 
$Url= $Prop.Values[0].Value

# If "PersonalSpace" (which we've copied to $Url) exists, log it to our file...
if ($Url) {
$siteUrl = "https://<your tenant name>-my.sharepoint.com"+ $Url
# Write OneDrive site url in console
Write-Host $Url -foreground Green
$siteUrl | Out-File $LogFile -Append -Force
}

# And now we check the next profile the same way...
$UserProfileResult = $UserProfileService.GetUserProfileByIndex($UserProfileResult.NextValue)
$i++
}
Source : https://technet.microsoft.com/en-us/library/dn911464.aspx

Thursday, 22 December 2016

Add or Remove Members and Owners in Office 365 Group using Powershell

We can use the Add-UnifiedGroupLinks cmdlet to add members and owners to an Office 365 Group and remove members and owners from unified group using the Remove-UnifiedGroupLinks cmdlet. Both the cmdlets includes the following key parameters:

Identity – Alias, Display name, or Email address of the group
Links – Alias, Display name, or Email address of the user being added
LinkType – Members, Owners, or Subscribers

Before proceed, run the following commands to connect Exchange Online Powershell session.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session

Add Members and Owners to Office 365 Group

This example add the member morgan@contoso.com to the Office 365 Group named TestO365Group. We need to set the parameter LinkType as Members to add users as member.
Add-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members  –Links morgan@contoso.com
The parameter Links accept multiple values, use the following syntax: value1,value2.... to add multiple members. If the values contain spaces or otherwise require quotation marks, use the following syntax: "value1","value2",....
Add multiple users as member:
Add-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members  –Links alexw@contoso.com,alland@contoso.com
Add an user as owner: To add an user as a owner to office 365 group, first we need to add the user as a member to the specified group and then we have to add the user as owner.
Add-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members –Links morgan@contoso.com
Add-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Owners –Links morgan@contoso.com

Remove Members or Owners from Office 365 Group

This example removes the member alexd@contoso.com and alland@contoso.com from the Office 365 Group named TestO365Group..
Remove-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members –Links alexw@contoso.com ,alland@contoso.com -Confirm:$false
Remove owner: To remove an owner from the group, first you have to remove user from the LinkType Owners and remove the user from the LinkType Members.
Remove-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Owners –Links morgan@contoso.com -Confirm:$false
Remove-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members –Links morgan@contoso.com -Confirm:$false

Add or Remove members from a CSV File:

You can use the below powershell commands to add members to an office 365 group by importing users from csv file. Consider the csv file members.csv that includes the column member which holds the member identity in each row of the csv file.
Import-CSV "C:\members.csv" | ForEach-Object {
Add-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members  –Links $_.member
}

List members or owners of a group

Once we added or removed members or owners, we can use the Get-UnifiedGroupLinks cmdlet to get members or owners of a specific group. The below command lists all members of the given group.
Get-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Members
List owners of a group.
Get-UnifiedGroupLinks –Identity "TestO365Group" –LinkType Owners

Thursday, 24 November 2016

Get all checked out files in SharePoint Library using CSOM

If you are in business need to find and get the list of all checked out documents from a sharepoint document library, we can easily achieve it by using client object model (csom) in C#.

The following C# code find and lists the files which are checkout by current user and all other users.
public static void GetAllCheckedOutFilesInLibrary() 
{ 
    string sitrUrl = "https://spotenant.sharepoint.com/sites/contoso"; 
    using (var ctx = new ClientContext(sitrUrl)) 
    { 
        //ctx.Credentials = 
        ctx.Load(ctx.Web, a => a.Lists); 
        ctx.ExecuteQuery(); 
 
        var listName = "Documents"; 
        List list = ctx.Web.Lists.GetByTitle(listName); 
        var items = list.GetItems( 
            new CamlQuery() {  
            ViewXml = @"<View Scope='RecursiveAll'><Query> 
            <Where><IsNotNull><FieldRef Name='File_x0020_Type' /></IsNotNull></Where> 
            </Query></View>"  
        }); 
        ctx.Load(items, a => a.IncludeWithDefaultProperties(item => item.File, item => item.File.CheckedOutByUser)); 
        ctx.ExecuteQuery(); 
        foreach (var item in items) 
        { 
            if (item.File.CheckOutType != CheckOutType.None) 
            { 
                Console.WriteLine("File: " + item["FileRef"].ToString().Split('/').LastOrDefault()); 
                Console.WriteLine("Checked-Out By: " + item.File.CheckedOutByUser.Title); 
                Console.WriteLine("Checked-Out User Email: " +item.File.CheckedOutByUser.Email); 
                Console.WriteLine("Last Modified: " + DateTime.Parse(item["Last_x0020_Modified"].ToString())); 
                Console.WriteLine("-----------------------"); 
                Console.WriteLine(""); 
            } 
        } 
    } 
}
In the above code first we are retrieving all the files and check every file if it is checked out or not, this method may takes some time to process large document library. So alternatively we can use filter in caml query itself and retrieve checked out files alone.
public static void GetAllCheckedOutFilesWithCamlQuery() 
{ 
    string sitrUrl = "https://spotenant.sharepoint.com/sites/contoso"; 
    using (var ctx = new ClientContext(sitrUrl)) 
    { 
        //ctx.Credentials = 
        ctx.Load(ctx.Web, a => a.Lists); 
        ctx.ExecuteQuery();  
 
        var listName = "Documents"; 
        List list = ctx.Web.Lists.GetByTitle(listName); 
        var files = list.GetItems(  
            new CamlQuery()  
            { 
            ViewXml = @"<View Scope='RecursiveAll'><Query> 
            <Where><IsNotNull><FieldRef Name='CheckoutUser' /></IsNotNull></Where> 
            </Query></View>" 
            }); 
        ctx.Load(files); 
        ctx.ExecuteQuery(); 
        foreach (var file in files) 
        { 
            Console.WriteLine("File: " + file["FileRef"].ToString().Split('/').LastOrDefault()); 
            Console.WriteLine("Checked-Out By: " + (file["CheckoutUser"] as FieldUserValue).Email); 
            Console.WriteLine("Last Modified: " + DateTime.Parse(file["Last_x0020_Modified"].ToString())); 
            Console.WriteLine("-----------------------"); 
            Console.WriteLine(""); 
        } 
    } 
} 
The above caml query retrieves documents which are checkout by all the users. If you want to get all the documents that are checked out by the current user then you can use the following caml query.
<Where>
<And>
<IsNotNull>
<FieldRef Name='CheckoutUser' />
</IsNotNull>
<Eq>
<FieldRef Name='CheckoutUser' />
<Value Type=’Integer’>
<UserID Type=’Integer’ />
</Value>
</Eq>
</And>
</Where>

Friday, 11 November 2016

Check if Office 365 user exists or not with Powershell

In this article I am going write powershell script to check if an Office 365 user exists or not with the Azure AD Powershell cmdlet Get-MsolUser. First run the below command to connect Office 365 Powershell module.
Import-Module MSOnline
$msolCred = Get-Credential
Connect-MsolService –Credential $msolCred
The below command checks if the given user account already exists in Office 365 or not. You can retrieve user by using ObjectId or UserPrincipalName of the user.
$upn = "alexd@MyTenant.onmicrosoft.com"
$User = Get-MsolUser -UserPrincipalName $upn -ErrorAction SilentlyContinue
If ($User -ne $Null) { 
"User exists in Azure AD" 
} Else {
"User not found in Azure AD"}
You need to use the parameter -ErrorAction SilentlyContinue to skip error when user not found, otherwise you will get the error message 'Get-MsolUser : User Not Found'.

Check if multiple Azure AD accounts are exists or not

First set list of user's userprincipalname as array object and enumerate the array to find user account in Office 365.
$users = @("alexd@MyTenant.onmicrosoft.com","sarad@MyTenant.onmicrosoft.com","kevin@MyTenant.onmicrosoft.com")
foreach ($user in $users) {
$userobj = Get-MsolUser -UserPrincipalName $user -ErrorAction SilentlyContinue
If ($userobj -ne $Null) {
    Write-Host "$user already exists" -foregroundcolor "green"
} else {
    Write-Host "$user not found " -foregroundcolor "red"
}}

Thursday, 10 November 2016

Check if AD user exists with PowerShell

In this article I am going write powershell commands to check if an Active Directory user exists or not with the AD Powershell cmdlet Get-ADUser. First run the below command to import the Active Directory module.
Import-Module ActiveDirectory
The below command checks if the given user account exists in AD or not. You can identify a user by its distinguished name (DN), GUID, SID,SamAccountName or Name.
$Name = "kevin"
$User = $(try {Get-ADUser $Name} catch {$null})
If ($User -ne $Null) { 
"User exists in AD" 
} Else {
"User not found in AD"}
You need to use try-catch block to skip error when user not found, otherwise you will receive the error message 'Get-ADUser : Cannot find an object with identity'.

Find if multiple AD users are exists or not

We can set list of user names as array object and enumerate the users to find user account in AD.
$users = @("kevin","smith","nick")
foreach ($user in $users) {
$userobj = $(try {Get-ADUser $user} catch {$Null})
If ($userobj -ne $Null) {
    Write-Host "$user already exists" -foregroundcolor "green"
} else {
    Write-Host "$user not found " -foregroundcolor "red"
}}

Tuesday, 1 November 2016

Check if AD Users from OU are Member of a Group using Powershell

We can use the Active Directory powershell cmdlet Get-ADGroupMember to check if an AD user is member of an AD group. In this article, I am going to write powershell script to find if users of specific OU are member of a Group.

Run the following command to import Active Directory cmdlets.
Import-Module ActiveDirectory

Find AD Users from OU are Member of a Group:

We can use the cmdlet Get-ADUser to get AD users from specific OU and enumerate the users to check their membership in the particular group. We can use the parameter -Recursive with Get-ADGroupMember cmdlet to get nested group members along with direct group members. The following powershell command select users from the Organization Unit 'TestOU' and check the users are member of 'Domain Admins' group.
$users = Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com"
$group = "Domain Admins"
$members = Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty Name
$users | ForEach-Object {
$user = $_.Name
If ($members -contains $user) {
      Write-Host "$user exists in the group"
} Else {
      Write-Host "$user not exists in the group"
}}

Check if Single User is Member of a Group:

The following powershell command find if particular single user is member of 'Domain Admins' group.
$user = "TestUser"
$group = "Domain Admins"
$members = Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty Name

If ($members -contains $user) {
      Write-Host "$user exists in the group"
 } Else {
        Write-Host "$user not exists in the group"
}

Thursday, 27 October 2016

Connect-MsolService through Proxy in Powershell

Problem:

I used to connect Azure AD Powershell module using Connect-MsolService command. I can always able to successfully connect via proxy server and without proxy. But for some reason, today, I am receiving the errors Exception of type Microsoft.Online.Administration.Automation.MicrosoftOnlineException' was thrown and There was no endpoint listening at https://provisioningapi.microsoftonline.com/provisioningwebservice.svc that could accept the message when I use Connect-MsolService command.

Error Message 1:
Connect-MsolService : There was no endpoint listening at 
https://provisioningapi.microsoftonline.com/provisioningwebservice.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. 
At line:1 char:1 
+ Connect-MsolService -Credential $Livecred; 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo          : OperationStopped: (:) [Connect-MsolService], EndpointNotFoundException 
    + FullyQualifiedErrorId : System.ServiceModel.EndpointNotFoundException,Microsoft.Online.Administration.Automation 
   .ConnectMsolService
Error Message 2:
Connect-MsolService : Exception of type 'Microsoft.Online.Administration.Automation.MicrosoftOnlineException' was thrown. 
At line:1 char:1 
+ Connect-MsolService -Credential $Livecred; 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo          : OperationStopped: (:) [Connect-MsolService], MicrosoftOnlineException 
    + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.MicrosoftOnlineException,Microsoft.Online.Adm 
   inistration.Automation.ConnectMsolService 

Fix/Solution:

The problem was solved for me after configuring Powershell to use proxy authentication for Microsoft Online endpoint (https://provisioningapi.microsoftonline.com/provisioningwebservice.svc) using Invoke-WebRequest command in Powershell.
Invoke-WebRequest -Proxy http://myporxyerver:myport -ProxyUseDefaultCredentials https://provisioningapi.microsoftonline.com/provisioningwebservice.svc
After running the above command, now the Powershell uses my proxy settings to connect Microsoft Office 365.

Note: replace myporxyerver with your proxy server and myport with your proxy server port.

Tuesday, 25 October 2016

Set Office 365 User Password Never Expire using Powershell

We may have a requirement to set a password for an individual user to never expire and in some cases requirement would be set a group of user's password to never expire. We can set passwordneverexpires flag to Office 365 user by using the Azure AD powershell cmdlet Set-MsolUser.

Before porceed run the following command to connect Azure AD powershell module:
Import-Module MSOnline
$msolCred = Get-Credential
Connect-MsolService –Credential $msolCred
Run the below command to set an individual user’s password to never expire.
Set-MsolUser -UserPrincipalName user@yourdomain.onmicrosoft.com -PasswordNeverExpires $true
If you want to verify the PasswordNeverExpires setting has been applied or not, you can check it by using Get-MsolUser cmdlet.
Get-MsolUser -UserPrincipalName user@yourdomain.onmicrosoft.com | Select PasswordNeverExpires

Set Password Never Expire for Group of Users

In some situations, we may required to set specific type of user's password to never expire (i.e. users who are in same department or same office). In this case, we need to first get users by applying filter in Get-MsolUser cmdlet and pipe the results to Set-MsolUser cmdlet.
Get-MsolUser -All | Where-Object { $_.Department -like '*Admin*'} | Set-MsolUser -PasswordNeverExpires $true
You can just remove the where-object check in above command if you want to set it for all users.

Set Bulk AD Users Password Never Expire from CSV

We can import users from csv file and set passwordneverexpires setting. Consider the CSV file office365users.csv which contains set of Office 365 users with the column header UserPrincipalName.
Import-Csv 'C:\office365users.csv' | ForEach-Object {
$upn = $_."UserPrincipalName"
Set-MsolUser -UserPrincipalName $upn -PasswordNeverExpires $true;
}

Get all Users whose Password Never Expire

We can select all Azure AD users whose password never expire by using below command.
Get-MsolUser -All | Where-Object { $_.PasswordNeverExpires -eq $true} |
Select DisplayName,UserPrincipalName
Use below command to export output to csv file.
Get-MsolUser -All | Where-Object { $_.PasswordNeverExpires -eq $true} | 
Select DisplayName,UserPrincipalName |
Export-CSV "C:\\PwdNeverExpireUsers.csv" -NoTypeInformation -Encoding UTF8

Tuesday, 18 October 2016

Connecting to remote server failed with the following error message - ps.outlook.com

Problem:

I am receiving the error '[ps.outlook.com] Connecting to remote server failed with the following error message : The SSL connection cannot be established' when I try to connect remote Exchange Online powershell by using below command.
Import-Module MSOnline
$O365Cred = Get-Credential
$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $O365Cred - 
Authentication Basic -AllowRedirection
Import-PSSession $O365Session
Error Message:
[ps.outlook.com] Connecting to remote server failed with the following error message : The SSL connection cannot be established. Verify that the service on the remote host is properly 
configured to listen for HTTPS requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is 
the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig -transport:https". For more information, see the about_Re
mote_Troubleshooting Help topic.
    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [], PSRemotingTransportException
    + FullyQualifiedErrorId : PSSessionOpenFailed

Fix/Solution:

For me the problem was fixed after changing the Exchange Online ConnectionUri https://ps.outlook.com/powershell as https://outlook.office365.com/powershell-liveid/. The below command is working fine for me now.
Import-Module MSOnline
$O365Cred = Get-Credential
$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $O365Cred -Authentication Basic -AllowRedirection
Import-PSSession $O365Session

Thursday, 13 October 2016

Check Mailbox Size and Usage Report using Powershell

In this collaborative business world mail communication is one of the best platform to share messages and files with customers and colleague. So, we often required to check mailbox size and quota for every user's mailbox. In this post, I am going write Powershell script to find mailbox size and usage status and find users who are going to reach their storage quota.

We can use the Exchange Online powershell cmdlet Get-MailboxStatistics to get mailbox size, and other mailbox related statistics data. This cmdlet will be available for both Exchange On-Premises server and Exchange Online (Office 365). Before proceed, first we need to connect Remote Exchange Online powershel module by running below command:
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the below command to get mailbox statistics for a single user.
Get-MailboxStatistics -Identity [username]
By default this command returns the DisplayName, ItemCount, StorageLimitStatus, and LastLogonTime fields for the specified user. But what we need is mailbox size, so we need to alter the command to return required fields.
Get-MailboxStatistics [username] | Select DisplayName, TotalItemSize,StorageLimitStatus, ItemCount
The field StorageLimitStatus indicates whether the user is above or below the storage limit. The field TotalItemSize shows the total size of a mailbox in bytes, we need to convert this size into MB or GB to make the value as user friendly.
Get-MailboxStatistics [username] | Select DisplayName, @{n=”Total Size (MB)”;e={[math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}}, StorageLimitStatus

Find Mailbox Size for all Office 365 users:

You can use the powershell cmdlet Get-Mailbox to get all the mailboxes and pipe the results into Get-MailboxStatistics cmdlet to get mailbox size for all users.
Get-Mailbox -ResultSize Unlimited  | Get-MailboxStatistics |
Select DisplayName, @{n=”Total Size (MB)”;e={[math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}}, StorageLimitStatus

Export Mailbox Size, Quota and Storage Limit Status Report to CSV:

The below powershell script export mailbox name, userprincipalname, current mailbox usage size (TotalItemSize), storage warning quota (IssueWarningQuota), maximum size limit (ProhibitSendQuota) and size limit status (StorageLimitStatus) to csv file
$Result=@() 
$mailboxes = Get-Mailbox -ResultSize Unlimited
$totalmbx = $mailboxes.Count
$i = 1 
$mailboxes | ForEach-Object {
$i++
$mbx = $_
$mbs = Get-MailboxStatistics $mbx.UserPrincipalName
 
Write-Progress -activity "Processing $mbx" -status "$i out of $totalmbx completed"
 
if ($mbs.TotalItemSize -ne $null){
$size = [math]::Round(($mbs.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)
}else{
$size = 0 }

$Result += New-Object PSObject -property @{ 
Name = $mbx.DisplayName
UserPrincipalName = $mbx.UserPrincipalName
TotalSizeInMB = $size
SizeWarningQuota=$mbx.IssueWarningQuota
StorageSizeLimit = $mbx.ProhibitSendQuota
StorageLimitStatus = $mbs.ProhibitSendQuota
}
}
$Result | Export-CSV "C:\\MailboxSizeReport.csv" -NoTypeInformation -Encoding UTF8

Thursday, 6 October 2016

Update User Profile Properties In SharePoint Online Using CSOM

In dynamic business need, we may required to frequently update user profile properties , such as email, manager and other business and personal information. In this article, I am going write Powershell script to set or update user profile properties programmatically using CSOM.

The Microsoft SharePoint Online SDK assembly Microsoft.SharePoint.Client.UserProfiles.dll includes the class PeopleManager and this class includes the following methods:
  • SetSingleValueProfileProperty - This method used to set a single valued property for any user. 
  • SetMultiValuedProfileProperty - This method used to update multi valued property for any user.
  • SetMyProfilePicture - This method used update current user profile picture. Users can only upload a picture to their own profile.

Update Single Value User Properties

Use the below Powershell script to update single valued user property.
#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")

$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 
 
$targetUser = "i:0#.f|membership|alexd@spotenant.onmicrosoft.com" 
#Initialize PeopleManager object
$peopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($ctx) 
# Update user's department info
$peopleManager.SetSingleValueProfileProperty($targetUser, "Department", "Sales Team") 
$ctx.ExecuteQuery() 

Update Multi Valued User Properties

Use the below Powershell script to set multi valued SharePoint user properties.
$siteUrl = "https://spotenant-admin.sharepoint.com" 

$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 
 
$targetUser = "i:0#.f|membership|alexd@spotenant.onmicrosoft.com" 
#Initialize PeopleManager object
$peopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($ctx) 
#Initialize string list to values
$propertyValues =New-Object "System.Collections.Generic.List``1[System.string]"   
# My responsibilities   
$propertyValues.Add("SharePoint")   
$propertyValues.Add("Office 365")           
$propertyValues.Add("Powershell") 
$propertyValues.Add("CSOM") 
# Update profile property
$peopleManager.SetMultiValuedProfileProperty($targetUser, "SPS-Skills", $propertyValues) 
$ctx.ExecuteQuery()

Thursday, 29 September 2016

Read User Profile Properties From SharePoint Online Using CSOM

We may required to retrieve SharePoint Online user profile properties, such as display name, email, title, manager and other business and personal information. In this article, I am going write C# code to get user profile properties programmatically using CSOM. The SharePoint Online SDK assembly Microsoft.SharePoint.Client.UserProfiles.dll includes the class PeopleManager and the PeopleManager class includes the following methods.
  • GetMyProperties - This method returns current user properties.
  • GetPropertiesFor - This method returns all profile properties for a specific person. 
  • GetUserProfilePropertiesFor -This method returns only required properties that you specify
Before proceed, you need to add the assembly reference Microsoft.SharePoint.Client.UserProfiles.dll and include following namespace
using Microsoft.SharePoint.Client; 
using Microsoft.SharePoint.Client.UserProfiles;

Read Current User Profile Properties

First initialize the PeopleManager object and use GetMyProperties() method to retrieve current user profile properties.
public static void GetCurrentUserProfileProperties() 
{ 
    string siteUrl = "https://spotenant-admin.sharepoint.com"; 
 
    // Connect to the sharepoint site client context. 
    ClientContext clientContext = new ClientContext(siteUrl); 
    //clientContext.Credentials = credentials
 
    // Get the PeopleManager object and then get the current user's properties. 
    PeopleManager peopleManager = new PeopleManager(clientContext); 
    PersonProperties myProperties = peopleManager.GetMyProperties(); 
             
    // This request load the AccountName and UserProfileProperties 
    clientContext.Load(myProperties, p => p.AccountName, p => p.UserProfileProperties); 
    clientContext.ExecuteQuery(); 
 
    foreach (var property in myProperties.UserProfileProperties) 
    { 
        Console.WriteLine(string.Format("{0}: {1}", 
            property.Key.ToString(), property.Value.ToString())); 
    } 
}

Get Specific User Profile Properties

To get the specified user profile information, we can use GetPropertiesFor() method by passing target user's account id. The account of the user, should formatted either as a login name, or as a claims identity, e.g. i:0#.f|membership|admin@spotenant.onmicrosoft.com;
public static void GetTargetUserProfileProperties() 
{ 
    string siteUrl = "https://spotenant-admin.sharepoint.com"; 
    string targetUser = "i:0#.f|membership|alexd@spotenant.onmicrosoft.com"; 
 
    // Connect to the sharepoint site client context. 
    ClientContext clientContext = new ClientContext(siteUrl); 
    // clientContext.Credentials = your credentials
 
    // Get the PeopleManager object and then get the target user's properties. 
    PeopleManager peopleManager = new PeopleManager(clientContext); 
    PersonProperties userProperties = peopleManager.GetPropertiesFor(targetUser); 
 
    // This request load the AccountName and user's all other Profile Properties 
    clientContext.Load(userProperties, p => p.AccountName, p => p.UserProfileProperties); 
    clientContext.ExecuteQuery(); 
 
    foreach (var property in userProperties.UserProfileProperties) 
    { 
        Console.WriteLine(string.Format("{0}: {1}", 
            property.Key.ToString(), property.Value.ToString())); 
    } 
}

Get Only Required Profile Properties

You can use the following C# code to get only specific set of user properties.
public static void GetSpecificProfileProperties() 
{ 
    string siteUrl = "https://spotenant-admin.sharepoint.com"; 
    string targetUser = "i:0#.f|membership|alexd@spotenant.onmicrosoft.com"; 
 
    // Connect to the sharepoint site client context. 
    ClientContext clientContext = new ClientContext(siteUrl); 
    // clientContext.Credentials = your credentials
 
    // Get the PeopleManager object. 
    PeopleManager peopleManager = new PeopleManager(clientContext); 
    // Retrieve specific properties by using the GetUserProfilePropertiesFor method.  
    string[] profilePropertyNames = new string[] { "Manager", "Department", "Title" }; 
    UserProfilePropertiesForUser profilePropertiesForUser = new UserProfilePropertiesForUser( 
        clientContext, targetUser, profilePropertyNames); 

    IEnumerable<string> profilePropertyValues = peopleManager.GetUserProfilePropertiesFor(profilePropertiesForUser); 
  
    // Load the request for the set of properties. 
    clientContext.Load(profilePropertiesForUser); 
    clientContext.ExecuteQuery(); 
 
    // Returned collection contains only property values 
    foreach (var value in profilePropertyValues) 
    { 
        Console.WriteLine(value); 
    } 
}

Wednesday, 28 September 2016

Find Last Logon Time for Office 365 Users using Powershell

Getting last logon date of all Office 365 Mailbox enabled users is one of the important task to track user logon activity and find inactive users to calculate the Exchange Online license usage. We can use the Exchange Online powershell cmdlet Get-MailboxStatistics to get last logon time, mailbox size, and other mailbox related statistics data.

Before proceed, first we need to connect Remote Exchange Online powershel module by running below command:
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the following command to get mailbox statistics for a single Office 365 user
Get-MailboxStatistics -Identity <name or upn of user>
To find last logon time for all the Office 365 users, first we need to get all mailboxes by using Get-Mailbox cmdlet and pipe the results to Get-MailboxStatistics.
Get-Mailbox -ResultSize Unlimited | Get-MailboxStatistics | Select-Object DisplayName,LastLogonTime
Using above script, you can get output only from the cmdlet Get-MailboxStatistics and you can't fetch any result from Get-Mailbox. If you want to read detail from Get-Mailbox command like UserPrincipalName, you need to merge output of two cmdlets.
$mailboxes = Get-Mailbox -ResultSize Unlimited
$mailboxes | ForEach-Object {
$mbx = $_
$mbs = Get-MailboxStatistics -Identity $mbx.UserPrincipalName | Select LastLogonTime
if ($mbs.LastLogonTime -eq $null){
$lt = "Never Logged In"
}else{
$lt = $mbs.LastLogonTime }

New-Object -TypeName PSObject -Property @{ 
UserPrincipalName = $mbx.UserPrincipalName
LastLogonTime = $lt }
}

Export Last Logon Time of Office 365 Users to CSV file:

You can also export all Exchange Online user's last logon time to csv file by using below script
$Result=@() 
$mailboxes = Get-Mailbox -ResultSize Unlimited
$totalmbx = $mailboxes.Count
$i = 1 
$mailboxes | ForEach-Object {
$i++
$mbx = $_
$mbs = Get-MailboxStatistics -Identity $mbx.UserPrincipalName | Select LastLogonTime
if ($mbs.LastLogonTime -eq $null){
$lt = "Never Logged In"
}else{
$lt = $mbs.LastLogonTime }

Write-Progress -activity "Processing $mbx" -status "$i out of $totalmbx completed"

$Result += New-Object PSObject -property @{ 
Name = $mbx.DisplayName
UserPrincipalName = $mbx.UserPrincipalName
LastLogonTime = $lt }
}

$Result | Export-CSV "C:\\O365-LastLogon-Info.csv" -NoTypeInformation -Encoding UTF8

Tuesday, 27 September 2016

Invite external users to SharePoint site using CSOM

We may required to automate the process of inviting external users to SharePoint site or document. In this article, I am going write CSOM based C# code to send invitation for bulk external users to site or document.

The Microsoft SharePoint Online SDK assembly Microsoft.SharePoint.Client.dll includes the namespace Microsoft.SharePoint.Client.Sharing in which there are two useful classes called WebSharingManager and DocumentSharingManager. We can use the class WebSharingManager to share a SharePoint site with external users.
private static void InviteExternalUsersForSite() 
{ 
    // Create Connection to SharePoint Online Site 
    using (var context = new ClientContext("https://spotenant.sharepoint.com/sites/contosobeta")) 
    { 
        context.Credentials = new SharePointOnlineCredentials("admin@spotenant.com", securePwd); 
        // Create invitation request list to multiple users 
        var users = new List<string>() { "admin@extDomain.com", "alexd@extDomain.com"}; 
        var userRoles = new List<UserRoleAssignment>(); 
        foreach (var user in users) 
        { 
            UserRoleAssignment role = new UserRoleAssignment(); 
            role.UserId = user; 
            role.Role = Role.View; 
            userRoles.Add(role); 
        } 
        string message = "Please accept this invite to access our SharePoint Site."; 
        // Send invitation requests to external users 
        WebSharingManager.UpdateWebSharingInformation(context, context.Web, userRoles, true, message, true, true); 
        context.ExecuteQuery(); 
    } 
}
We need to use the class DocumentSharingManager to programmtically share a document with external users.
string absoluteFileUrl = "https://spotenant.sharepoint.com/sites/contosobeta/Shared%20Documents/Document.docx"; 
DocumentSharingManager.UpdateDocumentSharingInfo(context, absoluteFileUrl, userRoles, true, true, true, customMsg, true, true);
Note: Here, I have used list to send invitation for multiple users, but you can alternatively import users from csv file and share site or document with bulk users.

Friday, 23 September 2016

Azure AD Import-Module – Could not load file or assembly

Problem:

You will receive the following error when try to run the Windows Azure Active Directory Module or run the command Import-Module MSOnline on a Windows 7 or 2008 R2 machine.
Import-Module : Could not load file or assembly ‘file:///C:\Windows\system32\WindowsPowerShell\v1.0\Modules\MSOnline\Microsoft.Online.Administration.Automation.PSModule.dll’ or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
At line:1 char:14
+ Import-Module <<<<  MSOnline
    + CategoryInfo          : InvalidOperation: (:) [Import-Module], BadImageFormatException
    + FullyQualifiedErrorId : FormatXmlUpateException,Microsoft.PowerShell.Com   mands.ImportModuleCommand

Cause:

This problem will occur due to PowerShell built against the .NET framework in a specific version. You can check it by the PowerShell variable: $PSVersionTable.

Fix/Solution:

For me the problem was solved after installing Windows Management Framework 3.0.

For more detail, you can refer this article: Azure AD Module – This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded

Powershell - Connect-MsolService Error : Method not found

Problem:

After installing Azure Active Directory Powershell module, you will get the following error when you connect Azure AD using the cmdlet Connect-MsolService.
Connect-MsolService : Method not found: 'Void
System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr, !!0)'.
At line:1 char:1
+ Connect-MsolService -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [Connect-MsolService], Mis
   singMethodException
    + FullyQualifiedErrorId : System.MissingMethodException,Microsoft.Online.A
   dministration.Automation.ConnectMsolService

Fix/Solution:

For me the issue was fixed after update my .NET to 4.5.2.

You can also try other solutions if the above update does not fix the problem for you. Check this Microsoft forum for more info: Problem to Connect MsolService

Fix - Office 365 Implicit Remoting Broken in PowerShell

Problem:

You will get the following error when you connect to Exchange Online via PowerShell after the Windows Client Update KB3176934.
Import-PSSession : Could not load type ‘System.Management.Automation.SecuritySupport’ from assembly
‘System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.

Cause:

On August 23, Microsoft released the Windows Client update KB3176934. Due to a missing .MOF file in the build package, the update breaks DSC. All DSC operations will result in an “Invalid Property” error. This is a known issue and it is documented under Known Issues section in https://support.microsoft.com/en-in/kb/3176934

Fix/Solution:

Microsoft released fix for this issue in next cumulative Windows update https://support.microsoft.com/en-us/kb/3176938.

Thursday, 22 September 2016

Create SharePoint List from Custom Template using CSOM

In this post, I am going write C# code sample to create a new list based on existing list template (.stp uploaded to the list template gallery) with managed Client Object Model. Along with creating new sharepoint list or document library, this process creates new content type, site columns , list view and contents (files or list items) if exists in custom list template.

This process includes following steps:

1. Initialize site context by giving site url where we want to create list or document library.
2. Get all custom list templates.
3. Initialize ListCreationInformation with new list or document library name and custom list template.
4. Finally, creates new list with custom template.
private static void CreateLibraryUsingCustomTemplate() 
{ 
    using (var context = new ClientContext("https://spo-tenant.sharepoint.com/sites/teamsite")) 
    { 
        context.Credentials = new SharePointOnlineCredentials("username", securePwd); 
        // Load the custom templates from site collection 
        ListTemplateCollection templates = context.Site.GetCustomListTemplates(context.Web); 
        context.Load(templates); 
        context.ExecuteQuery(); 
        // Initialize list or library creation info 
        var listCreationInfo = new ListCreationInformation 
        { 
            Title = "Test Custom Library", 
            Description = "Test Custom Library" 
        }; 
  
        ListTemplate listTemplate = templates.First(listTemp => listTemp.Name == "<template name>"); 

        listCreationInfo.ListTemplate = listTemplate; 
        listCreationInfo.TemplateFeatureId = listTemplate.FeatureId; 
        listCreationInfo.TemplateType = listTemplate.ListTemplateTypeKind;  
        // Add Document Library to site 
        context.Web.Lists.Add(listCreationInfo); 
        context.ExecuteQuery(); 
    } 
} 

Friday, 16 September 2016

Rename a document in Sharepoint Online using CSOM

There is no direct function to rename a uploaded document in SharePoint document library using the client side object model (csom), as a work-around, we need to use File.MoveTo method to rename a file. Here we need to actually move the file in same location with different name.

Use the below powershell script to rename a specific sharepoint document file.
#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")  
 
$siteUrl = "https://spotenant.sharepoint.com/sites/contosobeta" 
$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 
 
#Rename a file 
$fileUrl ="/sites/contosobeta/Shared Documents/test.csv" 
$newfileUrl="/sites/contosobeta/Shared Documents/test_rename.csv" 

$file = $ctx.Web.GetFileByServerRelativeUrl($fileUrl) 
$file.MoveTo($newfileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite) 
$ctx.ExecuteQuery() 

Rename a file using Office Dev PnP

You can also use below powershell code to rename a document stored inside a SharePoint Online document library using Office Dev PnP.
Connect-SPOnline -url [yoururl]
$ctx = Get-SPOContext
$web = Get-SPOWeb
$fileUrl ="/sites/contosobeta/Shared Documents/test.csv" 
$newfileUrl="/sites/contosobeta/Shared Documents/test_rename.csv" 
$file = $web.GetFileByServerRelativeUrl("$fileUrl")
$file.MoveTo("$newfileUrl", 'Overwrite')
$ctx.ExecuteQuery()
 

Rename all uploaded document files in a SharePoint List

You can also use the below powershell script to rename all the files in a document library.
$siteUrl = "https://spotenant.sharepoint.com/sites/contosobeta" 
$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 
  
#Load items 
$list = $ctx.Web.Lists.GetByTitle("Documents") 
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery() 
$items = $list.GetItems($query) 
$ctx.Load($items) 
$ctx.ExecuteQuery() 
 
#Rename File(s) 
foreach ($item in $items){ 
if($item.FileSystemObjectType -eq [Microsoft.SharePoint.Client.FileSystemObjectType ]::File) {  
$destFileUrl = $item["FileRef"].ToString().Replace("test","test_rename") 
$item.File.MoveTo($destFileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite) 
$ctx.ExecuteQuery() 
} 
}

Thursday, 15 September 2016

Guest access feature indroduced for Office 365 Groups

The introduction of Office 365 groups gives the rich collaboration within a team inside an organization. There will be a situation you need to give access to outside of organisation when you work closely with customers, partners, and others outside organizations. The importance of collaboration with external users is inevitable in various business needs, to resolve this, Microsoft finally announced the external user (Guest) access feature: Introducing guest access for Office 365 Groups


Note: Microsoft announced the guest access feature works only for email accounts including corporate and consumer domains (such as Outlook.com or Gmail.com). If the guest email identity is associated with a Microsoft account (such as Office 365 or Outlook.com accounts, for instance), the user is directed to a sign-in page to identify themselves. If the guest doesn’t have a Microsoft account, they will be directed to a sign-up page to create an account.

You can also read this great article https://www.petri.com/external-access-office-365-groups (by Tony Redmond) to know more about how to add guest users for Office 365 Groups and how an external user invitation works for guest users.

Wednesday, 14 September 2016

Get all Documents from a SharePoint List using CSOM

In this post, I am going to write C# code to list all documents in a SharePoint list and get all files from SharePoint Site using Client Object Model (CSOM).

List all documents in a SharePoint Document Library

The below C# code find and list all files in the particular document library. You can replace your own list name to get required documents.
public static void GetAllDcoumentsInaList() 
{    
    string sitrUrl = "https://SPTenant.sharepoint.com/sites/contosobeta"; 
    using (var ctx = new ClientContext(sitrUrl)) 
    { 
        //ctx.Credentials = Your Credentials
        ctx.Load(ctx.Web, a => a.Lists); 
        ctx.ExecuteQuery(); 

        List list = ctx.Web.Lists.GetByTitle("Documents"); 
        var items = list.GetItems(new CamlQuery() { ViewXml = "<View Scope=\"RecursiveAll\"><Query><Where><IsNotNull><FieldRef Name=\"File_x0020_Type\" /></IsNotNull></Where></Query></View>" }); 
        ctx.Load(items); 
        ctx.ExecuteQuery(); 
        foreach (var doc in items) 
        { 
            Console.WriteLine(doc["FileRef"].ToString().Split('/').LastOrDefault() + 
                " (" + doc["File_x0020_Size"].ToString() + " bytes)"); 
        } 
    } 
} 

Get all documents in a SharePoint Site

To retrieve items from entire site, first, we need to fetch all the lists in a site and add condition check BaseType in list to filter only document libraries.
public static void GetAllDcoumentsInaSite() 
{ 
    string sitrUrl = "https://SPTenant.sharepoint.com/sites/contosobeta"; 
    using (var ctx = new ClientContext(sitrUrl)) 
    { 
        //ctx.Credentials = Your Credentials
        ctx.Load(ctx.Web, a => a.Lists); 
        ctx.ExecuteQuery(); 
 
        foreach (List list in ctx.Web.Lists) 
        { 
            if (list.BaseType == BaseType.DocumentLibrary) 
            { 
                Console.WriteLine("List: " + list.Title); 
                Console.WriteLine("-----------------------"); 
                var items = list.GetItems(new CamlQuery() { ViewXml = "<View Scope=\"RecursiveAll\"><Query><Where><IsNotNull><FieldRef Name=\"File_x0020_Type\" /></IsNotNull></Where></Query></View>" }); 
                ctx.Load(items); 
                ctx.ExecuteQuery(); 
                foreach (var doc in items) 
                { 
                    Console.WriteLine(doc["FileRef"].ToString().Split('/').LastOrDefault() + 
                " (" + doc["File_x0020_Size"].ToString() + " bytes)"); 
                } 
            } 
        } 
    } 
} 

Thursday, 8 September 2016

CSOM : The request uses too many resources - SharePoint Online

I have the following c# csom (client side object model) code to get sub sites and nested sub sites of a site collection. This code runs perfectly for most site collections, but it not working for a single site collection which has a lot of sub-sites and nested sub sites.
private static List<Web> RecursiveSites(ClientContext siteCtx, Web site)
{
    var allSites = new List<Web>();
    allSites.Add(site);
    if (site.Webs.Count > 0)
    {
        siteCtx.Load(site.Webs, w => w.Include(a => a.Title, a => a.Url, a => a.Webs));
        siteCtx.ExecuteQuery();
        foreach (Web web in site.Webs)
        {
            allSites.AddRange(RecursiveSites(siteCtx, web));
        }
    }
    return allSites;
}
I am receiving below error:
Microsoft.SharePoint.Client.ServerException: The request uses too many resources
After googled sometime, I've found an article in MSDN that explains the request limits of the csom. You can refer this under the heading Request limits of the CSOM at bottom of this article https://msdn.microsoft.com/en-us/library/office/jj163082.aspx
The CSOM in Project Server 2013 is built on the CSOM implementation in SharePoint Server 2013 and inherits the limits 
for the maximum size of a request. SharePoint has a 2 MB limit for an operations request, and a 50 MB limit for the size of a
submitted binary object. The request size is limited to protect the server from excessively long queues of operations and
from processing delays for large binary objects.
.

Solution:

In SharePoint On-Premise, you can resolve this issue by setting the maxObjectPaths in WebApplication to a higher value using Powershell:
#Get the value:
Get-SPWebApplication | %{$_.ClientCallableSettings}

#Set the Value:
Add-PSSnapin Microsoft.SharePoint.PowerShell
$webApp = Get-SPWebApplication "http://myspwebapp/"
$webApp.ClientCallableSettings.MaxObjectPaths = 2500
$webApp.Update()
But in SharePoint Online, there is no way to access the ClientCallableSettings.MaxObjectPaths property. so we need to re-write the code to reduce request size. I have changed the code in a way to send request for one site instead of all sub sites at the same time, now the code execute the siteCtx.ExecuteQuery() inside the loop instead of outside the loop.
private static List<Web> RecursiveSites(ClientContext siteCtx, Web site)
{
    var allSites = new List<Web>();
    allSites.Add(site);
    if (site.Webs.Count > 0)
    {     
        foreach (Web web in site.Webs)
        {
            siteCtx.Load(web , w => w.Title, w => w.Url, w => w.Webs);
            siteCtx.ExecuteQuery();
            allSites.AddRange(RecursiveSites(siteCtx, web));
        }
    }
    return allSites;
}

Wednesday, 31 August 2016

Office 365 License Report using PowerShell

We can use the Azure AD powershell cmdlet Get-MsolUser to get all office 365 users. This command also returns the license based property IsLicensed and Licenses (applied license details).

Note: Before proceed, Install and Configure Azure AD PowerShell

Run the below command to get all the office 365 users.
Get-MsolUser -All  | Select-Object UserPrincipalName, DisplayName, isLicensed
The below command returns only licensed office 365 users.
Get-MsolUser -All | Where-Object { $_.isLicensed -eq $true } |
Select-Object UserPrincipalName, DisplayName, Department
You can also extract what are the licenses has been assigned to every users.
Get-MSOLUser -All | Where-Object { $_.isLicensed -eq $true } |
Select-Object UserPrincipalName, DisplayName, {$_.Licenses.AccountSkuId}
Run the below command to export all the licensed users and applied license details to csv file.
Get-MSOLUser -All | Where-Object { $_.isLicensed -eq $true } |
Select-Object UserPrincipalName, DisplayName, {$_.Licenses.AccountSkuId} |
 Export-CSV "C:\\office-365-users-license.csv" -NoTypeInformation -Encoding UTF8
You can read this technet article: https://technet.microsoft.com/en-us/library/dn771771.aspx to get fine-tuned license report, like all licensed users who are enabled for specific license plan.

Tuesday, 30 August 2016

Powershell - Write Output in Console

There are multiple ways to write output to powershell console, you can simply put quotation marks in any string to display on the screen and you can also use the powershell cmdlets Write-Host and Write-Output.
"Hello World1"
Write-Host "Hello world2"
Write-Output "Hello World3"
The Write-Host is the best choice in many cases, it is the cmdlet designed specifically to display output only on powershell console screen. You can display the output with background color and foreground color by using Write-Host.
Write-Host "Hello world" -BackgroundColor "Green" -ForegroundColor "Black"
Write-Output cmdlet should be used when you want to send data into the pipe line, but not necessarily want to display it on screen. Because, you can't pipe the output when you use Write-Host.
function Test-Output {
    Write-Output "Hello World"
}

function Receive-Output {
    process { Write-Host $_ -ForegroundColor Yellow }
}

#Output piped to another function, not displayed in first.
Test-Output | Receive-Output
You can get more detail about the cmdlets Write-Host and Write-Output from this article : https://blogs.technet.microsoft.com/heyscriptingguy/2011/05/17/writing-output-with-powershell/

Host Web vs App Web in SharePoint

If you are newbie for SharePoint apps development, you might be wondering to know clear idea about the terminologies host web and app web (add-in web).

The special site where the app is deployed is called an app web. The site where the app is installed is called the host web. In other words, the SharePoint add-in which host SharePoint components (e.g. lists, content types etc.) is called the app web.

Consider that you are developing an app with custom ribbon action in List view page and the custom action click redirects you to the special site page. Here, the custom action placed in host web and special page is an app web

App Web - The special website to which the add-in is deployed

Host Web - The site on which the App is installed

For more detail checkout this article : https://msdn.microsoft.com/en-us/library/office/fp179925.aspx

Monday, 29 August 2016

How to change product key in Office or Outlook 2016

Today, I have installed Office 2016 setup to use Outlook 2016 and put in the product key when I open the outlook. After entering the product key, it sends to the product Activation page, the product activation message says that it is valid key but it is already used. So, now I have been forced to change the new product key.

Find and Reset Office 2016 License Key using VBScript

1. Open a command prompt (Start-> Run: cmd).
2. Run the following commands:
cscript "C:\Program Files\Microsoft Office\Office16\ospp.vbs" /dstatus
3. Note it the 5 digit partial product key (You may find multiple keys).
How to change license key in Office or Outlook 2016
4. Then run the following command after replacing the <partial_key> with the 5 digit key that you got previous step.
cscript "C:\Program Files\Microsoft Office\Office16\ospp.vbs" /unpkey:<partial_key>
This will uninstall an installed product key with partial product key you noted earlier. Uninstall all of the keys.

5. Now you should be able to set the license key as usual way. Or you can use following command after replacing the <new_full_key> with your new license key:
cscript "C:\Program Files\Microsoft Office\Office16\ospp.vbs" /inpkey:<new_full_key>
Then you need run the below command to activate license.
cscript "C:\Program Files\Microsoft Office\Office16\ospp.vbs" /act

Note:

Depending on the combination of Office version you might have to change the path to Program Files(x86)

For (x64 Office 2016) : C:\Program Files\Microsoft Office\Office16\
For (x86 Office 2016): C:\Program Files(x86)\Microsoft Office\Office16\

For (x64 Office 2013) : C:\Program Files\Microsoft Office\Office13\
For (x86 Office 2013): C:\Program Files(x86)\Microsoft Office\Office13\

Friday, 26 August 2016

Powershell - Check Contains String In Where Object

You can use the Where-Object cmdlet to filter objects from a collection based on their property values. We can use the comparison operator like with wildcard character to check if a property of object contains a specific string.
Note: You can not use the comparison operator contains to check the contains string, because it's designed to tell you if a
collection of objects includes ('contains') a particular object
The following command returns all the processes in current machine.
Get-Process | Select ID,ProcessName
If you want to list only the process which contains string '32' in processname, you need to use the below command.
Get-Process | Where-Object { $_.Name -like '*32*' }
By default like operator ignore the case-sensitive check. To perform a case-sensitive comparison just prefix the word "c" with like operator ("clike").
Get-Process | Where-Object { $_.Name -clike '*rundll*' }
If you want to check starts with string, you can use the same like operator with appending * at the end of the string alone.
Get-Process | Where-Object { $_.Name -like 'rundll*' }
Likewise, to check ends with string, need to append * at start of the string.
Get-Process | Where-Object { $_.Name -like '*host' }

Thursday, 25 August 2016

Yammer is going to work with Office 365 Groups

As Microsoft moving the most valuable Office 365 IT Pro discussion network from Yammer to new lithium based Office 365 Network, most of the people's feeling is what Microsoft going to do with Yammer. Whether they are going kill Yammer to promote Office 365 Groups? or they have any other idea?.

Yammer is not dead, it’s growing as a part of Office 365 Groups service. That’s a good thing for your users and team scenarios. You can choose for your Group whether you want conversations to happen in Outlook (Email) or in Yammer (Social Network). You’ll also have other Office 365 Groups features available in Yammer, including SharePoint Team Site for Files, a Shared Calendar (powered by Exchange), a OneNote shared notebook, Planner boards, Power BI and Connectors so you’ll finally have all the integration points that you have waited so for.

Checkout this great article : https://naomimoneypenny.com/2016/08/24/yammers-place-in-office-365-groups/ for more information regarding Office 365 Groups and Yemmer's current uncertainty mode.

As prior step, all of these changes and value adds, rely on having the switch that says ‘Enforce O365 Identity‘ pushed in Yammer. As Yammer becomes a core service for your organization, you’ll want users to be able to log into it seamlessly, just like any other Office 365 service. Additionally, you’ll probably want to maintain a single identity for all Office 365 users for easier user management. You can achieve both of these goals by enforcing Office 365 identity in Yammer. By enforcing Office 365 identity in Yammer and configuring federated identity for Office 365, admins can achieve single sign-on (SSO) capabilities for all services in Office 365, including Yammer.

Checkout this detailed article : Enforce Office 365 identity for Yammer users  for more information

Wednesday, 24 August 2016

Powershell - Check If String Contains Word

We can use the powershell's like operator with wildcard character to check if a string contains a word or another string with case-sensitive and case-insensitive.
Note: You can not use the comparison operator contains to check the contains string, because it's designed to tell you if a
collection of objects includes ('contains') a particular object
The following method is used to check if a string contains a word using like operator. By default like operator ignore the case-sensitive check.
$strVal ='Hello world'
if($strVal -like '*World*') {
      Write-Host 'Your string contains the word world'
} else {
      Write-Host 'Your string does not contains the word world'
}
To perform a Case-Sensitive comparison just prefix the word "c" with like operator ("clike").
$strVal ='Hello world'
if($strVal -clike '*world*') {
      Write-Host 'True'
} else {
      Write-Host 'False'
}
We can also use the built in .NET string extension function Contains to check whether a string contains a another string.
$strVal ='Hello world'
if($strVal.Contains('world')) {
     Write-Host 'True'
} else {
     Write-Host 'False'
}
The .Contains() function is case sensitive. If you want to use the Contains() method for case-insensitive check, convert both strings to one case before compare.
$strVal ='Hello world'
if($strVal.ToLower().Contains('world'.ToLower())) {
     Write-Host 'True'
} else {
     Write-Host 'False'
}

Tuesday, 23 August 2016

Powershell - Check If String Starts With IgnoreCase

Checking a string is startswith some character(or a string) is common need for every kind of powershell script. We can use the powershell's like operator with wildcard character to check the startswith string for both case-sensitive and case-insensitive.

The following method is used to check if a string is starts with another string using like operator. By default like operator ignore the case-sensitive check.
$strVal ='Hello world'
if($strVal -like 'hello*') {
      Write-Host 'Your string is start with hello'
} else {
      Write-Host 'Your string does not start with hello"'
}
To perform a Case-Sensitive comparison just prefix the word "c" with like operator ("clike").
$strVal ='Hello world'
if($strVal -clike 'Hello*') {
      Write-Host 'True'
} else {
      Write-Host 'False'
}
We can also use the .NET's string extension function StartsWith to check whether a string is startswith a set of characters. The following method is used to check if a string is start with other string.
$strVal ='Hello world'
if($strVal.StartsWith('Hello')) {
     Write-Host 'True'
} else {
     Write-Host 'False'
}
Use the following method if you want to ignore the case in start with check.
$strVal ='Hello world'
if($strVal.StartsWith('hello','CurrentCultureIgnoreCase')) {
     Write-Host 'True'
} else {
     Write-Host 'False'
}

Monday, 22 August 2016

Complete List of SharePoint List Template IDs

This post list the complete SharePoint List Templates and IDs. You should know the template id for every type of list to differentiate all the lists. When you work with client side object models(CSOM) or any other scripting technology, this template id will be used to filter the specified type of lists (i.e. if you want to get all the asset library lists, you need to filter the lists by the template id 851).

Template Type Id Description
100 Generic List
101 Document Library
102 Survey List
103 Links List
104 Announcements List
105 Contacts List
106 Events List
107 Tasks List
108 Discussion Board
109 Picture Library
110 DataSources List
111 WebTemplate Catalog
112 UserInformationList
114 ListTemplate Catalog
113 WebPart Catalog
115 XmlForm Library
116 MasterPage Catalog
117 NoCode Workflows
118 Workflow Process
119 WikiPage Library
120 Grid List
121 SolutionCatalog
122 NoCode Workflows Public
123 Theme Catalog
130 DataConnection Library
140 Workflow History
150 Gantt Tasks
151 Help Library
200 Meetings List
201 MeetingAgenda List
202 MeetingAttendees List
204 MeetingDecision List
207 MeetingObjectives List
210 MeetingTextBox
211 MeetingThingsToBring List
212 MeetingHomePage Library
301 BlogPosts List
302 BlogComments List
303 BlogCategories List
400 ScheduleAndReservations
401 ManageResources List
402 Resources List
403 Whereabouts List
404 CallTrackingPhoneMemo
405 Circulation
420 Timecard
421 Holidays
432 KPIStatus List
433 Report Library
450 PerformancePointContent List
460 PerformancePointDataSource Library
470 PerformancePointDataConnections Library
480 PerformancePointDashboards Library
499 MicrosoftIMEDictionary List
505 VisioProcessDiagram Library (Metric)
506 VisioProcessDiagram Library (US Units)
600 External List
850 Pages Library
851 Asset Library
1100 IssueTracking List
1200 AdministratorTasks List
1220 Health Rules
1221 Health Reports
1300 TranslationManagement Library
1301 LanguagesAndTranslators List
1302 Record Library
2002 PersonalDocument Library
2003 PrivateDocument Library
2100 Slide Library

Thursday, 18 August 2016

Export Office 365 Email Addresses to CSV using Powershell

In this post, I am going write steps to export the list of exchange online users and their email addresses from Office 365 to csv file. We can use the powershell cmdlet Get-Mailbox to get mailbox information and use the cmdlet Export-CSV to export content to csv file.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

Then run the below powershell command to list the mailbox users and its primary email address.
Get-Mailbox -ResultSize Unlimited |Select-Object DisplayName,PrimarySmtpAddress
The following command export all the exchange online users and its associated email addresses to csv file.
Get-Mailbox -ResultSize Unlimited |
Select-Object DisplayName,PrimarySmtpAddress, @{n="EmailAddresses";e={$_.EmailAddresses |
Where-Object {$_ -like "smtp*"} | ForEach-Object {$_.Substring(5)}}} | 
Export-Csv "C:\\o365-email-addresses.csv" -NoTypeInformation -Encoding UTF8

Thursday, 11 August 2016

Convert a distribution group to an Office 365 group from Admin Center

Finally, the support for migrating Distribution list to Office 365 group comes to live through Office 365 Admin center. The introduction of Office 365 groups gives the next level for cloud first and mobile first agenda since it gives the rich collaboration experiences.

The office 365 group is the next generation type of group that replaces the function of a traditional distribution list, and it includes the benefits of a security group, along with many other rich collaboration that enables teams to come together and establish a single team identity and a single set of permissions across different Office 365 apps including Outlook, Planner, OneNote,OneDrive, Skype for Business, etc.

Using new DL migration option, you can now migrate a distribution group to an Office 365 group directly from the Exchange Admin Center.

For more details read this thread: https://network.office.com/t5/Exchange/Migrate-a-distribution-group-to-an-Office-365-group-with-one/m-p/4340/highlight/true#M81

migrate a distribution list to an Office 365 groupr

Wednesday, 10 August 2016

Export Office 365 Users to CSV using PowerShell

We can easily export users using Office 365 Admin center UI, but in this way we can get only set of attributes and we can't easily filter our required set of users. In this article, I am going to write powershell script to export all office 365 users and export only licensed users to csv file.

Note: Before proceed, Install and Configure Azure AD PowerShell

Use the below command to export all the office 365 users. You can add more columns to export.
Get-MsolUser -All  | Select-Object UserPrincipalName, DisplayName, isLicensed |
Export-CSV "C:\\all-office-365-users.csv" -NoTypeInformation -Encoding UTF8
In some scenarios, you might want to get details of only licensed office 365 users. To get only licensed users, you need to apply where filter in the output of Get-MsolUser cmdlet.
Get-MsolUser -All | Where-Object { $_.isLicensed -eq ”TRUE” } | 
Select-Object UserPrincipalName, DisplayName, Department  |
Export-CSV "C:\\licensed-office-365-users.csv" -NoTypeInformation -Encoding UTF8
You can also extract what are the licenses has been assigned to every users. The below command export all the licensed users and applied license details to csv file.
Get-MSOLUser -All | Where-Object { $_.isLicensed -eq ”TRUE” } | 
Select-Object UserPrincipalName, DisplayName, {$_.Licenses.AccountSkuId} |
 Export-CSV "C:\\office-365-users-license.csv" -NoTypeInformation -Encoding UTF8
Note: Checkout this post ( Manage Office 365 License using Powershell ) to add a new license, remove an existing license and update existing license options (enable or disable license plans) using PowerShell command.

Thursday, 4 August 2016

Mailbox : WhenCreated vs WhenMailboxCreated

You should have noticed the two attributes WhenCreated and WhenWhenMailbox while fetching the information through powershell using the cmdlet Get-Mailbox. The WhenMailboxCreated attribute shows the time when the mailbox was created or license assigned (in office 365). On the other side, the WhenCreated attribute gives time when the mailbox associated AD user or Azure AD user was actually created. So, the value of these two attributes may or may not equal.

WhenMailboxCreated : Gives the time when the mailbox was created.

WhenCreated : The time of when the AD user or Azure AD user of the associated mailbox was created.

So, if you want to get the list of mailboxes that are created in last 7 days. You need to use following powershell command.
Get-Mailbox | Where-Object {$_.WhenMailboxCreated –ge ((Get-Date).Adddays(-7))}
You may get incorrect results when you use whencreated to get mailboxes that are created in past N days. But, you can use below command to get actual AD users who are created in last 7 days.
Get-Mailbox | Where-Object {$_.WhenCreated –ge ((Get-Date).Adddays(-7))}

Wednesday, 13 July 2016

whenCreated vs createTimeStamp

Both are Active Directory schema attributes which specifies the date and time of when an AD object was created. Both attributes return the same values, but the actual value is stored in whenCreated attribute alone, because createTimeStamp is a constructed attribute and it reads the data from whenCreated attribute.

WhenCreated attribute was implemented first, and to be complaint with LDAP standards the createTimeStamp was added later on as constructed attribute, the data is really stored only once in the Active Directory database.

Both attributes are replicated to all DC's, the createTimeStamp should not be replicated to the Global Catalog server since the isMemberOfPartialAttributeSet property of the attribute is not TRUE. However, you can also get a value from the GC.

Sources:

whenCreated vs createTimeStamp
Active directory attributes - createTimeStamp & whenCreated

Tuesday, 12 July 2016

UserAccountControl Attribute Flag Values - Active Directory

UserAccountControl attribute is bitwise attribute and it control the behavior of the AD user and computer account.

This attribute value can be zero or a combination of one or more of the following values.

Property flagValue in hexadecimalValue in decimal
SCRIPT0x00011
ACCOUNTDISABLE0x00022
HOMEDIR_REQUIRED0x00088
LOCKOUT0x001016
PASSWD_NOTREQD0x002032
PASSWD_CANT_CHANGE
Note You cannot assign this permission by directly modifying the UserAccountControl attribute. For information about how to set the permission programmatically, see the "Property flag descriptions" section.
0x004064
ENCRYPTED_TEXT_PWD_ALLOWED0x0080128
TEMP_DUPLICATE_ACCOUNT0x0100256
NORMAL_ACCOUNT0x0200512
INTERDOMAIN_TRUST_ACCOUNT0x08002048
WORKSTATION_TRUST_ACCOUNT0x10004096
SERVER_TRUST_ACCOUNT0x20008192
DONT_EXPIRE_PASSWORD0x1000065536
MNS_LOGON_ACCOUNT0x20000131072
SMARTCARD_REQUIRED0x40000262144
TRUSTED_FOR_DELEGATION0x80000524288
NOT_DELEGATED0x1000001048576
USE_DES_KEY_ONLY0x2000002097152
DONT_REQ_PREAUTH0x4000004194304
PASSWORD_EXPIRED0x8000008388608
TRUSTED_TO_AUTH_FOR_DELEGATION0x100000016777216
PARTIAL_SECRETS_ACCOUNT0x04000000  67108864

Note: In a Windows Server 2003-based domain, LOCK_OUT and PASSWORD_EXPIRED have been replaced with a new attribute called ms-DS-User-Account-Control-Computed. For more information, check this article:https://msdn.microsoft.com/en-us/library/ms677840.aspx.

All the information available in Microsoft KB Article: https://support.microsoft.com/en-in/kb/305144

UserAccountControl flag descriptions:

  • SCRIPT - The logon script will be run.
  • ACCOUNTDISABLE - The user account is disabled.
  • HOMEDIR_REQUIRED - The home folder is required.
  • PASSWD_NOTREQD - No password is required.
  • PASSWD_CANT_CHANGE - The user cannot change the password. This is a permission on the user's object. For information about how to programmatically set this permission, visit the following Web site:
  • ENCRYPTED_TEXT_PASSWORD_ALLOWED - The user can send an encrypted password.
  • TEMP_DUPLICATE_ACCOUNT - This is an account for users whose primary account is in another domain. This account provides user access to this domain, but not to any domain that trusts this domain. This is sometimes referred to as a local user account.
  • NORMAL_ACCOUNT - This is a default account type that represents a typical user.
  • INTERDOMAIN_TRUST_ACCOUNT - This is a permit to trust an account for a system domain that trusts other domains.
  • WORKSTATION_TRUST_ACCOUNT - This is a computer account for a computer that is running Microsoft Windows NT 4.0 Workstation, Microsoft Windows NT 4.0 Server, Microsoft Windows 2000 Professional, or Windows 2000 Server and is a member of this domain.
  • SERVER_TRUST_ACCOUNT - This is a computer account for a domain controller that is a member of this domain.
  • DONT_EXPIRE_PASSWD - Represents the password, which should never expire on the account.
  • MNS_LOGON_ACCOUNT - This is an MNS logon account.
  • SMARTCARD_REQUIRED - When this flag is set, it forces the user to log on by using a smart card.
  • TRUSTED_FOR_DELEGATION - When this flag is set, the service account (the user or computer account) under which a service runs is trusted for Kerberos delegation. Any such service can impersonate a client requesting the service. To enable a service for Kerberos delegation, you must set this flag on the userAccountControl property of the service account.
  • NOT_DELEGATED - When this flag is set, the security context of the user is not delegated to a service even if the service account is set as trusted for Kerberos delegation.
  • USE_DES_KEY_ONLY - (Windows 2000/Windows Server 2003) Restrict this principal to use only Data Encryption Standard (DES) encryption types for keys.
  • DONT_REQUIRE_PREAUTH - (Windows 2000/Windows Server 2003) This account does not require Kerberos pre-authentication for logging on.
  • PASSWORD_EXPIRED - (Windows 2000/Windows Server 2003) The user's password has expired.
  • TRUSTED_TO_AUTH_FOR_DELEGATION - (Windows 2000/Windows Server 2003) The account is enabled for delegation. This is a security-sensitive setting. Accounts that have this option enabled should be tightly controlled. This setting lets a service that runs under the account assume a client's identity and authenticate as that user to other remote servers on the network. 
  • PARTIAL_SECRETS_ACCOUNT - (Windows Server 2008/Windows Server 2008 R2) The account is a read-only domain controller (RODC). This is a security-sensitive setting. Removing this setting from an RODC compromises security on that server.

Tuesday, 5 July 2016

How to call a function in a ps1 file from powershell

In Powershell world, the user defined function is one of the easiest way to reuse the set of powershell commands. In some scenarios, this function might be too big, so having functions in separate ps1 file and load a function by importing .ps1 file is a good choice. In this post, I am going to explain how to import a powershell function from ps1 file.

Load Powershell function from ps1 file:

You just imagine the ps1 file MyScript.ps1, and the file contains the following content:
Write-Host "Loading functions"
function MyFunc
{
    Write-Host "MyFunc is running!"
}
Write-Host "Done"
To register the function MyFunc, we need to run the .ps1 file with the dot(.) operator prefix.
 . C:\Scripts\MyScript.ps1
The dot operator is used to include script.
PS C:>  . C:\Scripts\MyScript.ps1
Loading functions
Done

PS C:\> MyFunc
MyFunc is running!

Import Powershell function from psm1 file:

We can also import a function from PSM1 file by using Import-Module command. The major advantage of using Import-Module is that you can unload them from the shell if you need to, and it keeps the variables in the functions from creeping into the shell. First, save the MyScript.ps1 as MyScript.psm1 and load the file by using below command.
Import-Module C:\Scripts\MyScript.psm1
PS C:\> Import-Module C:\Scripts\MyScript.psm1
Loading functions
Done
PS C:\> MyFunc
MyFunc is running!

Tuesday, 21 June 2016

Create Office 365 Group using Powershell

Office 365 Groups provide a platform for collaboration that enables teams to come together and establish a single team identity and a single set of permissions across different Office 365 apps including Outlook, OneDrive, OneNote, Skype for Business, Power BI and Dynamics CRM. In this article, I am going write powershell commands to create Office 365 Groups, add members and owners to an Office 365 Group.

Before proceed, first connect Exchange Online Powershell session by using the following commands.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session
We can use the PowerShell cmdlet New-UnifiedGroup to create a new Office 365 group. This cmdlet includes the following key parameters:

DisplayName – display name of the new group
Alias – Email alias of the group. If you omit the parameter, it will generate an alias by using display name.
AccessType – Privacy type of the group (Public or Private)
AutoSubscribeNewMembers – Add this parameter to auto subscribe new members to the group

Use the below command to create a new group with minimal parameters.
New-UnifiedGroup –DisplayName "Test O365 Group 1"
Create the group with key parameters.
New-UnifiedGroup –DisplayName "Test O365 Group 2" -Alias "TestO365Group2" -AccessType Public
Once we created the group, we can use Get-UnifiedGroup cmdlet to list all the available groups.

Add Members and Owners to Office 365 Group

We can use Add-UnifiedGroupLinks cmdlet to add members and owners to the group. This cmdlet includes the following key parameters:

Identity – Alias, Display name, or Email address of the group
Links – Alias, Display name, or Email address of the user being added
LinkType – Members, Owners, or Subscribers

Add an user as owner: To add an user as owner to the group, first we need the user as a member to the specified group.
Add-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Members –Links Morgan
Add-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Owners –Links Morgan
Add member:
Add-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Members  –Links AlexD
Add subscriber: A subscriber who receives updates by email can be added by changing the LinkType to "Subscribers"
Add-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Subscribers  –Links AlexD
The parameter Links accept multiple values, use the following syntax: value1,value2.... If the values contain spaces or otherwise require quotation marks, use the following syntax: "value1","value2",....

Add members to multiple office 365 groups:

$Groups = "group 01","group 02","group 03"
$Groups | ForEach-Object {
Add-UnifiedGroupLinks –Identity $_ –LinkType Members  –Links "Morgan" }

Import office 365 group members from a CSV File:

You can use the below powershell commands to add members to an office 365 group by importing users from csv file. Consider the csv file members.csv that includes the column member which holds the member identity in each row of the csv file.
Import-CSV "C:\members.csv" | ForEach-Object {
Add-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Members  –Links $_.member
}

Find members and owners of a group:

Once we added the members and owners, we can use Get-UnifiedGroupLinks cmdlet to get members or owners of a specific group. The below command lists all members of the given group.
Get-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Members
List owners of a group.
Get-UnifiedGroupLinks –Identity "TestO365Group2" –LinkType Owners