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.
Read More...

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
Read More...

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
Read More...

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.
Read More...

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(); 
    } 
} 
Read More...

Friday, 16 September 2016

How to 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() 
} 
}
Read More...

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.
Read More...

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)"); 
                } 
            } 
        } 
    } 
} 
Read More...

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;
}
Read More...

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 licensed 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.
Read More...

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/
Read More...

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
Read More...

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\
Read More...

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' }
Read More...

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
Read More...