Tuesday, March 28, 2023

Powershell script to export all SEWP and CEWP content to CSv and text files

A working example to export all script editors and content editors content from an on-prem site collection. Handy for a SharePoint onprem to online migration project 


Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

 

#Configuration parameters

$webApp = Get-SPWebApplication "http://yourwebappurl"


$csvFile = "<path to export folder>\pageswitheditors.csv"


$SiteURL = "http://yoursitecollurl"

$ReportOutput="<path to export folder>\pageswitheditors.csv"

 

$ResultCollection = @()

 

#Get All Subsites in a site collection and iterate through each

$Site = Get-SPSite $SiteURL

$counter=0;

ForEach($Web in $Site.AllWebs)

{

    write-host Processing $Web.URL

    # If the Current Web is Publishing Web

    if ([Microsoft.SharePoint.Publishing.PublishingWeb]::IsPublishingWeb($Web))

    {

        #Get the Publishing Web

        $PubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($Web)

                   

        #Get the Pages Library

        $PagesLib = $PubWeb.PagesList

     }

     else

     {

        $PagesLib = $Web.Lists["Site Pages"]

     }            

        #Iterate through all Pages 

        foreach ($Page in $PagesLib.Items | Where-Object {$_.Name -match ".aspx"})

        {

            $PageURL=$web.site.Url+"/"+$Page.File.URL

            $WebPartManager = $Page.File.GetLimitedWebPartManager([System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)

                  #Get All Web Parts data

            foreach ($WebPart in $WebPartManager.WebParts)

            {

             if ($webPart.GetType().Name -eq "ContentEditorWebPart" -or $webPart.GetType().Name -eq "ScriptEditorWebPart")

             {

             $counter+=1

             $content = $WebPart.Content.InnerText -replace "`n", " "

                $Result = New-Object PSObject

                $Result | Add-Member -type NoteProperty -name "Site URL" -value $web.Url

                $Result | Add-Member -type NoteProperty -name "Page URL" -value $PageURL

                $Result | Add-Member -type NoteProperty -name "Web Part Title" -value $WebPart.Title

                $Result | Add-Member -type NoteProperty -name "Web Part Type" -value $WebPart.GetType().ToString() 

                 $Result | Add-Member -type NoteProperty -name "Web Part Content" -value "content$counter.txt" 

 

                $ResultCollection += $Result

               

                 $obj = New-Object -TypeName PSObject -Property @{

    Content = $content

}

$obj |Export-csv   "<path to export folder>\content$counter.txt" -notypeinformation -Encoding UTF8


         }}}

}

#Export results to CSV

$ResultCollection | Export-csv $ReportOutput -notypeinformation  -Encoding UTF8


Powershell Script to export all active workflows in a web application to a CSV file

Here is a working example of exporting a list of all active workflows in a web application 


Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue


$webApp = Get-SPWebApplication "http://your webapp url"


$csvFile = "<path to export folder>\workflows-active.csv" 


$results = @()


foreach ($site in $webApp.Sites) {

    foreach ($web in $site.AllWebs) {

     if ($web.WorkflowAssociations.Count -gt 0) {

            $webObj = New-Object PSObject -Property @{

                "Title" = $web.Title

                "Url" = $web.Url

                "Workflows" = $web.WorkflowAssociations| where {$_.Enabled -eq $true} | Select-Object -ExpandProperty Name

            }

            $results += $webObj

        }

        # Get all the lists in the web

        $lists = $web.Lists

        foreach ($list in $lists) {

            # Get all the workflow associations for the list

            $workflowAssociations = $list.WorkflowAssociations | where {$_.Enabled -eq $true}

            foreach ($workflowAssociation in $workflowAssociations) {

                # Create an object to store the workflow details

                $workflowObj = New-Object PSObject -Property @{

                    "SiteCollection" = $web.Site.Url

                    "Web" = $web.Title

                    "List" = $list.Title

                    "ListURL" = $web.Url + "/" + $list.RootFolder.Url

                    "WorkflowName" = $workflowAssociation.Name

                    "IsActive" = $workflowAssociation.Enabled

                }

                # Add the workflow object to the results array

                $results += $workflowObj

            }

        }

        $web.Dispose()

    }

    $site.Dispose()

}


$results | Export-Csv -Path $csvFile -NoTypeInformation


Wednesday, March 15, 2017

Get Child Count in Parent List SharePoint Lookup Field


I came across a requirement where I required the number of comments
 against a post in a child list (lstComments) maintained in the Parent list (lstPost).

Below is a very efficient way to achieve this


 using (SPSite site = new SPSite(webUrl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList lstPost = web.Lists.TryGetList("Post");
                    SPList lstComments = web.Lists.TryGetList("Comments");

                    if (lstPost != null &&  lstComments != null )
                    {
                        SPField id= lstPost .Fields.TryGetFieldByStaticName("ID");
                        if (null != id)
                        {
                            // Create a PostID lookup field on the lstComments list.  
                            string PostIdName = lstComments .Fields.AddLookup("PostID", lstPost .ID, true);
                            SPFieldLookup PostIdField =
                                (SPFieldLookup)lstComments .Fields.GetFieldByInternalName(PostIdName );
                            PostIdField .LookupField = id.InternalName;
                            PostIdField .Update();
                            AddToDefaultView(lstComments , PostIdName );

                            // Create a CommentCount Lookup field to maintain child count in the lstPost list
                            string commentCountName = lstPost .Fields.AddLookup("CommentsCount", lstComments .ID, false);
                            SPFieldLookup commentCountField =
                                (SPFieldLookup)lstPost .Fields.GetFieldByInternalName(commentCountName );
                            commentCountField .LookupField = id.InternalName;
                            commentCountField .CountRelated = true;
                            commentCountField .Update();
                            AddToDefaultView(lstPost , commentCountName );
                        }
                    }
                }

            } 

Friday, February 10, 2017

SharePoint Distributed Cache Issue

All of a sudden my farm started throwing Distributed cache errors. My ULS filled with below log when I refreshed a page 
Unexpected Exception in SPDistributedCachePointerWrapper::InitializeDataCacheFactory for usage 'DistributedLogonTokenCache' - Exception 'Microsoft.ApplicationServer.Caching.DataCacheException: ErrorCode<ERRCA0009>:SubStatus<ES0001>:Cache referred to does not exist. Contact administrator or use the Cache administration tool to create a Cache.   
 at Microsoft.ApplicationServer.Caching.DataCache.ThrowException(ResponseBody respBody, RequestBody reqBody)   
 at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetCacheProperties(RequestBody request, IClientChannel channel)   
 at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetCache(String cacheName)   
 at Microsoft.SharePoint.DistributedCaching.SPDistributedCachePointerWrapper.InitializeDataCacheFactory()'.

I tried steps below and walla!

1) Go to Manage Services on Server in Central Administration and stop Distributed Cache on all Application Servers and WFEs

