Monday, 29 February 2016

Force WMI to read the 32-bit Registry Hive on a 64-bit Computer

In some cases, the registry settings for installed Applications will be available only in WoW6432Node even in 64-bit machine. So, we need to force WMI to access the 32-bit Registry Hive in 64 bit computer.

Use the following C# code to access 32 bit registry hive information in 64 machine. We can force WMI to load the 32-bit provider by adding the ConnectionOptions __ProviderArchitecture and __RequiredArchitecture.
private static void Read32RegistryIn64Machine()
{
    uint LOCAL_MACHINE = 0x80000002;
    ConnectionOptions options = new ConnectionOptions();
    options.Impersonation = ImpersonationLevel.Impersonate;
    options.EnablePrivileges = true;
    options.Username = "MyUserName";
    options.Password = "MyPassword";

    ManagementScope mgmtScope = new ManagementScope("\\\\" + "ComputerName" + "\\root\\default", options);

    mgmtScope.Options.Context.Add("__ProviderArchitecture", 32);
    mgmtScope.Options.Context.Add("__RequiredArchitecture", true);

    ManagementClass mc = new ManagementClass(mgmtScope, new ManagementPath("StdRegProv"), null);
    ManagementBaseObject inParams = mc.GetMethodParameters("EnumKey");
    inParams["hDefKey"] = LOCAL_MACHINE;
    inParams["sSubKeyName"] = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";

    ManagementBaseObject outParams = mc.InvokeMethod("EnumKey", inParams, null);
    inParams = mc.GetMethodParameters("GetStringValue");
    inParams["hDefKey"] = LOCAL_MACHINE;

    foreach (string name in (string[])outParams["sNames"])
    {
        inParams["sSubKeyName"] = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + "\\" + name;
        inParams["sValueName"] = "DisplayName";
        outParams = mc.InvokeMethod("GetStringValue", inParams, null);
        Console.WriteLine(outParams["sValue"]);
    }
}

How to read 64 bit registry from 32 bit application using WMI

When we work with 32 Application in a 64 bit machine to read registry value using WMI, we have to access the node WoW6432Node instead of normal registry path, but if the requested registry value not available in WoW6432Node and if it is only available in 64 bit registry path, then we have to force WMI to load the 64-bit provider and get value from 64-bit registry

Use the following C# code to access 64 bit registry hive information from a application running in 32 bit mode on a 64 bit machine(WOW). We need to add the __ProviderArchitecture and __RequiredArchitecture option in ManagementScope's ConnectionOptions to force WMI to load the 64-bit provider.
private static void Read64RegistryFrom32App()
{
    uint LOCAL_MACHINE = 0x80000002;
    ConnectionOptions options = new ConnectionOptions();
    options.Impersonation = ImpersonationLevel.Impersonate;
    options.EnablePrivileges = true;
    options.Username = "MyUsername";
    options.Password = "MyPassword";

    ManagementScope mgmtScope = new ManagementScope("\\\\" + "ComputerName" + "\\root\\default", options);
            
    mgmtScope.Options.Context.Add("__ProviderArchitecture", 64);
    mgmtScope.Options.Context.Add("__RequiredArchitecture", true);

    ManagementClass mc = new ManagementClass(mgmtScope, new ManagementPath("StdRegProv"), null);
    ManagementBaseObject inParams = mc.GetMethodParameters("EnumKey");
    inParams["hDefKey"] = LOCAL_MACHINE;
    inParams["sSubKeyName"] = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";

    ManagementBaseObject outParams = mc.InvokeMethod("EnumKey", inParams,null);
    inParams = mc.GetMethodParameters("GetStringValue");
    inParams["hDefKey"] = LOCAL_MACHINE;

    foreach (string name in (string[])outParams["sNames"])
    {
        inParams["sSubKeyName"] = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + "\\" + name;
        inParams["sValueName"] = "DisplayName";
        outParams = mc.InvokeMethod("GetStringValue", inParams, null);
        Console.WriteLine(outParams["sValue"]);
    }
}

Thursday, 25 February 2016

Get all site collections in SharePoint using PowerShell

There might be a need to get all site collections in all the web applications in SharePoint server. We can get all web applications by using the powershell cmdlet Get-SPWebApplication and then we can get a list of site collections under a particular web application using Get-SPSite cmdlet.

Before proceed, run the following command to add SharePoint PowerShell management snapin.
Add-PSSnapin Microsoft.SharePoint.PowerShell
The following PowerShell script list all site collections in a single web application. You have to change the $url value with your own webapplication url.
$url ='http://sharepoint_server:90/'
$Site= Get-SPSite $url         
$spWebApp = $Site.WebApplication
#Enumerate all site collections from webapplication
$spWebApp.Sites | Select-Object @{n="Name"; e={$_.RootWeb.Title}},Url,ContentDatabase | FL

Get all site collections in all web applications using PowerShell:

First, you need to get all web applications by using Get-SPWebApplication cmdlet and pipe the results to Get-SPSite cmdlet to get site collections for each and every web application. The following powershell script export all site collections in all web applications to CSV file.
Get-SPWebApplication | ForEach-Object {
$web = $_
$Site= Get-SPSite $web.Url -Limit All -ErrorAction SilentlyContinue       
if($Site)
{
$spWebApp = $Site.WebApplication
$spWebApp.Sites | ForEach-Object {
New-Object -TypeName PSObject -Property @{
             Name = $_.RootWeb.Title
             Url = $_.Url
             WebApplication= $web.Name
             Database = $_.ContentDatabase 
             CreationTime = $_.RootWeb.Created 
}}}} | Export-CSV "C:\\AllSiteCollections.csv" -NoTypeInformation -Encoding UTF8

Get all site collections in Web Application using PowerShell

As an Administrator, there might be a need to view all the site collections under a web-application in SharePoint. We can get a list of site collections in a particular web application using the Powershell cmdlet Get-SPSite.

Before proceed, run the following command to add SharePoint PowerShell management snapin.
Add-PSSnapin Microsoft.SharePoint.PowerShell
The following PowerShell script find and list all site collections details in a given web application. You have to change the $url value with your own webapplication url.
$url ='http://sharepoint_server:90/'
$Site= Get-SPSite $url         
$spWebApp = $Site.WebApplication
#Enumerate all site collections from webapplication
$spWebApp.Sites | Select-Object @{n="Name"; e={$_.RootWeb.Title}},Url,ContentDatabase | FL
You can also export the site collection details to csv file by using the powershell cmdlet Export-CSV.
$url ='http://sharepoint_server:90/'
$Site= Get-SPSite $url         
$spWebApp = $Site.WebApplication
#Enumerate site collections list from webapplication
$spWebApp.Sites | ForEach-Object {
 New-Object -TypeName PSObject -Property @{
             Name = $_.RootWeb.Title
             Url = $_.Url
             WebApplication= $web.Name
             Database = $_.ContentDatabase 
}} | Export-CSV "C:\\SiteCollections.csv" -NoTypeInformation -Encoding UTF8

Wednesday, 24 February 2016

Get list of all computers in AD using PowerShell

We can get a list of all computers in Active Directory using the Powershell cmdlet Get-ADComputer. The Get-ADComputer cmdlet supports SQL like filter and LDAP filter to filter AD computers. You can select any attribute that supported in Active Directory and it also supports Extended Properties like Enabled,LastLogonDate,etc...

Before proceed run the following command to import Active Directory module.
Import-Module ActiveDirectory
The following command find and list all the available computers in Active Directory.
Get-ADComputer -Filter * -Properties * |
 Select -Property Name,DNSHostName,Enabled,LastLogonDate

Export all AD Computers to CSV file:

You can also export the computer list to csv file by using the powershell cmdlet Export-CSV.
Get-ADComputer -Filter * -Properties * |
 Select -Property Name,DNSHostName,Enabled,LastLogonDate | 
 Export-CSV "C:\\AllComputers.csv" -NoTypeInformation -Encoding UTF8

Get all computers in OU:

We can also find and get a list of AD computers from particular OU by setting target OU scope by using the parameter SearchBase. The following powershell command select all AD computers from the Organization Unit 'TestOU' and export it to CSV file.
Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com" -Properties *  |
 Select -Property Name,DNSHostName,Enabled,LastLogonDate | 
 Export-CSV "C:\\AllComputersInOU.csv" -NoTypeInformation -Encoding UTF8

Apply SQL Like filter to get specific computers:

The Get-ADComputer cmdlet supports SQL like filter, users who are not familiar with LDAP filter can easily use this filter to get only specific set of AD computers. The following powershell commnd export all computers based on operatingSystem that contains the value 'Windows 7'.
Get-ADComputer -Filter 'operatingSystem -like "*Windows 7*"' -Properties * |
 Select -Property Name,DNSHostName,operatingSystem,LastLogonDate | 
 Export-CSV "C:\\Windows7Computers.csv" -NoTypeInformation -Encoding UTF8

Apply LDAP Filter to get specific computers:

If your are familiar with LDAP filter, instead of normal filter, you can also use LDAP filter in Get-ADComputer cmdlet with more flexibility to filter Active Directory computers. The following powershell commnd get list of computers based on operatingSystem that contains the value 'Windows 7'.
Get-ADComputer -LDAPFilter '(operatingSystem=*Windows 7*)'  -Properties * |
 Select -Property Name,DNSHostName,operatingSystem,LastLogonDate | 
 Export-CSV "C:\\Windows7Computers.csv" -NoTypeInformation -Encoding UTF8

Where is Microsoft.SharePoint.Client.Runtime.dll

