Wednesday, February 10, 2016

Get all sites where a feature is activated or deactivated

Get list of webs where either feature activated or deactivated in SharePoint at different scopes like web, site collection, web application and farm.

Below PowerShell script will provide list of webs(sub site including top level site) where specified feature is installed and not activated in particular site collection

Get-SPSite "http://kmsnet:5050"| Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -eq $null} | Select Url


Below script will provide list of webs(sub sites including toplevel site) where specified feature is installed and activated.

Get-SPSite "http://kmsnet:5050"| Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -ne $null} | Select Url

Note: If the feature object is null then those web(s) considered that feature is installed and not activated. If it is not-null then feature is installed and activated on the web.

Below PowerShell script will provide list of webs(sub sites including top level site) where specified feature is installed and not activated in all site collections from current SharePoint Farm

Get-SPSite –Limit All | Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -eq $null} | Select Url


Below script will provide list of webs(sub sites including toplevel site) where specified feature is installed and activated in all site collections from current SharePoint Farm.

Get-SPSite –Limit All | Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -ne $null} | Select Url

Below PowerShell script will provide list of webs(sub sites including top level site) where specified feature is installed and not activated in all site collections from specified web application

Get-SPWebApplication “http://kmsnet:5050” |Get-SPSite –Limit All | Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -eq $null} | Select Url

Below script will provide list of webs(sub sites including toplevel site) where specified feature is installed and activated in all site collections from specified web application.

Get-SPWebApplication “http://kmsnet:5050” |Get-SPSite –Limit All | Get-SPWeb -Limit All | Where-Object { (Get-SPFeature "12f73b57-1db8-4272-3d45-d8c1cc9f3d41" -ErrorAction SilentlyContinue -Web $_.Url) -ne $null} | Select Url

Monday, January 25, 2016

Find Process Identifier (PID) for Application Pool

Developers and system administrators must know to find out the correct PID associated with application pool if multiple web sites are running different app pools on the same server. PID is more important when Administrator troubleshoots an issue/worker process or developers debug the code by attaching the correct W3WP process with visual studio.

There are four common methods available to find out the Process Identifier for application pool.
1. Using IIS user interface
2. Using Command prompt
3. Using Task manager
4. Using Process Viewer


Method 1: Using IIS User Interface


1. Open IIS
2. Select Server from Connection Tree
3. Select Features Tab
4. Double click on Worker Process available under IIS section
5. Find the application pool name and Process identifiers in tabular view


Method 2: Using Command Prompt

iisapp.vbs script needs to be used to retrieve the correct PID from IIS6 and Windows 2003 server. Find the details in below snapshot.

C:\Windows\System32>script iisapp.vbs

Command “appcmd” need to be used on IIS7 or above and Windows 2008 server or above to retrieve the correct PID details from server. The “appcmd” command had to be executed by passing additional parameters “list” and “wps”. Find the details in below snapshot.


Go to c:\Windows\system32\inetsrv>appcmd list wps

Method 3: Using Command Prompt
1. Open Task Manager
2. Go to Process Tab
3. Go to View menu and client on Select columns
4. Add PID(Process Identifier) and Command line
5. Click OK
6. Find the PID and application pool details in the updated view




Thursday, January 14, 2016

Activate Web (subsite) scoped feature in all existing sites and subsites using PowerShell


We ware asked to enable a new rule that site/sub site cannot be deleted if any document declared as record. Of course I have added  new web deleting event receiver and used a web scoped feature to register the event on web.

But we have more than 100000 sub sites in our SharePoint farm. And enabling web scoped feature for all existing sites became a risk and performance hit.

I had created two scripts to resolve this issue. 1. PS script to collect all site collection from a web application and store it in a XML file. 2. PS script will read the XML file and process the site collection one by one as we got a provision to pass number site to be processed at one time. It reduced the performance hit and trace issue if any feature failed to activate

PowerShell script to Fetch All Site Collection:

# This script to generate XML file which contains all site collections in web application

# .\1_GetsiteCollections.ps1 -url "http://kmsnet:5500/" 



param
(
[string]$url   # Web application URL

)

If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction Stop) -eq $null )  
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell } 

