Pages

Tuesday, 12 February 2013

When opening office (word, excel) documents from anonymous Internet facing site hosted on SharePoint 2010, users receive logon prompts

Scenario: 

When using IE and opening office (word, excel) documents from anonymous access enabled Internet facing site hosted on SharePoint 2010, users receive logon prompts. After hitting the escape key a couple of times the document does open. When using Firefox the logon prompt does not appear.

Reason:

IE opens word first and then word tries to download the document, however other browsers download the document and then open word to view the document.

According to the Microsoft Knowledge base article, giving "OpenItems" permission allows anonymous users to have view source rights to certain files that could potentially contain sensitive info.



Programmatically give "OpenItems" permission to the SPWeb to anonymous users. Note that you should only do this if you understand & accept the security implications. The sample script below can be used to add the "Open Items" permission:

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

$siteUrl = "http://URL_of_your_SITE";
$site = New-Object Microsoft.SharePoint.SPSite($siteurl);
$web = $site.OpenWeb();

$enumPerms = [Microsoft.SharePoint.SPBasePermissions];

Write-Host $web.AnonymousPermMask64;
$web.AnonymousPermMask64 = $web.AnonymousPermMask64 -bor $enumPerms::OpenItems
$web.Update();
Write-Host $web.AnonymousPermMask64;

$web.Dispose();
$site.Dispose();