When working with the managed client object model, we need to create a ClientContext class (in Microsoft.SharePoint.Client assembly) and use its Web or Site properties to access server side objects. This class is inherited from the abstract ClientRuntimeContext class (in Microsoft.SharePoint.Client.Runtime assembly). So, if you read the methods and properties of web or site, you should add the dll reference of Microsoft.SharePoint.Client.Runtime.dll.

But it is not installed by default in your machine, you need to download and install the SharePoint Server 2013 Client Components SDK from MSDN.

After the installation is done, you will find the dll in at the following location:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI

Where is Microsoft.SharePoint.Client.dll

When we work with the managed client object model (CSOM), we need to create a ClientContext class (in Microsoft.SharePoint.Client assembly) to access SharePoint Online sites and site collections. To use this class we should add the dll reference of Microsoft.SharePoint.Client.dll.

But it is not installed by default in your machine, you need to download and install the SharePoint Server 2013 Client Components SDK from MSDN.

After the installation is done, you will find the dll in at the following location:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI
You can also download directly from nuget packages : https://www.nuget.org/packages/Microsoft.SharePoint.Client.dll/

Tuesday, 23 February 2016

Where is the Microsoft.Online.SharePoint.Client.Tenant.dll ?

If you are working with CSOM to create a site collection or get list of all site collections in SharePoint Online, you need to use the class Tenant from Microsoft.Online.SharePoint.Client.Tenant.dll.

But it is not installed by default in your machine, you need to download and install the SharePoint Server 2013 Client Components SDK from MSDN.

After the installation is done, you will find the dll in at the following location:
C:\Program Files\SharePoint Client Components\Assemblies
You can also download directly from nuget packages : https://www.nuget.org/packages/Microsoft.Online.SharePoint.Client.Tenant.dll/

Get all site collections in SharePoint Online using PowerShell

In previous post, I have written C# code sample to get the list of all site collections in SharePoint Online using SharePoint's client object model (CSOM). In this article, I am going to write PowerShell script sample to retrieve all site collections in a SharePoint tenant.

Before proceed, you need to download and install the SharePoint Server 2013 Client Components SDK

The below powershell script get all sites collection from the given SharePoint tenant. You have to provide your own tenant url, admin username and password.
[Reflection.Assembly]::LoadFrom("C:\Sharepoint\CSOM\Microsoft.SharePoint.Client.dll")
[Reflection.Assembly]::LoadFrom("C:\Sharepoint\CSOM\Microsoft.Online.SharePoint.Client.Tenant.dll")

# Initialize client context
$adminURL = 'https://MyTenant-admin.sharepoint.com/'
$username = 'admin@MyTenant.onmicrosoft.com'
$password = 'MyPassword'
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($adminURL)
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username,$securePassword)
$clientContext.Credentials = $credentials

# Enumerate all site collections

$tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($clientContext)
  
$props = $tenant.GetSiteProperties(0, $true)
$clientContext.Load($props)
$clientContext.ExecuteQuery()
    
foreach($sp in $props)
{
       Write-Host 'Title:' $sp.Title
       Write-Host 'Url:' $sp.Url
       Write-Host '-----------------'
}

Monday, 22 February 2016

Get all sites and subsites in SharePoint Online using C#

We can easily get the list of all sites and sub sites of all site collections from a Office 365 tenant using SharePoint's client object model (CSOM) in C#. In this article, I am going to write C# code sample to retrieve all sites and sub sites in a SharePoint tenant and get all subsites for the given site url.

Before proceed, you need to download and install the SharePoint Server 2013 Client Components SDK and add the following dlls in your project reference.

- Microsoft.Online.SharePoint.Client.Tenant.dll
- Microsoft.SharePoint.Client.dll
- Microsoft.SharePoint.Client.Runtime.dll

The below C# code lists all sites and sub sites (nested sub sites) for all sites collections in the given SharePoint tenant. You have to provide your own tenant url, admin username and password.
private static void Get_AllSites_and_SubSites()
{
    SPOSitePropertiesEnumerable prop = null;

    var password = new SecureString();
    foreach (char c in "MyPassword".ToCharArray()) password.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@MyTenant.onmicrosoft.com", password);
    var ctx = new ClientContext("https://MyTenant-admin.sharepoint.com/");
    ctx.Credentials = credentials;

    Tenant tenant = new Tenant(ctx);
    prop = tenant.GetSiteProperties(0, true);
    ctx.Load(prop);
    ctx.ExecuteQuery();
    //#1 . Getting all site collections
    foreach (SiteProperties sp in prop)
    {
        Console.WriteLine("Site collection: " + sp.Title + " => " + sp.Url);
        Console.WriteLine("------------------------------------------------");
        var siteCtx = new ClientContext(sp.Url);
        siteCtx.Credentials = credentials;
        var web = siteCtx.Web;
        List allSites = new List();
        siteCtx.Load(web, w=>w.Webs, w => w.Title, w => w.Url);
        siteCtx.ExecuteQuery();
        //#2 . Adding first level site of the site collection
        allSites.Add(web);
        //#3 . Getting sub sites and all the nested sub sites
        GetSubSites(siteCtx, web.Webs, ref allSites);
        foreach (Web site in allSites)
        {
            Console.WriteLine("Site : " + site.Title + " => " + site.Url);
            Console.WriteLine("-------------------");
        }
    }
}