2) Open SharePoint Management Shell and run following commands

       a) Use-CacheCluster
       b) Get-CacheCluster | Select CacheName
Above commands should return list of 10 cache types 

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>

Incase you get nothing - you need to setup DistribtedCache again so move on to step 7

In case above list is returned move on to step 3

3) Run following command 
                   Remove-SPDistributedCacheServiceInstance

4) to check of the cache instance is removed successfully 
                   Get-Cache | Select CacheName
this should return below error

Get-Cache : ErrorCode<ERRCMS0006>:SubStatus<ES0001>:Error while loading the
provider "SPDistributedCacheClusterProvider". Check HKEY_LOCAL_MACHINE ->
SOFTWARE\Microsoft\AppFabric\V1.0\Providers\AppFabricCaching ->
SPDistributedCacheClusterProvider....

5) Now add new instance of DistributedCacheService by running following command
                                  a) Add-SPDistributedCacheServiceInstance
                                 b)  Restart-CacheCluster
this should return below

HostName : CachePort                      Service Name             Service Status            Version
                                                                                       Info
--------------------                    ------------                    --------------         ----------
<host server name>:<port>      AppFabricCachingService            UP                           3
                                                                                      [3,3][1,3]

6) check if cache is available now:
                    Get-Cache | Select CacheName
should give output as below

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>


 7) No output on running step 2) indicates that you need to setup Distributed Cache altogether

to do so first determine your farm ID 
         Get-SPFarm | Select Id 
get the output and run the following command 
       New-Cache -CacheName DistributedLogonTokenCache__<ur farm ID>



8) check if cache is available now:
                    Get-Cache | Select CacheName
should give output as below

CacheName            
---------          
DistributedAccessCache_<ur farm ID>
DistributedActivityFeedCache_<ur farm ID>
DistributedActivityFeedLMTCache_<ur farm ID>
DistributedBouncerCache_<ur farm ID>
DistributedDefaultCache_<ur farm ID>
DistributedLogonTokenCache_<ur farm ID>
DistributedSearchCache__<ur farm ID>
DistributedSecurityTrimmingCache_<ur farm ID>
DistributedServerToAppServerAccessTokenCache_<ur farm ID>
DistributedViewStateCache_<ur farm ID>


 Hope this helps


Wednesday, June 1, 2016

FileNet SharePoint Integration - II

Here is my second post related to Implementing FileNet P8 API in SharePoint. In my previous post, I explained a bit about FileNet, FileNet P8 API and connecting to FileNet from C# application.