In my case this did not work, so I had to change the approach to pass the relative path to the document to /_layouts/download.aspx

 Added this script to the Scripts.js (custom Javascript library for my SharePoint site) and called the method in $(document.ready.....


function rectifyOfficeDocumentLinks()
{
     $("a").each(function(){
                if (this.href.match(/.doc$/i) || this.href.match(/.docx$/i) || this.href.match(/.rtf$/i) || this.href.match(/.xls$/i) || this.href.match(/.xlsx$/i) || this.href.match(/.ppt$/i) || this.href.match(/.pptx$/i))
                {
                    if (this.href.indexOf("/_layouts/download.aspx?SourceUrl=") == -1)
                    {
                     this.href = _spPageContextInfo.siteServerRelativeUrl + "/_layouts/download.aspx?SourceUrl=" + this.href.replace("http://" + window.location.host,''); 
                    }
                }
                });
}


References:
  • http://social.msdn.microsoft.com/forums/en-SG/sharepointgeneralprevious/thread/62381802-20b9-49ee-985b-8d2dcd2453ea 
  • http://support.microsoft.com/kb/2498047/en-us
  • http://blogs.technet.com/b/acasilla/archive/2011/10/01/add-openitems-permission-to-the-default-anonymouspermmask64-so-that-you-can-open-office-docs-within-an-anonymous-accessible-sharepoint-site.aspx

Thursday, 7 February 2013

Custom List form loading error "Error while executing web part: System.StackOverflowException: Operation caused a stack overflow"

To solve this issue either 
  • SharePoint will throw the stack overflow exception if a transform takes longer than 1 second. Then in such circumstances, please break the “dvt_1.rowedit” template into smaller template.
 Or

  • Microsoft has released february 2012 CU for SharePoint: http://support.microsoft.com/default.aspx?scid=kb;EN-US;2597150 where it it possible to modify the XSL tranformation timeout by using Powershell. This will fix the issue as the original timeout was hardcoded to 1 second. After installing the CU, you are able to do the following by using PowerShell:
 
 
$farm = Get-SPFarm 
$farm.XsltTransformTimeOut = 5 //timeout in seconds 
$farm.Update() 

How to Deploy changes to the web.config file as a feature for a SharePoint web application

I am currently working for a SharePoint hosting provider and as part of the general guidence, direct web.config changes are not allowed. Any change should be incorporated as a SharePoint feature, if you think about it, this is a good practice to get into.

Pros for deploying as features:
  • A solution repository can be maintained, which will make migration easy
     
  • Any future upgrades can lead to missing manual config changes
  • Fuctionality can be targeted to a web application or a sitec collection etc

Anyways, the post is about how to deploy changes to a web config via a feature.

*** Warning - Programatically modifying web.config changes are not very clean, so

Web config changes are specific to a web app, hence we will write and deploy a feature targetting a web app.

  1. Open visual studio and create a empty SharePoint project
  2. Add a new feature and set the Target to " Web Application"  (Make sure you name your Feature with an appropriate name)
  3. Double click on the Feature and in the Properties window, set the "Activate on Default" to false - We want to manually activate the feature per web application
     
  4. Add a Feature Receiver
  5. in the feature activated event, add the following code:


     public override void FeatureActivated(SPFeatureReceiverProperties properties)
            {
                try
                {
                   SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://mywebapp"));

                    SPWebConfigModification moduleModification = new SPWebConfigModification();
                    moduleModification.Path = "configuration/system.webServer/modules runAllManagedModulesForAllRequests=\"true\"";
                    moduleModification.Name = "add[@name=\"myHttpModule\"][@type=\"myHttpModule.myHttpModuleClassLib, myHttpModule\"]";
                    moduleModification.Sequence = 0;
                    moduleModification.Owner = "admin";
                    moduleModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                    moduleModification.Value = "<add name=\"
    myHttpModule\" type=\"myHttpModule.myHttpModule, myHttpModule\" />";
                    webApp.WebConfigModifications.Add(moduleModification);

                    webApp.Update();
                    //service.ApplyWebConfigModifications();
                    webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                }
                catch (Exception ex)
                {
                    //Log exceptions in the Event Log
                    using (EventLog eventLog = new EventLog("Application"))
                    {
                        eventLog.Source = "myHttpModule";
                        eventLog.WriteEntry(string.Format("{0}: - {1} Error: \"{2}\" ", EventLogEntryType.Error, "myHttpModule- Feature Activating", ex.ToString() + Environment.NewLine + ex.StackTrace.ToString()), EventLogEntryType.Error);
                    }
                   
                    //Throw the exception for the admin
                    throw ex;
                }

            }
  6.   Add the following code to feature deactivating


     public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
            {
                try
                {
                    SPWebConfigModification configModFound = null;
                    SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://mywebapp"));
                    Collection<SPWebConfigModification> modsCollection = webApp.WebConfigModifications;
                    for (int i = 0; i < modsCollection.Count; i++)
                    {
                        if (modsCollection[i].Owner == "fu1adm" && modsCollection[i].Name == "add[@name=\"
    myHttpModule\"]")
                            configModFound = modsCollection[i];
                    }
                    if (configModFound != null)
                    {
                        modsCollection.Remove(configModFound);
                        webApp.Update();
                        webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                    }
                }
                catch (Exception ex)
                {
                    //Log exceptions in the Event Log
                    EventLog eventLog = new EventLog("Application");
                    eventLog.WriteEntry(string.Format("{0}: - {1} Error: \"{2}\" ", EventLogEntryType.Error, "myHttpModule- Feature Deactivate", ex.ToString() + Environment.NewLine + ex.StackTrace.ToString()), EventLogEntryType.Error);
                    throw ex;
                }


            }
  7.  Build the solution and add it to the solution store
  8. Deploy the solution to the web app or globally
  9. In Central Admin > Click on the Application management > Manage web applications > Select the appropriate web application and click on Manage Features > Click on activate.
  10.  Make sure the web.config has been modified.

There are numerous reasons why web.config changes should be avoided via code. Microsoft has limited documentation on this

References:
http://msdn.microsoft.com/en-au/library/bb861909%28v=office.14%29.aspx  

Wednesday, 30 January 2013

How to list all the Web Applications, all the site collections within the web app and all the Level 1 sub sites within that site collection using c# SharePoint 2010

I recently had  a requirement for a SharePoint Hosting provider, they wanted an inventory list of all the web applications, all the site collections and the first level sub sites with the site collection.

I used a console application, you can do this easily with Powershell as well.


try
            {
                SPServiceCollection services = SPFarm.Local.Services;

                foreach (SPService curService in services)
                {
                    if (curService is SPWebService)
                    {
                        SPWebService webService = (SPWebService)curService;
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                            {
                                foreach (SPWebApplication webApp in webService.WebApplications)
                                {
                                    // here you can do something with webApp

                                    foreach (SPSite siteCollection in webApp.Sites)
                                    {
                                        using (SPSite site = new SPSite(siteCollection.Url.ToString()))
                                        //(ConfigurationManager.AppSettings["SiteCollUrl"]))
                                        {
                                            SPWebCollection webCollection = site.AllWebs;
                                            if (webCollection.Count > 0)
                                            {
                                                for (int i = 0; i < webCollection.Count; i++)
                                                {
                                                    if (!webCollection.Names[i].Contains("/"))
                                                    {
                                                        Console.WriteLine(webCollection[i].Url + " : " + webCollection[i].Title + " : " +
                                                                            webCollection[i].Description + " : " + webCollection[i].IsRootWeb);
                                                    }
                                                }
                                            }
                                        }
                                        //}
                                        siteCollection.Dispose();
                                    }
                                }
                            });
                    }
                }
            }
            catch (Exception ex)
            {
                writetoCSV("", "", ex.Message, false);
                throw ex;
            }