private static void GetSubSites(ClientContext siteCtx, WebCollection webs, ref List allSites)
{
    if (webs.Count > 0)
    {
        siteCtx.Load(webs, w => w.Include(a => a.Webs, a => a.Title, a => a.Url));
        siteCtx.ExecuteQuery();
        foreach (Web web in webs)
        {
            allSites.Add(web);
            GetSubSites(siteCtx, web.Webs, ref allSites);
        }
        siteCtx.ExecuteQuery();
    }
}

Get all sites and subsites for the given site url

The below C# CSOM code lists all sites and sub sites (nested sub sites) for the given SharePoint Online site url.
private static void Get_AllSites_and_SubSites_For_Given_Site(string siteUrl)
{
    var password = new SecureString();
    foreach (char c in "MyPassword".ToCharArray()) password.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@MyTenant.onmicrosoft.com", password);

    var siteCtx = new ClientContext(siteUrl);
    siteCtx.Credentials = credentials;
    var web = siteCtx.Web;
    List allSites = new List();
    siteCtx.Load(web, w => w.Webs, w => w.Title, w => w.Url);
    siteCtx.ExecuteQuery();
    allSites.Add(web);
    //Getting sub sites and all the nested sub sites
    GetSubSites(siteCtx, web.Webs, ref allSites);
    foreach (Web site in allSites)
    {
        Console.WriteLine(site.Title + " => " + site.Url);
        Console.WriteLine("-------------------");
    }
}

private static void GetSubSites(ClientContext siteCtx, WebCollection webs, ref List allSites)
{
    if (webs.Count > 0)
    {
        siteCtx.Load(webs, w => w.Include(a => a.Webs, a => a.Title, a => a.Url));
        siteCtx.ExecuteQuery();
        foreach (Web web in webs)
        {
            allSites.Add(web);
            GetSubSites(siteCtx, web.Webs, ref allSites);
        }
        siteCtx.ExecuteQuery();
    }
}

Friday, 19 February 2016

Get list of inactive mailboxes in office 365 using PowerShell

User's mailboxes will be unused when they leave organization. So, you have to find all the inactive mailboxes within your organization to take further action, like removing assigned license, deleting mailbox, etc... The following powershell script generate a list of all the users who have not logged in for at least 30 days using the Exchange Online powershell cmdlet Get-StaleMailboxDetailReport. From this information you can then take the appropriate action to remove unused mailboxes.

Note: In some cases the report may not provide a LastLogin date and mailboxes under a litigation hold may also appear in this report.

#1 Open Windows PowerShell as privileged user (Run as administrator) and run the following command and type your Office 365 admin user name and password, and then click OK.
$365Logon = Get-Credential
#2 Run the following command to connect exchange online powershell session.
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session
#3 Finally, run the below command to get a list of users inactive for 30 days.
Get-StaleMailboxDetailReport | SELECT UserName, LastLogin, DaysInactive
You can also export the inactive mailboxes to csv file by using the powershell cmdlet Export-CSV.
Get-StaleMailboxDetailReport | SELECT UserName, LastLogin, DaysInactive|
Export-CSV "C:\\Inactive_MailBoxes_Report.csv" -NoTypeInformation -Encoding UTF8

Get list of site collections with CSOM in SharePoint Online

We can easily get the list of all site collections from a Office 365 tenant using SharePoint's client object model (CSOM) in C#. In this article, I am going to write C# code sample to retrieve all site collections in a SharePoint tenant and get all site collection users and administrators.

Before proceed, you need to download and install the SharePoint Server 2013 Client Components SDK and add the following dlls in your project reference.

- Microsoft.Online.SharePoint.Client.Tenant.dll
- Microsoft.SharePoint.Client.dll
- Microsoft.SharePoint.Client.Runtime.dll

The below C# code retrieves all sites collection from the given SharePoint tenant. You have to provide your own tenant url, admin username and password.
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
// ---------------------------------
private static void GetAllSiteCollections()
{
    SPOSitePropertiesEnumerable prop = null;

    var password = new SecureString();
    foreach (char c in "MyPassword".ToCharArray()) password.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@MyTenant.onmicrosoft.com", password);
    var ctx = new ClientContext("https://MyTenant-admin.sharepoint.com/");
    ctx.Credentials = credentials;

    Tenant tenant = new Tenant(ctx);
    prop = tenant.GetSiteProperties(0, true);
    ctx.Load(prop);
    ctx.ExecuteQuery();
    foreach (SiteProperties sp in prop)
    {
        Console.WriteLine(sp.Title + " => " + sp.Url);
        Console.WriteLine("---------------------------");
    }
}