Here is how you can read a folder from FileNet, fetch its properties, fetch subfolders.

FileNet API allows you to get Folders / Files using Ids and Path. In my case, I used the path as those are configurable and can work in different scenarios.

  1. Connect to FileNet
  2. Fetch a Folder
  3. Fetch Subfolders from FileNet & Properties

1. Connect to FileNet:
public static IObjectStore Connect()
{
  try
  {
   // Set connection parameters; substitute for the placeholders.
   string uri =  GetConfigValue("FileNetServerURL");
   //"http://filenetserverurl:9082/wsi/FNCEWS40MTOM/"; 
      string username = GetConfigValue("FileNetServerAdmin"); //"P8Admin";
   string password = GetConfigValue("FileNetServerAdminPassword"); //"Password";
   string objectstorename = GetConfigValue("FileNetObjectStore");//ECMStore
   // Get client context.
   IConnection conn = Factory.Connection.GetConnection(uri);
   // UsernameToken 
   UsernameCredentials creds = new UsernameCredentials(username, password);
   ClientContext.SetProcessCredentials(creds);
     // Get default domain.
   IDomain domain = Factory.Domain.FetchInstance(conn, null, null);
   // Get object stores for domain.
   IObjectStore os = Factory.ObjectStore.FetchInstance(domain, objectstorename, null);
   return os;
 }
 catch (Exception ex)
 {   
  return null;
 }
}
2. Get Folder By Path:
   private static PropertyFilter PFFolder;
   public static string GetFolderIDFromPath(string path, string siteUrl=null )
            {
                try
                {

                PFFolder = new PropertyFilter();
                PFFolder.AddIncludeProperty(new FilterElement(null, null, null, PropertyNames.ID  , null)); 
//property that is not fetched directly can be fetched using a property filter
  IObjectStore os = Connect(siteUrl); // returns IObjectStore from Connect Method, check connect method
                    IFolder ifolder = Factory.Folder.FetchInstance(os, path,PFFolder );
                    return ifolder.Id.ToString ();
                }
                catch (EngineRuntimeException ex)
                {
             LogError(ex, " GetFolderIDFromPath("+path+")", siteUrl);
                    return null;
                }
            }

3. Fetch Sub-folders from FileNet:
   public static List<FileNetFolder> GetAllFolders(string folderpath, bool includeContent, string siteUrl = null)
            {
                List<FileNetFolder> allFolders = new List<FileNetFolder>();
                try
                {
                    IObjectStore os = Connect(siteUrl );
                    IFolder folder = Factory.Folder.GetInstance(os, ClassNames.FOLDER, folderpath);
                    IFolderSet subFolders = folder.SubFolders;
                    for (IEnumerator iterator = subFolders.GetEnumerator(); iterator.MoveNext(); )
                    {
                        IFolder subFolder = (IFolder)iterator.Current;
                        FileNetFolder newSubFolder = new FileNetFolder();
                        newSubFolder.Title = subFolder.FolderName;
// fetch OOB Properties
                        newSubFolder.TitleEn = Convert.ToString(subFolder.Properties["TitleEn"]); 
//Fetch Custom properties of a folder
                        newSubFolder.folderId = Convert.ToString(subFolder.Id);
                        allFolders.Add(newSubFolder);
                    }
                }
                catch (Exception ex)
                {
                    LogError(ex, "GetAllFolders()", siteUrl);
                  
                }
                return allFolders;

            } 


I have used the property filter while fetching properties of a folder. A property filter adds properties that are not directly received when fetching/getting a folder. such properties can be added to a property Filter add retrieved while fetching/getting a folder/file. 

Example:

private static PropertyFilter PFFolder; 
PFFolder = new PropertyFilter();
                PFFolder.AddIncludeProperty(new FilterElement(null, null, null, PropertyNames.ID  , null));

   IFolder ifolder = Factory.Folder.FetchInstance(os, path,PFFolder ); 

Tuesday, May 31, 2016

SharePoint User Profile Service Application Provisioning Issues


SharePoint User Profile Service Application Provisioning Issues
Quick Fix: 

$sync_db = "Sync DB"
$ups_service_app_name = "User Profile Service Application"

net stop sptimerv4
$syncdb=Get-SPDatabase | where {$_.Name -eq $sync_db}
$syncdb.Unprovision()
$syncdb.Status='Offline'
$ups = Get-SPServiceApplication  | where {$_.Displayname -eq $ups_service_app_name }
$ups.ResetSynchronizationMachine()
$ups.ResetSynchronizationDatabase()
$syncdb.Provision()
net start sptimerv4


------------------------------------------------------------------------------------------------------------------------------
 Get-SPServiceInstance | where {$_.TypeName -eq "User Profile Synchronization Service"}