You can write this to a CSV file or txt file.

If you want a list of all the site collections and sub sites for a given web application use the powershell script listed here:



Tuesday, 22 January 2013

Custom 404 error page does not render in Firefox and Chrome but works in IE


Had an issue last week where our custom 404 error page rendered fine in Internet Explorer but did not render in Firefox and Chrome.

Thanks to a colleague of mine, he stumbled across this awesome post by Brian farm hill.

http://blog.brianfarnhill.com/2012/12/issues-with-a-custom-404-page-in-sharepoint-2010

How to activate a set of standard list of features in all site collections for a web application using Powershell in SharePoint 2010

Problem

The department has a site collection that is heavily used and is a key site collection.The business would like to standardise site collection features across the board. 
How to activate a standard list of features in all site collections for a web application using powershell script for SharePoint.

Solution:
Note: # is a comment in powershell

Contents of  ManualListofFeaturesInEDSite.txt - This contains all the features that need to be activated. If you do not wish to read from a text file and use a reference site then just use 

$allSiteColFeature = Get-SPFeature -site "http://muwebapp/sites/nintex" | Select displayname, id 
NintexWorkflow
NintexWorkflowWebParts
NintexWorkflowInfoPath
NintexWorkflowEnterpriseWebParts
NintexWorkflowContentTypeUpgrade
OfficeWebApps
OpenInClient
ReviewPublishingSPD1033
ReportServer
Reporting
PublishingSite
BaseSite
InPlaceRecords
LocationBasedPolicy
WAReports
DocumentSet
DocId
Workflows
LocationBasedPolicy
ViewFormPagesLockDown


 ***** Script begins here ******
  Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue

$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
Start-Transcript -path C:\Admin\SiteFeaturesoutput.txt -append

 $webs =  get-spsite -webapplication "http://mywebapp" -Limit All
 # Returns a detailed list of features, hence not being used
 #$allSiteColFeature = Get-SPFeature -site "http://muwebapp/sites/nintex" | Select displayname, id
 
 $fileContent = Get-Content "C:\drive\PROJECTS\DEVELOPMEN\ManualListofFeaturesInEDSite.txt"
 