Get all site collection users and administrators

The above C# code only returns site collection information, to get site collection associated users and administrators, we need to load site users from site collection context and and execute the query again.
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
// ---------------------------------
private static void GetAllSiteCollectionsAndUsers()
{
    SPOSitePropertiesEnumerable prop = null;

    var password = new SecureString();
    foreach (char c in "MyPassword".ToCharArray()) password.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("admin@MyTenant.onmicrosoft.com", password);
    var ctx = new ClientContext("https://MyTenant-admin.sharepoint.com/");
    ctx.Credentials = credentials;

    Tenant tenant = new Tenant(ctx);
    prop = tenant.GetSiteProperties(0, true);
    ctx.Load(prop);
    ctx.ExecuteQuery();
    foreach (SiteProperties sp in prop)
    {                        
        var context = new ClientContext(sp.Url);
        context.Credentials = sp.Context.Credentials;
        var web = context.Web;
        context.Load(web, w => w.SiteUsers);
        context.ExecuteQuery();
                
        var admins = string.Join(";", web.SiteUsers.Where(u => u.IsSiteAdmin).Select(a => a.Title).ToList());
        var users = string.Join(";", web.SiteUsers.Where(u => !u.IsSiteAdmin).Select(a => a.Title).ToList());

        Console.WriteLine(sp.Title + " => " + sp.Url);
        Console.WriteLine("Administrators  => " + admins);
        Console.WriteLine("Users  =>  " + users);
        Console.WriteLine("---------------------------");
    }
}

Wednesday, 17 February 2016

Get Serial Number of a Remote Computer with PowerShell

The serial number can be useful to identify computer hardware for inventory purpose, which is often written on a small sticker in back side of the device. We can also get this serial number from the BIOS configuration. We can retrieve it using the Windows Management Instrumentation (WMI) class Win32_Bios.

The following command get a serial number of the current computer:
Get-WMIObject Win32_Bios | Select-Object SerialNumber

Get Serial Number of a Remote Computer:

You can pass the remote computer name with the paramater -ComputerName and get serial number of remote machine.
Get-WMIObject Win32_Bios -ComputerName 'remote-svr1' | Select-Object SerialNumber

Get Serial Number for a list of Remote Computers using PowerShell:

Use the below powershell script to find serial number for multiple remote computers. First create the text file computers.txt which includes one computer name in each line. You will get the machine name and serial number in the csv file SerialNumbers.csv.
Get-Content C:\computers.txt  | ForEach-Object{
$ser_number = (Get-WMIObject Win32_Bios -ComputerName $_ ).SerialNumber
if(!$ser_number){
$ser_number ="The server is unavailable"
}
New-Object -TypeName PSObject -Property @{
      ComputerName = $_
      SerialNumber = $ser_number
}} | Select ComputerName,SerialNumber |
Export-Csv C:\SerialNumbers.csv -NoTypeInformation -Encoding UTF8

Get Serial Number for a list of Remote Computers from CSV:

Use the below powershell script to to find serial number for multiple remote computers from csv file. First create the csv file computers.csv which includes the column ComputerName in the csv file. You will get the ComputerName and SerialNumber list in the csv file SerialNumbers.csv.
Import-Csv C:\computers.csv | ForEach-Object{
$ser_number = (Get-WMIObject Win32_Bios -ComputerName $_.ComputerName).SerialNumber
if(!$ser_number){
$ser_number ="The server is unavailable"
}
New-Object -TypeName PSObject -Property @{
      ComputerName = $_.ComputerName
      SerialNumber = $ser_number
}} | Select ComputerName,SerialNumber |
Export-Csv C:\SerialNumbers.csv -NoTypeInformation -Encoding UTF8

System.Data.OleDb.OleDbException: IErrorInfo.GetDescription failed with E_FAIL(0x80004005)

I am getting this error 'System.Data.OleDb.OleDbException: IErrorInfo.GetDescription failed with E_FAIL(0x80004005)' while running the below MS Access select query:
Select Title, Address, Size, LastModifiedDate From MyTable

Solution:

The problem is due to the Reserved keyword Size. The problem solved after changed the query by enclosing the Reserved keyword with square brackets ([])
Select Title, Address, [Size], LastModifiedDate From MyTable

Tuesday, 16 February 2016

Add Site Collection Administrator in Sharepoint Online using Powershell

By default, the user who is owner of the site collection is the only person who has site collection admin rights on it. This can be a problem for compliance and e-discovery reasons. You might be in a situation where you need to give site collection admin rights to a compliance manager or a global administrator. In this article, I am going to write PowerShell script to set a Site Collection administrator in Sharepoint Online/Office 365 using CSOM library.

Before proceed, you need to download the SharePoint Server 2013 Client Components SDK. Adjust the path of reference Assembly as necessary in below script.