#Start-Transcript
if($url)
{

[string]$filepath = $(get-location).Path;
# XML file generation code 
$ErrorActionPreference = "SilentlyContinue"
#$ErrorActionPreference = "Stop"

# Create a new XML File with config root node
[System.XML.XMLDocument]$oXMLDocument=New-Object System.XML.XMLDocument

# New Node
[System.XML.XMLElement]$oXMLRoot=$oXMLDocument.CreateElement("SiteCollection")
# Append as child to an existing node
$oXMLDocument.appendChild($oXMLRoot)
    $site = get-spsite $url
    $WebApp = $site.webapplication 
    $Count =0;
    try
    {
   foreach ($spsite in $WebApp.sites) 
   {
            [System.XML.XMLElement]$oXMLSystem=$oXMLRoot.appendChild($oXMLDocument.CreateElement("site"))
            $Count +=1;
       $oXMLSystem.SetAttribute("Count",$($Count))
       $oXMLSystem.SetAttribute("URL",$($spsite.Url))
            $oXMLSystem.SetAttribute("GUID",$($spsite.ID))
            $oXMLSystem.SetAttribute("Status","New")
                        
        }
        
        $xmlPath=$filepath + "\SiteCollXML";
        New-Item -force -ItemType directory -Path $xmlPath;
        $Filename = $filepath + "\SiteCollXML\SiteURL.xml"
        $oXMLDocument.Save($Filename )
        Write-host " Site collection file is generated : " $Filename
        
    }
     catch
    {
       # $Error; 
        $ErrorMessage = $_.Exception.Message
        write-host $ErrorMessage 


        $FailedItem = $_.Exception.ItemName
        write-host $FailedItem 
        
    }

}
else
{
Write-host "Please provide the Web Application Url...!!!" -foregroundcolor "Yellow"
}

PowerShell Script to process each site collection.

# .\2_EnableWebScopedFeature.ps1 -count 5 -Enable Y -FeatureId "12f73b57-1db8-4272-9d95-d8c1cc9f3d41"

param
(
    
    [int]$count =$(throw "Count is mandatory, please provide a value."), # No. of site collections to be processed
    [string]$Enable =$(throw "Pass y/Y to Activate the feature else pass n/N to deactivate the deature"),
    [string]$FeatureId =$(throw "Pass feature Id")
    
 )



Start-Transcript

If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction Stop) -eq $null )  
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell } 

write-host "Successfully added SharePoint PowerShell snapins"

#$ErrorActionPreference = "Stop"
$ErrorActionPreference = "SilentlyContinue"
$curDir=$(get-location).Path;
$LogTime = Get-Date -Format yyyy-MM-dd_h-mm  
$LogFile = $curDir + "\Logs1-$LogTime.txt"  
$DocIDFile = $curDir + "\Log2-$LogTime.txt"  
write-host "Log file Location : " $LogFile


$filePath = $curDir + "\SiteCollXML\SiteURL.xml"

#write-host "source XMl file Path is $filePath "
write-host " Doc Id file " $DocIDFile 


$SiteCollectionsXML = [xml](gc $filePath)
try
{
    write-host "$count number of site collection requested to process";
    $currentcount = 0
    $DocIDcount = 0

$SiteCollectionsXML = [xml](gc $filePath)
$newItems=$SiteCollectionsXML.SiteCollection.site | where { $_.Status -eq "New"} 
    $node="";
    foreach ($sColl in $newItems)
  {
      if ([int]$currentcount -lt $count)
            {
        write-host "Start: Site Collection ";
        
        try
        {
        $currentcount = $currentcount + 1
         $node = $SiteCollectionsXML.SiteCollection.site | where {$_.GUID -eq $sColl.GUID}   
        $node.Status = "New"
        $objsite = Get-SPSite $sColl.URL;
        if($Enable -eq "Y" -and $Enable -eq "y")
        {
        $objsite | Get-SPWeb -limit all | ForEach-Object {Enable-SPFeature -Identity $FeatureId -Url $_.Url -Confirm:$false -ErrorAction:SilentlyContinue -Force}
        $node.Status = "Feature Activated"
        }
        
        if($Enable -eq "N" -and $Enable -eq "n")
        {
        $objsite | Get-SPWeb -limit all | ForEach-Object {Disable-SPFeature -Identity $FeatureId -Url $_.Url -Force -Confirm:$false -ErrorAction:SilentlyContinue}
        $node.Status = "Feature Dectivated"
        }
        
        $objsite.Dispose();
        
              
        
         
        }
        catch
        {
        $ex = $_.Exception 
        $node.Status = "Failed to Activate: $ex.Message" 
        Write-Error "Error on $siteURL details: $ex.Message" 
continue 
        
        }
        finally
        {
        $objsite.Dispose();
        $SiteCollectionsXML.Save($filePath);
        }
        
          }
    }
        $SiteCollectionsXML.Save($filePath)
}
catch
{
       
    $ErrorMessage = $_.Exception.Message
    write-host $ErrorMessage 

    $FailedItem = $_.Exception.ItemName
    write-host $FailedItem 
       
    $node = $SiteCollectionsXML.SiteCollection.site | where {$_.GUID -eq $Guid}
    $node.Status = "Error"

    Add-Content -path $LogFile -value ("`n" + "Site URL : " + ($SiteCollectionUrl)  + ' Site GUID : ' + ($Guid) + ' Error: ' + ($ErrorMessage) )

    $SiteCollections.Save($filePath)

}