#$oneweb = "http://mywebapp/sites/nintex"
   
    Foreach ($oneweb in $webs)
    {
        Foreach ($featureId in $fileContent)
        {
            #$siteFeature = get-spfeature -site $oneweb | Where {$_.id -eq $featureId.id}
            $siteFeature = get-spfeature -site $oneweb | Where {$_.displayname -eq $featureId.displayname}
           
            if ($siteFeature -eq $null)
            {
              Write-Host "Activating Site level Features at $oneweb FeatureID: $featureid" -foregroundcolor Yellow
               Enable-SPFeature $featureId -URL $oneweb.URL -Confirm:$False
              #Disable-SPFeature $featureId -URL $oneweb.URL -Confirm:$False
              #Enable-SPFeature $featureId -URL $oneweb -Confirm:$False
            }
            else
            {
              Write-Host "Feature $feature is already activated on $oneweb" -foregroundcolor green
            }
        }

    }

Stop-Transcript



****** End of Script ******

Using PowerShell script to change a web application's authentication to claims mode

Open PowerShell command window and execute the script below:

$webApp = Get-SPWebApplication "http://mywebapp"
$webApp.UseClaimsAuthentication = "True";
$webApp.Update();
$webApp.ProvisionGlobally();

Once the script has executed, navigate to your web app’s authentication provider settings:

image

Under Zone click on Default and select your identity provider for claims based authentication:

image

Sunday, 25 November 2012

How to manage multiple remote desktop sessions

If you are sysadmin or anyone who needs to manage multiple remote desktop sessions, then this free tool is a must. It's called Remote Desktop Connection Manager, free from Micorsoft.

http://www.microsoft.com/en-us/download/details.aspx?id=21101

Tuesday, 20 November 2012

How to log the output to a text file for a powershell script

Problem

Some times when performing bulk operations you would want to log the output of a powershell script to a text file, so you can examine the results and perhaps even investigate what went wrong.

Solution:

Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue

$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
Start-Transcript -path C:\Admin\SiteFeaturesoutput.txt -append


.
.
Your script goes here
.
.
Stop-Transcript

Sunday, 11 November 2012

How to get crawled properties for a document using Powershell in SharePoint 2010


(This is an exact copy from this site: I have created this post for my Personal Reference)


In order to get the crawled properties for a document copy the powershell command, this information can be used to create Managed Properties for search.