User Profile Synchronization ... Online   ID of the service instance  1
User Profile Synchronization ... Provi...  ID of the service instance 2

$abc=Get-SPServiceInstance | where {$_.Id -eq "ID of the service instance 2"}
Stop-SPServiceInstance | where {$_.Id -eq "ID of the service instance 2"} 

and the lifesaver Reset SharePoint Cache: reference:  (http://saadiyadad.blogspot.com/2014/03/reset-SharePoint-config-cache.html) did the magic


FileNet SharePoint Integration - I

Hi Readers,
I had been away for a while and now planning to write some post based on the work I have been doing in this period. My upcoming post will be related to SharePoint 2013 development, workflows, SharePoint tweaks and fixes and majorly FileNet integration to SharePoint 2013 using FileNet P8 API and FileNet Connector for SharePoint. All my posts will be in the context of Integration of FileNet to SharePoint. You can get complete information on FileNet at IBM Support Knowledge Center.
Let's start with the introduction to FileNet and some basic operations using FileNet P8 API:
  • Introduction to FileNet Content Manager
  • FileNet P8 API Basic Concepts 
  • Connect to FileNet Repository
  • A single repository for enterprise content to provide centralized access and better control.
  • Document management services and application development support to streamline content management and delivery.
  • Delivery of active content in motion for improved business value and reduced costs.
  • Integration with Microsoft SharePoint and Microsoft Office to help increase productivity.
  • Social collaboration and mobile computing support to use the latest technologies in your enterprise content management (ECM) environment." Source: IBM
Documents
Folders
Custom Objects
  •  Example  HTTP://<your FileNet server URL>:<port>/wsi/FNCEWS40MTOM/
  • P8Administrator
  • ECM
      try
      {
       string uri =  GetConfigValue("FileNetServerURL");
          string username = GetConfigValue("FileNetServerAdmin"); 
    //"P8Administrator";
       string password = GetConfigValue("FileNetServerAdminPassword");
     //"Password";
       string objectstorename = GetConfigValue("FileNetObjectStore");
    //ECMStore
       // Get client context.
       IConnection conn = Factory.Connection.GetConnection(uri);
      
     // UsernameToken 
       UsernameCredentials creds = new UsernameCredentials(username, password);
       ClientContext.SetProcessCredentials(creds);
      
       // Get default domain.
       IDomain domain = Factory.Domain.FetchInstance(conn, null, null);
       // Get object stores for domain.
       IObjectStore os = Factory.ObjectStore.FetchInstance(domain, objectstorename, null);
       return os;
     }
     catch (Exception ex)
     { 
      return null;
     }

Introduction to FileNet Content Manager:
"Document management with IBM® FileNet® Content Manager helps you meet the growing challenge of managing enterprise content with greater speed, efficiency, and accuracy. FileNet Content Manager is a document management engine that combines enterprise content, security and storage features with ready-to-use workflow and process management capabilities.
FileNet Content Manager features include:

FileNet P8 API Basic Concepts:
 FileNet provides an extensive API for Java and C# to programmatically handle operations in FileNet Content Manager. P8 API allows applications to interact to FileNet for CRUD operations as well as Management of properties, classes, subscriptions, Permissions etc. 
  
The .NET framework-based API provides a .NET framework-based Common Language Runtime (CLR)-compliant API for accessing the full capability of Content Engine. The API accepts username and password credentials for authentication. The .NET framework-based API works only with the WSI Listener.
Following are some basic concepts of FileNet Content Manager.

Object Store:
Refers to the FileNet repository. All documents, folders, custom objects are referred to as objects in FileNet so Object store is actually a container for those objects. Every object store has a database that can comprise one or more storage areas. Objects in FileNet are further classified into versionable and non-versionable objects 

Documents are versionable objects and have metadata. A document contains content elements. A file of any type is an example of a document.

A folder is a container of objects(documents, folders etc. ). It is a non-versionable object and has metadata.

Custom objects are non-versionable objects that can contain metadata but no content. you can relate them to a database table row.

Connect to FileNet Repository:
Following is a sequence of how you can interact with FileNet through P8 API.
 You require FileNet repository details as mentioned below to connect to FileNet Content Manager through API

1. FileNet Repository URL:
2. Administrator User Name:
3. Administrator Password: 
4.  Object Store Name: 

Code Example to Connect to FileNet is as Follows:

public static IObjectStore Connect()
   // Set connection parameters; substitute for the placeholders.
   //"http://filenetserverurl:9082/wsi/FNCEWS40MTOM/";
}


Note: You must install Microsoft WSE to connect to FileNet on Windows Server 2008 R2, Win Server 2012 if FileNet server URL starts with HTTP:// else it will fail to connect since WCF only supports https:// connections