Stop-Transcript

XML Output

<SiteCollection>
  <site Count="1" URL="http://kmsnet:5500" GUID="870c5dbb-c1b8-417a-89b3-c428369b7e45" Status="Feature Activated" />
  <site Count="2" URL="http://kmsnet:5500/SC1/" GUID="888b3fd3-48a1-41c5-b1c9-bd5b9102b29f" Status="Feature Activated" />
  <site Count="3" URL="http://kmsnet:5500/SC2" GUID="9f6f0d3b-1e02-42e0-8fbd-070b298576dc" Status="Feature Activated" />

</SiteCollection>
 
 
 

Tuesday, December 29, 2015

Set value to an Managed Metadata field


Managed Metadata is an extraordinary feature in SharePoint career path. It helps organization to structure all unstructured data and it is easy to use them.

The managed metadata field can be associated with List, document library.. etc

Also it has a feature that not used values(terms) can be deprecated instead deleting them permanently from centralized location. The deprecated terms can be used for future tracking. Normally if any MMD field associated with a TermSet then user can see only Enabled terms in the TermStore tree. It is a out-of-the-box feature that SharePoint will apply filter and display only enabled terms to the end user.

But deprecated term also can be assigned to a MMD field if necessary based on business need using Server Object model.

Find the code sample below which assign value to MMD field with enabled and deprecated term.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;

namespace SetMMD_Field {

    class Program {
        static void Main(string[] args) {
            SPList lst = null; ;
            
            using (SPSite site = new SPSite(@"http://kmstechs/")) {
                using (SPWeb web = site.RootWeb) {
                  //  SPSecurity.RunWithElevatedPrivileges(delegate() {
                        lst = web.Lists["SK_Test"];
                        SPListItem oSPListItem = lst.Items.Add();
                        oSPListItem["Title"] = "Hello SharePoint";
                        TaxonomySession session = new TaxonomySession(site);

                        TaxonomyField taxfield = oSPListItem.Fields["Invalid_MMD"] as TaxonomyField;

                        Term InvalidTerm = session.GetTerm(new Guid(@"7dba48a0-89fa-4203-a265-e49ca3752ab7"));
                        string taxFieldInternalname1 = oSPListItem.Fields["Invalid_MMD"].InternalName;
                        oSPListItem[taxFieldInternalname1] = InvalidTerm.Name + "|" + InvalidTerm.Id.ToString();
                        taxfield.SetFieldValue(oSPListItem, InvalidTerm);

                        TaxonomyField taxfield2 = oSPListItem.Fields["Valid_MMD"] as TaxonomyField;

                        Term validTerm = session.GetTerm(new Guid(@"dca67b77-e4f4-4630-8785-e22518945ecc"));
                        string taxFieldInternalname2 = oSPListItem.Fields["Valid_MMD"].InternalName;
                        oSPListItem[taxFieldInternalname2] = validTerm.Name + "|" + validTerm.Id.ToString();
                        taxfield2.SetFieldValue(oSPListItem, validTerm);

                        oSPListItem.Update();

                   // });
                }
            }

            Console.WriteLine("done");

            Console.ReadKey(true);
        }
    }
}

Enjoy working with SharePoint :-)

Monday, December 21, 2015

Add more properties (metadata) to SharePoint Folder

Add more properties (metadata) to SharePoint Folder

Folder is an content type in SharePoint and it being used for categorizing OR grouping specified items/documents OR Applying Explorer view on SharePoint contents.  The folder content type provide explorer view if user wanted to navigate an document among many.

But the Folder content type is sealed in SharePoint and it will not allow the administrator to amend folder’s properties. Instead we can create a new custom content type by inheriting base folder content type and add new properties that are needed.

Below are the steps to create new folder content type with additional properties (metadata)


  1. Login to the  SharePoint site where you need folder with additional properties
  2. Navigate to Site Actions -->  Site Settings
  3. Click on Site Content Types
  4. Click on Create link
  5. Enter new content type name 
  6. Set the parent content type group as “Folder Content Types”
  7. Set the parent content type to “Folder”
  8. Provide new group name for new content type. Or else the new content type will be displayed under Custom content type group.
  9. Click OK button
  10. Click on New column and provide the column details 
  11. Add the custom content type where ever you need and update the views with new folder properties.