Replace the following variables with your own values:
  • $siteUrl
  • $siteAdmin
  • $siteAdminPwd
  • $newAdmin
[Reflection.Assembly]::LoadFrom("C:\Sharepoint\CSOM\Microsoft.SharePoint.Client.dll")
[Reflection.Assembly]::LoadFrom("C:\Sharepoint\CSOM\Microsoft.SharePoint.Client.Runtime.dll")
 
$siteUrl = “https://mts.sharepoint.com/sites/MySiteCollection” 
$siteAdmin = "admin@mts.onmicrosoft.com" 
$siteAdminPwd ='MyPa@@word';
$password = New-Object System.Security.SecureString;
$siteAdminPwd.ToCharArray() | ForEach-Object {$password.AppendChar($_)};
  
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)  
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($siteAdmin, $password)  
$ctx.Credentials = $credentials 

$newAdmin = 'morgan@mts.onmicrosoft.com'
$spUser = $ctx.Web.EnsureUser($newAdmin); 
$spUser.IsSiteAdmin = $true; 
$spUser.Update();
 
$ctx.Load($spUser) 
$ctx.ExecuteQuery()
Note: An existing site collection administrator can alone add another administrator.

Sunday, 14 February 2016

Litigation Hold vs In Place Hold in Office 365

Litigation Hold allow customers to immutably preserve mailbox content to meet long term preservation and eDiscovery requirements. When a mailbox was placed on Litigation Hold, mailbox content was preserved indefinitely.

In-Place Hold was introduced to allow more flexibility in preserving your data. It allowed you to preserve items matching your query parameters, known as a query-based In-Place Hold, preserve items for a specified period, known as a time-based In-Place Hold, and also preserve everything indefinitely as same as the Litigation Hold feature

For more information, see this article: Exchange Online Service Description under “In-Place Hold and Litigation Hold”.

In Exchange Online, you can use In-Place Hold or Litigation Hold to accomplish the following goals:
  • Enable users to be placed on hold and preserve mailbox items immutably
  • Preserve mailbox items deleted by users or automatic deletion processes such as MRM
  • Protect mailbox items from tampering, changes by a user, or automatic processes by saving a copy of the original item
  • Preserve items indefinitely or for a specific duration
  • Keep holds transparent from the user by not having to suspend MRM
  • Use In-Place eDiscovery to search mailbox items, including items placed on hold

Additionally, you can use In-Place Hold to:

  • Search and hold items matching specified criteria
  • Place a user on multiple In-Place Holds for different cases or investigations

Saturday, 13 February 2016

Get list of Office 365 licenses using Powershell

Every Office 365 subscription includes different type of license plans, you can list all the available license plans (SKU ID’s) in your tenant by using the powershell cmdlet Get-MsolAccountSku.

Note: Before proceed, Install and Configure Azure AD PowerShell

The below command lists all the licenses that part of your tenant subscription, it includes no. of allowed users (ActiveUnits) and how many no. of licenses assigned to users (ConsumedUnits). So, from this result, you can conclude that how many no. of license units are available to assign new users.
Get-MsolAccountSku | Select AccountSkuId,SkuPartNumber,ActiveUnits,ConsumedUnits
The above command lists all the license plans, the plan itself includes a bundle of services. Use the following command to see the available services (sub plans). You have to get the value of SkuPartNumber from the output of above command.
$plan = Get-MsolAccountSku | Where {$_.SkuPartNumber -eq "ENTERPRISEPACK"}
$plan.ServiceStatus
I have got the below output for my license plan "ENTERPRISEPACK".
ServicePlan                                                 ProvisioningStatus
-----------                                                 ------------------
SWAY                                                        PendingActivation
INTUNE_O365                                              PendingActivation
YAMMER_ENTERPRISE                                      Success
RMS_S_ENTERPRISE                                        Success
OFFICESUBSCRIPTION                                     Success
MCOSTANDARD                                               Success
SHAREPOINTWAC                                            Success
SHAREPOINTENTERPRISE                                  Success
EXCHANGE_S_ENTERPRISE                                Success
You can refer this article: Manage Office License to assign/remove/update license and license options.

Getting license status is also one of the important task for every admin to check whether a specified license is active or expired. You can use the powershell cmdlet Get-MsolSubscription to get license status of all the available licenses.

The following command lists all the license subscriptions:
Get-MsolSubscription | Select SkuPartNumber, Status, TotalLicenses
SkuPartNumber: The SKU associated with this subscription.

Status: The status of this subscription (Enabled, Expired, or Suspended).

TotalLicenses: The number of seats included in this subscription.

Thursday, 11 February 2016

Add-Type : Unable to load one or more of the requested types

