Pages

Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

December 22, 2014

Get List of WFE, APP and SQL Servers Using PowerShell

A while ago I needed a list of every WFE, APP, SQL server in the farm. The SharePoint Central Administration provides list of servers in farm, however it was not useful in my case because I did not have an exclusive WFE servers, but rather I had 2 servers that I call 'WFE' but they run the Foundation Web Application service in addition to other APP services. From SharePoint perspective, these servers are Application servers.

So I wrote the following PowerShell script to give me a list of objects for WFE, APP, SQL and other servers too.


function getListOfWFEServerNames(){
                        $WfeServers = New-Object System.Collections.ArrayList
                        $FarmServers = get-spserver
                        foreach ($Server in $FarmServers){
                                                $WAService = $Server.serviceinstances | where-object { $_.TypeName –eq "Microsoft SharePoint Foundation Web Application"}
                                                $WAServiceOnline = $WAService.Status –eq "Online"
                                                if ($WAServiceOnline){
                                                                        $WfeServers.add($Server.Name)
                                                }
                        }
                        return $WfeServers
}


function getListOfDBServerNames(){
                        $DBservers = New-Object System.Collections.ArrayList
                        $cdb = get-spcontentdatabase
                        foreach ($c in $cdb){
                                                if ($DBservers -notcontains $c.Server){
                                                                        $DBservers.add($c.Server)
                                                }
                        }
                        return $DBservers
}


$AllServers = Get-spserver | select Name, role
$SPServers = $AllServers | where-object {$_.role -eq "WebFrontEnd" -or $_.role -eq "Application"}
$wfeserversNames = getListOfWFEServerNames
$WFE = $SPServers | where-object {$wfeserversNames -contains $_.Name}
$APP = $SPServers | where-object {$_.Role –eq “Application”}
$OtherServers = $AllServers | where-object {$_.role -ne "WebFrontEnd" -and $_.role -ne "Application"}
$dbserversNames = getListOfDBServerNames
$DB = $OtherServers | where-object {$dbserversNames -contains $_.Name}

# Output
write-host "-------------------------------"
write-host "WFE servers are:"
$WFE | select Name
write-host "-------------------------------"
write-host "APP servers are:"
$APP | select Name
write-host "-------------------------------"
write-host "DB servers are:"
$DB | select Name

Happy SharePoint administration!

November 17, 2014

Error: feature with ID is not installed in this farm and cannot be added to this scope


Error:
In Visual Studio 2013 or 2010 when you are trying to deploy your feature (using the default Active Deployment) and your SharePoint farm has a multiple servers, then it will fail to deploy the solution & activate the features, and will throw the following error message:
 “Error occurred in deployment step ‘Activate Features’: feature with ID '{guid}' is not installed in this farm, and cannot be added to this scope.”
Also, the solution will show ‘Not Deployed’ in Farm solutions page in Central Administration


Reason:
This is a bug in Visual Studio 2013 (see this post for same issue in VS2010). Visual Studio uses the Microsoft.SharePoint.Administration.SPSolution.DeployLocal() method that can only deploy/activate features on local machine when its the only server in farm.


Objective:

To preserve the way the developer works. Developer need not worry about target environment (number of servers in farm for example), and should not need to run PowerShell commands every time the code changes. Developer should only use the Build > Deploy menu item in Visual Studio as usual, and the deploy process should figure it out how to install the package & features.


Solution:

Its actually a workaround until Microsoft fix with their Visual Studio. The idea is to replace Visual Studio feature activation action by a PowerShell script that will make sure the feature was installed then activated properly. The script is to be called as a post-deployment command.


Tested with:

Visual Studio 2013 Update 2, and SharePoint 2013 Visual Web Part


How To Use:
1- Make sure that path of your project does not contain spaces
     Example: “D:\TeamShared\iibraheem\PSproj\PSproj”



2- If you are using Visual Studio 2013 to target SharePoint 2013: Make sure that you set the ‘Site Url’ property of your project to target a SharePoint 2013 site that has the new SP2013 UI.


The reason is that your Visual Studio 2013 visual web part will NOT work for a SharePoint 2013 site that has a SP2010 UI (coming from a SP2010 db upgrade). 3-Adding the script
     3.1-Add the script file (Example: PostDeployScript_Feature.ps1) to project at root level:



     3.2- Edit script file: set the parameters $Url and $FeatureName. $FeatureName is in the format of   ‘ProjectName_FeatureName’ (without quotes) and has nothing to do with feature title 2.


4- Go to project properties > SharePoint tab


    4.1-Set Active Deployment Configuration to ‘No Activation’


    4.2- Paste the below command in Post-Deployment Command Line box:

  • Show Then Hide PS console (recommended):
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell "start-process powershell.exe -ArgumentList '$(ProjectDir)PostDeployScript_Feature.ps1'"
  • Keep visible PS console (for debugging):
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell "start-process powershell.exe -ArgumentList '-NoExit', '$(ProjectDir)PostDeployScript_Feature.ps1'"



5- Save the project



6- Build > Deploy

    Check PowerShell console window:
    It stays visible if ‘-NoExit’ parameter used, otherwise it will close automatically:




Now, check the target site for changes:

  • Feature to be added to the required scope (for example a specific site collection)
  • Web part will be added to Web Parts gallery at the site collection
  • Web part can be inserted to page. If previously added to a page, the page will show the updated web part

Below are the contents of PostDeployScript_Feature.ps1:


# This is a Post-Deployment PowerShell script to be called from Visual Studio to automate feature deployment

# Developed by: Ibraheem A. Ibraheem

# Feel free to adjust to your needs




# Parameters

$Url = "https://servername.domain.com"

# $FeatureName is in the format: [ProjectName_FeatureName] and has nothing to do with feature title

$FeatureName = "PSproj_Feature1"




write-host "Started.."



# When PowerShell version is 2 or more, create new thread for 1st invocation then reuses it

$ver = $host | select version.

if ($ver.Version.Major -gt 1) {

       $host.Runspace.ThreadOptions = "ReuseThread"

       write-host "ReuseThread"

}



# Add SharePoint snap-in if needed

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {

    Add-PSSnapin "Microsoft.SharePoint.PowerShell"

}

write-host "Microsoft.SharePoint.PowerShell snap-in is loaded."



# If feature already enabled then disables & retract it

$feature = Get-SPFeature -Site $Url | Where {$_.DisplayName -eq $FeatureName}

if ($feature -ne $null) {

       write-host "Feature found in target site " $Url

       Disable-SPFeature -Identity $FeatureName -Url $Url -confirm:$false

       write-host "Feature deactivated."

       Uninstall-SPFeature $FeatureName

       write-host "Feature uninstalled."

}

else{

       write-host "Feature was not found in target site: " $Url

}



# installing the feature

Install-SPFeature -Path $FeatureName

echo ""

write-host "Feature installed to 15 hive."



# If feature already enabled then disable it, because the enable is not complete (web parts are not copied


# to web part gallery in site collection)

# Note: feature will get automatically enabled when installed if scope is either 'SiteCollection' or 'Web'

$feature = Get-SPFeature -Site $Url | Where {$_.Displayname -like $FeatureName}

if ($feature -ne $null) {

       Write-Host "Feature is already activated at: " $Url

       Disable-SPFeature -Identity $FeatureName -Url $Url -confirm:$false

       write-host "Feature deactivated."

}

else {

       Write-Host "Feature is not activated at: " $Url

}



# Enable the feature

Enable-SPFeature -Identity $FeatureName -Url $Url

Write-Host "Feature got activated at: " $Url



write-host "Finished."


September 20, 2014

List view with GroupBy error: Attempted to use an object that has ceased to exist


Error Scenario:
In SharePoint, when navigating to a list view page (ex: 'All Items' view), or to a site page (like home page) that contains a list view web part, the page crashes, throwing the following error:

Server Error in '/' Application.

Attempted to use an object that has ceased to exist. (Exception from HRESULT: 0x80030102 (STG_E_REVERTED)) 


Debugging:
We know its something with list that causes the error, could be the view itself, or the columns or even something with the content types. The problem is that you cannot reach the list settings because 

1. Using PowerShell to get ID of the list and store it on text file:

$rrdbWeb = Get-SPWeb “http://{sitename}”
$rrdbWeb.Lists[“{listname}”].ID > C:\ListID.txt

Example result: 522ba78b-f2e4-4335-b3e3-2a0ff6bb6d2e

 2. Manually construct list settings page url by adding the list ID as parameter to listedit.aspx page:

http://{sitename}/_layouts/listedit.aspx?List={522ba78b-f2e4-4335-b3e3-2a0ff6bb6d2e}

3.  Create new personal view 

4. Using PowerShell to get ID of the problematic view:

$rrdbWeb.Lists[“{listname}”].Views[“{viewname}’].ID > C:\ViewID.txt

Example result: c6a3293a-377d-4757-b5f3-26de78564f04

5. Remember to dispose objects you created  in PowerShell like $rrdpWeb when you finish

6. Manually construct the modify page for the problematic view, by adding List & View parameters to ViewEdit.aspx page:

http://{sitename}/_layouts/ViewEdit.aspx?List={522ba78b-f2e4-4335-b3e3-2a0ff6bb6d2e}&View={c6a3293a-377d-4757-b5f3-26de78564f04}

 Now have a look on all details of this view. 

7. Create Another view (I prefer personal one) & enter the exact same details from the our original view. The objective here is to be able to replicate and test the error. After playing with details, I found that GroupBy option is causing the error. When GroupBy is not used then view works perfectly well!


Root Cause:
The error is thrown because of the resource throttling in that list. The GroupBy is counting & folding too many items causing SharePoint to prevent the SQL server from processing the view query. When checking the number of items in list settings page, it shows it had 18670 items (way above the default list view threshold of 5000).


Solution:
The fix is to enable larger resource throttling for the target web application.
Example: In this case I set to 20000.

From Central Administration site > Manage Web Applications > select target web app > General Settings > Resource Throttling > change List View Threshold > OK

Note: there is a reason of why Microsoft set the default theshold into 5000 which is to avoid getting a performance hit on SQL server by queries on too many items. When you have very large lists or libraries, try to think about alternative approaches to divide the data, such as split into multiple lists, or using folders in case of document libraries.