Note: Make sure allow custom content type option is enabled in the document library advances settings to add custom content type.


Wednesday, May 13, 2015

SharePoint 2013 server is not allowing 32bit application

I got a task to setup SharePoint 2013 production environment. Simply I was told by customer that we need SharePoint 2013 setup in single server with Search and Excel services.  I have download AuthoSPInstaller from here and updated the configuration values as per customer need. The AutoSPIntstaller reduce most of my time on installing pre-requisites and SharePoint installation. I will write all in details in separate post.

Post SharePoint 2013 installation, Customer is happy with the configuration and they started using all SharePoint 2013 features. After a week of time customer planned to use same SharePoint server to deploy some 32bit .Net web services. But the deployment was not successful as the SharePoint server not to ready allow any 32bit application.

The issue reported to me then I have investigated the issue and found the problematic place. The global module web config does not have any  property to allow 32bit application. At same time I found some more 32bit related error in event viewer.

The Module DLL 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\isapi\spnativerequestmodule.dll' could not be loaded due to a configuration problem. The current configuration only supports loading images built for a x86 processor architecture. The data field contains the error number. To learn more about this issue, including how to troubleshooting this kind of processor architecture mismatch error, see http://go.microsoft.com/fwlink/?LinkId=29349.

New ISAPI module in SharePoint 2013 stopping our 32 site from loading. Probably part of the new Request Management piece in SP2013 (http://blogs.technet.com/b/speschka/archive/2012/09/14/working-with-request-manager-in-sharepoint-2013.aspx)

I  have verified global section in “ ApplicationHost.config” file which present at %systemroot%\system32\inetsrv\config

Alternatively command prompt can be used list global module section from “ ApplicationHost.config”

  1. Open command prompt
  2. Change directory to %systemroot%\system32\inetsrv (e.g. c:\windows\system32\inetsrv)
  3. Used below command to list all config details.

         appcmd list config  /section:globalmodules

Check the property in SharePoint Native Request Module

< add name="SPNativeRequestModule" image="C:\Program Files\Common Files\Micro
soft Shared\Web Server Extensions\15\isapi\spnativerequestmodule.dll" />

If precondition property not available then update property using below command to enable the server to allow 32bit application.

appcmd.exe set config -section:system.webServer/globalModules /[name='SPNativeRequestModule'].preCondition:integratedMode,bitness64

Once the above command executed successfully then the property of SharePoint Native Request Module will be updated as below.

   
< add name="SPNativeRequestModule" image="C:\Program Files\Common Files\Micro
soft Shared\Web Server Extensions\15\isapi\spnativerequestmodule.dll" preConditi
on="integratedMode,bitness64" />  

Restart the server and verify 32 bit application.

Good luck :-)





Tuesday, May 5, 2015

Retrieve Secure Store Service credentials in SharePoint 2010/13


There are some actions to be taken care manually in SharePoint 2010/13. If any service account password is updated then the same password can be updated using managed accounts which get updated in all the places in same SharePoint Farm. But if SharePoint using any services from other farm then the password will not be updated and create new issue while access the service from other farms.

The account details will be stored in secure store services. To update the new password, SharePoint Administrator should aware or refer any document to find services and currently using credentials. SharePoint 2010 service application does not have any user interface to identify those details quickly. In such case below PowerShell script can be used.

$serviceCntx = Get-SPServiceContext -Site http://kmsnet:12345/
$sssProvider = New-Object Microsoft.Office.SecureStoreService.Server.SecureStoreProvider
$sssProvider.Context = $serviceCntx
$marshal = [System.Runtime.InteropServices.Marshal]

try
{
$applicationlications = $sssProvider.GetTargetApplications()
foreach ($application in $applicationlications)
{
Write-Output "`n$($application.Name)"
Write-Output "$('-'*50)"
try
{
$sssCreds = $sssProvider.GetCredentials($application.Name)
foreach ($sssCred in $sssCreds)
{
$ptr = $marshal::SecureStringToBSTR($sssCred.Credential)
$str = $marshal::PtrToStringBSTR($ptr)
Write-Output "$($sssCred.CredentialType): $($str)"
}
}
catch
{
Write-Output "(Something went wrong) - Error getting credentials!"
}
Write-Output "$('-'*50)"
}
}

catch
{
Write-Output "(Something went wrong) - Error getting Target Applications."
}

$marshal::ZeroFreeBSTR($ptr)