I have a .NET assembly (a dll) to load Sharepoint Online information. I am trying load this assembly in powershell using Add-Type command.
Add-Type -Path "C:\SharepointCSMO\Microsoft.SharePoint.Client.dll" 
But, I am receiving the error 'Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information'.
Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
At line:1 char:9
+ Add-Type <<<<  -Path "C:\SharepointCSMO\Microsoft.SharePoint.Client.dll"
+ CategoryInfo          : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
+ FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeCommand
Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Solution:

For me, I can able to load the same assembly using reflection:
[System.Reflection.Assembly]::LoadFrom("C:\SharepointCSMO\Microsoft.SharePoint.Client.dll")
If your assembly placed in Global Assembly Cache (GAC). You can use the method .LoadWithPartialName(), which allows you to use just that part of the “full name” that most of us would consider the name.
[System.Reflection.Assembly]::LoadWithPartialName("Windows.Forms")
For more details, you can also refer following articles:

http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html
http://serverfault.com/questions/455163/how-to-properly-add-net-assemblies-to-powershell-session 
http://stackoverflow.com/questions/24906392/issue-loading-in-different-assemblies-to-powershell

Wednesday, 10 February 2016

What is DataStore.edb and is it safe to delete?

What is DataStore.edb?:

The DataStore.edb file is some kind of log file, it keeps the history of Windows updates and it is located under SoftwareDistribution folder (C:\Windows\SoftwareDistribution\DataStore\DataStore.edb). Its size will grow for every Windows Update check.

Is it safe to delete?:

Yes, it is safe to delete, but the next time when Windows checks for updates, it will basically start from scratch and check everything. There's no point in deleting DataStore.edb since it will just be rebuilt the next time Windows checks for updates. If you are just looking for stuff to delete you can empty the SoftwareDistribution\Download folder.

You can also refer following links for more information: 

http://superuser.com/questions/539411/pc-boots-then-writes-giant-datastore-edb-file-slowing-the-computer-down
https://in.answers.yahoo.com/question/index?qid=20110218143222AA4lzw4 http://juneyourtech.blogspot.com/2013/06/datastoreedb-and-windows-vista.html

Permanently Delete a User in Office 365 using powershell

When you delete users in Office 365 admin Portal, these deleted users are moved to the Recycle Bin where they will be retained for another 30 days before that user is permanently deleted. In the Office 365 admin portal, it is not possible to permanently remove users or purge deleted user accounts. However, you can do it through remote powershell.

Note: Before proceed, Install and Configure Azure AD PowerShell

Use the following command to connect the Azure Active Directory:
Connect-MsolService
Use the following command to retrieve a list of all deleted users. This command will list all the users that are currently stored in the Recycle Bin folder, and have not deleted permanently because 30 days have not passed since they were moved to this folder.
Get-MsolUser –ReturnDeletedUsers
Once you get the deleted users list, you can decide certain users to delete permanently from this list and you can use the cmdlet Remove-MsolUser to remove a specific deleted user with the parameter -RemoveFromRecycleBin.
Remove-MsolUser -UserPrincipalName mike@mts.onmicrosoft.com -RemoveFromRecycleBin -Force
You can remove all the deleted users by fetching all deleted users using Get-MsolUser cmdlet and pipe the output to Remove-MsolUser.
Get-MsolUser -ReturnDeletedUsers | Remove-MsolUser -RemoveFromRecycleBin -Force
You can also filter the deleted users with specific criteria and remove those users permanently.
Get-MsolUser -ReturnDeletedUsers | Where-Object { $_.Department -like '*DevTeam*'} | 
Remove-MsolUser -RemoveFromRecycleBin -Force

Tuesday, 9 February 2016

What Is an Offline Storage Table (OST) File?

An OST file, or offline storage table (.ost) file, is an offline Outlook Data File used by Microsoft Exchange Server that enables users to work with their messages and mail data even when access to the mail server isn't available. OST files are used in two scenarios: with Microsoft Exchange Server’s Cached Exchange Mode and with the Outlook Connector for Windows Live Hotmail when accessing Hotmail mail.

There are two types of Outlook Data Files used by Outlook. A Personal Storage Table (.pst) is used for most accounts. If you are using a Microsoft Exchange account, your items are usually delivered to and saved on the mail server. To allow you to work with your messages even when you can’t connect to the mail server, a second type of data file that is named an offline Outlook Data File (.ost) is kept on your computer.

The primary differences between the two types of Outlook data files are as follows:

Personal Storage Table (.pst) files are used for POP3, IMAP, and web-based mail accounts. When you want to create archives or back up your Outlook folders and items on your computer, such as Exchange accounts, you must create and use additional .pst files.

Offline Storage Table (.ost) files are used when you have an Exchange account and want to work offline or use or use the default Cached Exchange Mode. This type of data file is also used for accounts that you set up with the Outlook Connector for Outlook.com (formerly Hotmail). Outlook Data Files (.ost) are always copies of items that are saved on a mail server and don’t have to be backed up like Outlook Data Files (.pst).

Monday, 8 February 2016

Get all Licensed Office 365 users with PowerShell