Function Get-CrawledPropertyNames([string]$DocURL){  
$DocURL = $DocURL.Replace("%20"," "$webfound = $false 
$weburl = $DocURL 
 
while ($webfound -eq $false) { 
    if ($weburl.Contains("/")){ 
    $weburl = $weburl.Substring(0,$weburl.LastIndexOf("/")) 
    $web = get-spweb -identity $weburl -ea 0 
    if ($web -ne $null){ 
        $webfound = $true 
    } 
    }else{ 
    Write-Host -ForegroundColor Red "The Web could not be found" 
    return -1 
    } 
     
} 
$web.GetFile($DocURL).item.xml.Replace("' ""' `n").Replace("`" ", "`" `n") 
} 


#To use enter the url of a file within a doucment library 
Get-CrawledPropertyNames "http://sites/doc/file.pdf" 
 
The output: 




Thursday, 1 November 2012

How to ensure the field value is the same in a repeating section in an InfoPath form hosted in SharePoint 2010 Forms library

Scenario:
Consider this: You have a information request form at a school. When someone (who is an authorised requester) requests information for a student. The admin staff use this form to record the information sent to the requester for legal reasons. The admin staff are allowed to add multiple students for the same request however, the students need to be from the same school.

When the admin staff login, their details are populated automatically from GetUserProfileByName web service.


`Figure 1

The form has a repeating control as seen in Figure 2 (People Picker Control + Label (Field Name is ChildSchool)) in an InfoPath form which is published to a Form Library in SharePoint 2010


Figure 2
Problem:
Since it is a repeating section, you cannot control or know the number of instances of the control. A user can add many by clicking the insert link.

Solution:
Add another control (text) to form called AllSchoolNames, it does not have to be visible on the form it is just used to calculate the total number of schools
Figure 3

Click properties of the AllSchoolNames field and add this to the Value field under Default Value Section
eval(eval(NameOfChilds, 'concat(../my:childSchool, substring(";", 1, string-length(../my:childSchool)))'), "..")




Click on "fx" and click on "Edit XPath (advanced)" - Ensure your values look similar to this:

xdMath:Eval(xdMath:Eval(../my:NameOfChild/my:NameOfChilds, 'concat(../my:childSchool, substring(";", 1, string-length(../my:childSchool)))'), "..")

This will return either o (false) or 1 (true)

That's it. Based on the return value you can include Rules to perform an action.

Hope it helps:
References:

http://www.infopathdev.com/forums/p/7124/75545.aspx

Thursday, 25 October 2012

Adding and Deploying solutions in SharePoint 2010

*** When a wsp is available ***

Adding a solution to the Solution Store

Add-SPSolution -LiteralPath <SolutionPath>

Deploy a solution

Install-SPSolution -Identity <SolutionName> -WebApplication <URLname>

To deploy a solution package to all Web applications

Install-SPSolution -Identity <SolutionName> -AllWebApplications -time <TimeToDeploy> -GACDeployment -CASPolicies


To upgrade an existing wsp solution file

Update-SPSolution –Identity mySolution.wsp –LiteralPath c:\mySolution.wspGACDeployment

To uninstall a solution

Uninstall-SPSolution –Identity mySolution.wsp –WebApplication http://webapp

To remove a solution

Remove-SPSolution –Identity mySolution.wsp

Extract a solution from the Content DB: SharePoint 2010

In order to gain access to a copy of a wsp file from the Config DB, follow these steps:

Powershell:

$farm = Get-SPFarm
$file = $farm.Solutions.Item("mySolution.wsp").SolutionFile
$file.SaveAs("c:\temp\mySolution.wsp")

To Get all solutions within a farm:
(Get-SPFarm).Solutions | ForEach-Object{$var = (Get-Location).Path + "\" + $_.Name; $_.SolutionFile.SaveAs($var)}

 

C#

using Microsoft.SharePoint
using Microsoft.SharePoint.Administration

namespace GetWSPFile
{
   class GetFile
   {
      static void Main(string[] args)
      {
           SPSolutionCollection AllSolutions = SPFarm.Local.Solutions;
           foreach (SPSolution solution in AllSolutions)
           {
              if(solution.Name =="mySolution.wsp")
              {
                     SPPersistedFile wspFile = solution.SolutionFile;
                     wspFile.SaveAs("C:\" + Solution.Name);
              }
           }
       }
    }
}

Installing a Feature when you only have access to the Feature Folder on the Server: SharePoint 2010

*** When you only have access to
the Feature folder ***
  • First, Copy the folder to the web front end / Central Admin server
Install to the farm:
Install-SPFeature FeatureFolderName

Enable at a site collection
Enable-SPFeature FeatureFolderName -Url http://server/site/subsite

Uninstall a featrure based on a folder:

Uninstall-SPFeature FeatureFolderName
Disable a feature for a site collection
Disable-SPFeature FeatureFolderName -Url http://server/site/subsite

Wednesday, 24 October 2012

How to customise the New form for a document library in SharePoint 2010.

How to customise the New form for a document library in SharePoint 2010.


Note: This is not supported by Microsoft and it just a work around.

In order to create a custom New Form for a document library we will follow these simple steps:


  1. Create a list with exact content type (List settings > Advanced settings > Allow management of content types)
  2. Then click on the Customise Form (Infopath Icon)
  3. The form will open in Infopath
  4. Once the form is open select File > Publish > Export Source Files and save it in a desired location
  5. Edit the mainfest.xsf File in a text editor (I use Notepad++)
  6. Scroll down to bottom section where you should see this:



  7. We want to change the content type ID and the relativeUrl values here to point to the document library that we want to customise the new form for:
  8. In order to get the content type ID follow this post
  9. Change the Content type ID and Relative URL (for a document library just replace ../../ with the library name does not require a prefix library either)
  10. Save the mainfest.xsf
  11. Right click and select Design, now the form will point to the library, save and publish.

On a side note:
I have only tested this with a single content type




How to get the list ID and Content type ID in sharePoint 2010

To get the List ID:
  1. Navigate to list settings and copy List={ENCODED GUID}

    In my case it was this List=%7B2E5002B0-EDC3-4541-A0ED-2A81797B459C%7D
  2.  Decode the GUID here or here
  3. It should return a value similar to this: List={2E5002B0-EDC3-4541-A0ED-2A81797B459C}
That's it :)

To get the Content type ID currently associated with a list or library:

(Assuming allow management of content types is set to Yes (Under list settings > advanced settings))
  1. Navigate to list/library settings
  2. Under content types > select the content type
  3. From the URL copy this part:
    ctype=0x0100801F054C4E00C243A9A49EC13FF778D7003293EF8DE37E144BAA8A5296D5E6CA8B
  4. This the Content type ID

Monday, 28 February 2011

SharePoint 2007 Tips and Tricks

My First blog:
What better way to start of by posting a few SharePoint 2007 (MOSS) tips and tricks.

--> -->
Tip #1: Add Command Line Shortcut to "12 Hive"
When you're in a command prompt, sometimes you need to navigate to the 12 Hive directory. But no one wants to type the directory path to c:\Program Files\Common Files\Microsoft Shared\web server extensions\12. Wouldn't it be easier if you could just type the following to get there?
c:\>cd\
c:\>cd %12hive%
c:\Program Files\Common Files\Microsoft Shared\web server extensions\12
The other thing is you want to be within a Visual Studio Command Prompt to have easy access to things like SN.EXE and GACUTIL.EXE. A VS Command Prompt is nothing more than a simple batch file.
Create a new file called SharePointCommandPrompt.cmd and insert the following text in it (if you're on a 64 bit system, you'll want to make the appropriate changes):
@echo off
echo Setting 12HIVE environment variable.
set 12HIVE="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12"
"C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" x86
  1. After saving the file, create a new shortcut with the following target:
%comspec% /k ""c:\[Path To The File You Just Created]\SharePointCommandPrompt.cmd""
  1. To put a cherry on top, drag the shortcut onto your Quick Launch toolbar... should work like a champ!
To try it out, click the shortcut and type CD %12HIVE% at the command prompt. You should change directories to the root of the 12 Hive.
Tip #2: Access STSADM.EXE From any Directory in a Command Prompt
STSADM.EXE, the main administration utility for SharePoint, is still just a command line utility. You'll find it in %12HIVE%\BIN. To run it, you have to actually be in that directory... an inconvenience to me! Instead, add the directory to the PATH environment variable so you can type STSADM.EXE from any directory on your system. To do this:
  1. Start -> All Programs -> Control Panel -> System
  2. On the Advanced tab, click the Environment Variables button.
  3. Select the variable Path and click the Edit button.
  4. Add the following to the end of the Variable value field (don't forget the semicolon... the Path environment variable is a semicolon delimited string of directories):
    ;C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN
  5. OK out of all the dialogs.
Next time your system restarts, you'll be able to type STSADM.EXE at a command prompt from any directory on your system.
Tip #3: Recycle Application Pools, not IIS
So many things in SharePoint require you to recycle the the W3WP.EXE process running SharePoint in order for certain changes to be picked up. So many people think this means recycling IIS by typing IISRESET. But it takes so long for IIS to recycle!
Did you know you don't have to recycle IIS most of the time, just the application pool your site is running within? For development purposes, run all SharePoint sites off the same app pool. Though, not the most secure, but each app pool consumes roughly 100MB of memory so why have a ton of them floating around in a virtual machine when memory is precious!
Instead of recycling IIS, I create a shortcut that I add to my Quick Launch that recycles the app pool all my sites run under. To do this, create a new shortcut on your desktop and enter the following target:
%windir%\system32\cscript.exe c:\windows\system32\iisapp.vbs /a "[Name of your App Pool]" /r
Click the shortcut and watch how fast an app pool is recycled compared to IIS!