It is very common requirement to get all the licensed users within an Office 365 tenant. We can use the Azure AD powershell cmdlet Get-MsolUser to list all the licensed office 365 users.

Note: Before proceed, Install and Configure Azure AD PowerShell

The following command just list the licensed office 365 users
Get-MsolUser -All | Where-Object { $_.isLicensed -eq ”TRUE” } | Select-Object UserPrincipalName, DisplayName, Department
The following command exports all the licensed users to csv file
Get-MsolUser -All | Where-Object { $_.isLicensed -eq ”TRUE” } | Select-Object UserPrincipalName, DisplayName, Department | Export-Csv C:\LicensedUsers.csv  -NoTypeInformation -Encoding UTF8
The above command just tell whether an user is licensed or not, doesn't list what kind of license has been applied to the users. The following powershell script get the detailed license plans and subscriptions that applied to every office 365 users and exports the output to csv file by using Export-CSV cmdlet.
$users = Get-MsolUser -All | Where-Object { $_.isLicensed -eq ”TRUE” }
$users | Foreach-Object{ 
  $licenseDetail = '' 
  $licenses='' 
  if($_.licenses -ne $null) {
ForEach ($license in $_.licenses){
  switch -wildcard ($($license.Accountskuid.tostring())) { 
           '*POWER_BI_STANDALONE' { $licName = 'POWER BI STANDALONE' } 
           '*CRMSTANDARD' { $licName = 'CRM Online' }
           '*O365_BUSINESS_PREMIUM' { $licName = 'Office 365 BUSINESS PREMIUM' } 
           '*ENTERPRISEPACK' { $licName = 'Office 365 (Plan E3)' }  
           default { $licName = $license.Accountskuid.tostring() }
        }         

  if($licenses){  $licenses = ($licenses + ',' + $licName) } else { $licenses = $licName}
ForEach ($row in $($license.servicestatus)) {

if($row.ProvisioningStatus -ne 'Disabled') {          
       switch -wildcard ($($row.ServicePlan.servicename)) { 
           'EXC*' { $thisLicence = 'Exchange Online' }  
           'LYN*' { $thisLicence = 'Skype for Business' } 
           'SHA*' { $thisLicence = 'Sharepoint Online' }       
           default { $thisLicence = $row.ServicePlan.servicename }  
       }         
 if($licenseDetail){ $licenseDetail = ($licenseDetail + ',' + $thisLicence) }  Else { $licenseDetail = $thisLicence}}
}}}
New-Object -TypeName PSObject -Property @{    
    UserName=$_.DisplayName  
    IsLicensed=$_.IsLicensed 
    Licenses=$licenses 
    LicenseDetails=$licenseDetail }
}  | Select UserName,IsLicensed,Licenses,LicenseDetails |
Export-CSV "C:\\Office-365-User-License-Report.csv" -NoTypeInformation -Encoding UTF8

Monday, 1 February 2016

Office 365: Get-MsolUser

The Get-MsolUser cmdlet is an Azure AD powershell cmdlet. It can be used to get an individual user, or list of users information. An individual user will be retrieved if the ObjectId or UserPrincipalName parameter is used.

Note: Before proceed, Install and Configure Azure AD PowerShell

Retrieve single user:
Get-MsolUser -ObjectId <Guid>
-------------or---------------
Get-MsolUser -UserPrincipalName <UserPrincipalName>
Retrieve all users:
Get-MsolUser -All

Example 1

The following command retrieves all users in the company (up to 500 results).
Get-MsolUser

Example 2

The following command retrieves only first 100 users in the company.
Get-MsolUser -MaxResults 100

Example 3

The following command retrieves all the available users in the company.
Get-MsolUser -All

Example 4

The following command retrieves all the deleted users in the company.
Get-MsolUser -All -ReturnDeletedUsers

Example 5

The following command retrieves the user with the UPN morgan@mts.com
Get-MsolUser -UserPrincipalName morgan@mts.com

Example 6

The following command retrieves all the licensed users
Get-MsolUser -All | Where-Object { $_.isLicensed -eq "TRUE" }

Example 7

The following command retrieves and export all the licensed Office 365 users to csv file.
Get-MsolUser | Where-Object { $_.isLicensed -eq "TRUE" } | Select DisplayName,UserPrincipalName,IsLicensed |
Export-Csv c:\LicensedUsers.csv -NoTypeInformation

Example 8

The following command retrieves all users based on Department filter.
Get-MsolUser -All | Where { $_.Department -like "*Sales*" -or $_.Department -eq "Marketing" } |
Select DisplayName,UserPrincipalName,Department,IsLicensed

Example 9

The following command retrieves and export all the users with when they last changed their passwords in Office 365 to csv file.
Get-MsolUser -All | select DisplayName,UserPrincipalName, LastPasswordChangeTimeStamp | 
Export-CSV C:\LastPasswordChange_Report.csv -NoTypeInformation