Archive

Archive for the ‘Environment’ Category

Open PDF documents in your client application

July 2, 2015 1 comment

When working with PDF files in SharePoint, most of the time these have to be opened in the browser and most of the time that works. That is because an Adobe plugin within your browser checks if the file which is returned has a content type of application/pdf and if so, it opens the document within your browser.

For one of my customers this was not what they wanted. The wanted the option to open multiple PDF documents and show them next to each other on their screen (not in different browser windows). You can disable the Adobe browser plugin, but this will impact all PDF’s you download, also from other sources (Internet etc.)

Okey, so how did we fixed this. The most important part is that the Adobe plugin checks the content type (the MIME type) returned. So to start, we need to change this one… Perform these steps on ALL of your front-end servers:

  1. Open Internet Information Services.
  2. On the GLOBAL level, navigate to the MIME types.
    The PublishingHttpModule handles the authorize request and also looks up the MIME type, this will be done based on the global settings. This means this method will work for all web applications within your farm, if you want it or not.
  3. Find the MIME type for the extension pdf.
  4. Change the MIME type to application/pdf2.
  5. Perform an IISRESET.

These actions will prevent the PDF document to open in the browser, but instead it will show you the save dialog (which I don’t want):PDF Download Dialog
Note: This dialog will only be shown for documents which haven’t been opened before. For other documents, you will have to clear your local browser cache!

If you want the document to open automatically within the Adobe Reader or Writer, or whichever application you use to open PDF files, this can be achieved by updating your registry. This can of course also be set by a policy for your entire company. The following steps can be made to update your registry to automatically open your PDF application:

  • Start regedit on your client (or create a policy)
  • Navigate to HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell
  • Navigate to AttachmentExecute or create this key if it doesn’t exist yet.
  • Navigate to {0002DF01-0000-0000-C000-000000000046} or create this key if it doesn’t exist yet.
  • Create a new Binary Value with the name AcroExch.Document.11

Note: The value of the name of the binary value can differ with your company. The AcroExch.Document.11 is used for the Adobe Acrobat Reader. To check your value open your command prompt and execute the command assoc.[extension], so in this case assoc.pdf

That’s it! All PDF documents stored within your SharePoint environment will now be opened within your client application.

Advertisements
Categories: Environment, SharePoint

Forcefully delete site collection

August 21, 2014 8 comments

Today I found a site collection on a customer environment which gave a completely blank page when you opened it via a browser. It didn’t gave a 404 (Not Found) error, it was just a blank page. I decided to figure out what was happening and found that during the creation of the site collection, an IISRESET had taken place. Because of this, the site wasn’t completely provisioned. Well, if it wasn’t completely provisioned, I don’t need it… Nobody could have added content.

I found out that I couldn’t remove the site using Central Administration. When you navigate to the site collection using the “Delete a site collection” page, the details (right hand site of the page) where not loaded and you cannot select the site collection. So… I wanted to delete the site using PowerShell, but this gave me an error:

PS C:\Users\macaw> remove-spsite http://dms/case/P68430
Confirm
Are you sure you want to perform this action?
Performing the operation “Remove-SPSite” on target “http://dms/case/P68430“.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”): Y
remove-spsite : <nativehr>0x80070003</nativehr><nativestack></nativestack>
At line:1 char:1
+ remove-spsite http://dms/case/P68430
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Share…mdletRemoveSite:SPCmdletRemoveSite) [Remove-SPSite], DirectoryNotFoundException
+ FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletRemoveSite

Apparently, the normal remove-spsite cmdlet cannot delete a site collection which is not fully provisioned, and this cmdlet doesn’t have a force flag. To forcefully delete the site collection, I used the SPContentDatabase.ForceDeleteSite method:

$siteUrl =http://dms/case/P68430
$site = get-spsite $siteUrl
$siteId = $site.Id
$siteDatabase = $site.ContentDatabase
$siteDatabase.ForceDeleteSite($siteId, $false, $false)

SharePoint 2013 warm-up script

For SharePoint On Premise platforms it’s a good practice to use a warm-up script to avoid long loading times in the morning. By default IIS recycles the web application pools every night to clean up the memory and this is a good practice. Todd Klindt written a nice post about using the Invoke-WebRequest cmdlet which is available in PowerShell v3 and how to use this as basis for your warm-up script.

I used it as a basis and created the script you find below. Important notes:

  • The script will load the start page of the root site collection of every web application.
  • Different types of web templates, use different assemblies. If you want to preload all assemblies, ensure you load the different types of sites. The additionalUrls array is used for that in the script.
  • When you use multiple front-end servers, you want schedule the script on all front-end servers. Also make sure the server doesn’t use a load balancer when you are on the server itself, you can do this by updating the hosts file.

#——————————————————
# Ensure the SharePoint Snappin has been loaded
#——————————————————
if ( (Get-PSSnapin -Name “Microsoft.SharePoint.PowerShell” -ErrorAction SilentlyContinue) -eq $null ) {
    Add-PSSnapin “Microsoft.SharePoint.PowerShell”
}

#——————————————————

# Simple method to write status code with a colour
#——————————————————
function Write-Status([Microsoft.PowerShell.Commands.WebResponseObject] $response) {
    $foregroundColor = “DarkRed”
    if($response.StatusCode -eq 200) {
        $foregroundColor = “DarkGreen”
    
}
    write-host ([string]::Format(“{0} (Status code: {1})”, $response.StatusDescription, $response.StatusCode)) -ForegroundColor $foregroundColor
}

#——————————————————
# Warm-up all web applications
#——————————————————
Get-SPWebApplication | ForEach-Object {
    
write-host ([string]::Format(“WebApplication request fired for {0} [{1}]… “, $_.DisplayName, $_.Url)) -NoNewline
    
Write-Status -response (Invoke-WebRequest $_.url -UseDefaultCredentials -UseBasicParsing)
}

#——————————————————
# Since the root of web applications use different templates then other site collections, also load other sites of different
# types. This ensures their assemblies also get loaded in memory
#——————————————————
$additionalUrls = @(http://developmentserver/sites/search&#8221;,
 http://developmentserver/site/teamsite&#8221;)
$additionalUrls | ForEach-Object {
    write-host ([string]::Format(“Additional web request fired for Url: {0}… “, $_)) -NoNewline
    
Write-Status -response (Invoke-WebRequest $_ -UseDefaultCredentials -UseBasicParsing)
}

 

 

Creating new document via SharePoint 2013 shows Page not Found

Today I was working with SharePoint 2013 and I wanted to create a new Word document in a document library. When I clicked on the New Document button, I got a The webpage cannot be displayed error. The URL of the page was: ms-word:nft|u|http://[customerurl]/Documents/Forms/template.dotx|s|http://[customerurl]/Documents

The problem I had was that my client PC had Office 2010 AND SharePoint Designer 2013. When you have applications of Office 2013 next to Office 2013 on your machine, you might get this issue. This means both Office versions have Microsoft SharePoint Foundation Support installed. You can either remove this from one of the versions, or just install SP2 for Office 2010.

Categories: Environment, SharePoint

SharePoint 2013 memory issues

I’ve been working with SharePoint 2013 for a little while now and I’ve noticed some curious issues:

  1. When connecting to a site using SharePoint Designer 2013 I kept getting a message that the site contents could not be loaded. I actually had to stop SharePoint Designer via task manager since I kept getting the message boxes.
  2. When working with the Secure Store Service Application via code I got errors indicating the Secure Store was not started even though it was started according to the Services on Server page in Central Administration.
  3. When working with the Secure Store Service Application via code I got access denied errors on the web service call.
  4. When working with the Secure Store Service Application via code I got access denied errors on the web service call.
  5. When working with the Business Data Connectivity Service Application I got access denied errors on the web service call.

It took me a bit of time, but at the end I found out that these issues arose because of memory issues, or better the lack of available memory. When your SharePoint server uses 95% or more of its memory, web services can no longer be started. The problem I have with my development environment is that it’s a single server setup. SQL Server is running on the same VM and it was slowing eating all my available memory. By setting the maximum server memory I can avoid these issues luckily.

Optimizing your SharePoint development environment – Versioning

June 25, 2012 1 comment

Today I’ve spent some time optimizing my Visual Studio settings in order to automatically update version numbers in my SharePoint projects. For this I’ve look at adding version numbers for assemblies and for solution packages.

In this post I’ll start by explaining the theory and I will end with how I’ve changed my Visual Studio settings.

The theory

Assembly versions

For assemblies, you have two different version numbers you could update.

  • Assembly Version: This is the version number used by the .NET framework during build and at runtime to locate, link and load the assemblies. When you add reference to any assembly in your project, it is this version number which gets embedded. At runtime, CLR looks for assembly with this version number to load.
  • Assembly File Version: This is the version number given to file as in file system. It is displayed by Windows Explorer. It’s never used by .NET framework or runtime for referencing.

Challenges with assemblies in WSP’s

Updating the assembly version number for your SharePoint solutions will provide you with some challenges. The main challenges are:

  • SharePoint stores assembly references including assembly version in many different places:
    • ASPX
    • C# Code
    • Web Part XML
    • Web Config
    • Control Templates
    • Creating a new version would require a lot of additional work, since it would mean you need to modify a large number of files to update the assembly version and would require tooling to upgrade artifacts in the content databases.

SharePoint Solution Packages (WSP)

Solutions don’t have a version number included unless you add one in the name. It is recommended to add a version number, because this is the only way to know which version of your solution is deployed (only the name is listed in the solution overview page or when you check the installed solutions via PowerShell).

Important:The name is only used for displaying which solutions are installed, internally SharePoint uses the identifier of the solution (a GUID).

To be consistent with the naming conventions on features, add the namespace to the solution name too. For instance Peter.SP2010.Intranet.Core_v1.0.12177.wsp for a solution adding core functionality.

I use the following naming convention for solutions:

<Company>.SP2010.<ApplicationName>.<ApplicationBuildingBlock>_<version>.wsp

For example:

Peter.SP2010.Intranet.SiteDefinitions_v1.0.12177.wsp

Version numbers

Version numbers are written as:

<major>.<minor>.<build>.<revision>

I incremented the version numbers as followed:

  • Major: A significant change to the UI or code base is reflected in the major number. This mainly happens when a complete new version of the solution has been created
  • Minor: Providing a new release package with huge changes. This is something I tend to avoid, since I don’t want to update all versions numbers in non-code files.
  • Build: Indicating which day of which year the build is made. The format for the build number is YYDDD. The YY is indicating the last two digits of the year and DDD is indicating the day of the year (1-365).
  • Revision: Is used to indicate if the release is contains a bugfix. If the number is higher than 0 then that indicates that the release contains a bugfix from the same day.

The implementation

To update the AssemblyFileVersion and the solution naming, I’ve updated the project file manually and added a pre and post build event.

Ensure a package is created during the build event

Most times I perform a build, I also want the WSP file to be generated. To allow this, you can add the following XML to your project file:

<PostBuildEventDependsOn>

$(PostBuildEventDependsOn);

CreatePackage;

</PostBuildEventDependsOn>

This ensures that on every build action, a WSP is created as well. I need this file to update the name to include the version number in the next steps.


Update the AssemblyFileVersion

Notes

The following PowerShell script can be used to update the AssemblyFileVersion when building your project. Important items to note:

  • The build events are triggered from the folder in which the assembly is build. So this will be either from [projectfolder]\bin\debug or [projectfolder]\bin\release.
  • When using TFS, you should make sure the path to the Visual Studio folder containing tf.exe is added to the PATH environment variable and the line to check the file out should be enabled.
  • I only update the AssemblyFileVersion when generating a release package. For debug on my development machine I don’t think it’s needed.

Usage

To use this script, please it somewhere on your development machine and then start it in a pre-build event (properties of your project > Build Events). In my case I start it as stated below. I use a relative path since it’s part of my TFS source and I don’t know the mapping of other developers:

if $(ConfigurationName) == Release powershell.exe ..\..\..\..\..\BuildScripts\UpdateFileVersionAssembly.ps1

The script

#-------------------------------------------------------------------------------            
# Displays how to use this script.            
#-------------------------------------------------------------------------------            
function Help {            
    "Sets the AssemblyFileVersion of AssemblyInfo.cs files`n"            
    ".\SetVersion.ps1 [VersionNumber]`n"            
    " [VersionNumber] The version number to set, for example: 1.1.9301.0"            
    " If not provided, a version number will be generated.`n"            
}            

#-------------------------------------------------------------------------------            
# Generate a version number.            
# Note: customize this function to generate it using your version schema.            
#-------------------------------------------------------------------------------            
function Generate-VersionNumber {            
    $today = Get-Date            
    return "1.0." + ( ($today.year - 2000) * 1000 + $today.DayOfYear )+ ".0"            
}            

#-------------------------------------------------------------------------------            
# Update version numbers of AssemblyInfo.cs            
#-------------------------------------------------------------------------------            
function Update-AssemblyInfoFiles ([string] $version) {            

    $fileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'            
    $fileVersion = 'AssemblyFileVersion("' + $version + '")';            

    $scriptPath = pwd            
    $scriptPath = Split-Path -Path (Split-Path -Path $scriptPath -Parent) -Parent            

    $scriptPath | Get-ChildItem -r -filter AssemblyInfo.cs | ForEach-Object {            
        $filename = $_.Directory.ToString() + '\' + $_.Name            
        $filename + ' -> ' + $version            

        # If you are using a source control that requires to check-out files before             
        # modifying them, make sure to check-out the file here.            

  # Ensure the TFS command line tool is accessible            
  #$env:Path =$env:Path + ";D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\"            

  # For example, TFS will require the following command:            
        # tf checkout $filename            

        (Get-Content $filename) | ForEach-Object {            
            % {$_ -replace $fileVersionPattern, $fileVersion }            
        } | Set-Content $filename            
    }            
}            

#-------------------------------------------------------------------------------            
# Parse arguments.            
#-------------------------------------------------------------------------------            
if ($args -ne $null) {            
    $version = $args[0]            
    if (($version -eq '/?') -or ($version -notmatch "[0-9]+(\.([0-9]+|\*)){1,3}")) {            
        Help            
        return;            
    }            
} else {            
    $version =  Generate-VersionNumber            
}            

Update-AssemblyInfoFiles $version

Update the Solution name

Notes

The following PowerShell script can be used to update the solution name when building your project. Important items to note:

  • You should have updated the project file to generate a solution package on build.
  • The build events are triggered from the folder in which the assembly is build. So this will be either from [projectfolder]\bin\debug or [projectfolder]\bin\release.
  • The script makes a copy of the solution to a different location in my mapped source tree. Make sure the $copyPath is valid for you. If you just want to rename it, use Move-Item instead of Copy-Item.

Usage

To use this script, please it somewhere on your development machine and then start it in a post-build event (properties of your project > Build Events). In my case I start it as stated below. I use a relative path since it’s part of my TFS source and I don’t know the mapping of other developers:

if $(ConfigurationName) == Release powershell.exe ..\..\..\..\..\BuildScripts\UpdateWSPName.ps1

The script

#-------------------------------------------------------------------------------            
# Displays how to use this script.            
#-------------------------------------------------------------------------------            
function Help {            
    "Sets the WSP name to include a version`n"            
    ".\SetVersion.ps1 [VersionNumber]`n"            
    "   [VersionNumber]     The version number to set, for example: 1.1.9301.0"            
    "                       If not provided, a version number will be generated.`n"            
}            
            
#-------------------------------------------------------------------------------            
# Generate a version number.            
# Note: customize this function to generate it using your version schema.            
#-------------------------------------------------------------------------------            
function Generate-VersionNumber {            
    $today = Get-Date            
    return "1.0." + ( ($today.year - 2000) * 1000 + $today.DayOfYear )+ ".0"            
}            
             
#-------------------------------------------------------------------------------            
# Update version numbers of WSP file            
#-------------------------------------------------------------------------------            
function Update-WSPFile ([string] $version) {               
    # Determine the paths            
    $generatedPath = pwd            
    $copyPath = pwd            
    #$copyPath = Join-Path -Path (Split-Path -Path (Split-Path -Path (Split-Path -Path $copyPath -Parent) -Parent) -Parent)  -ChildPath "\_deployment\WSP\"            
            
    $generatedPath | Get-ChildItem -filter "*.wsp"| ForEach-Object {            
        # Remove previous version from WSPFolder            
        $copyPath | Get-ChildItem -filter ($_.Name.TrimEnd(".wsp") + "*.wsp") | ForEach-Object {            
            remove-item $_.fullname            
        }            
                    
        # Copy to deployment folder            
        $filenameOld = $_.Directory.ToString() + "\"+ $_.Name            
        $filenameNew = $copyPath.ToString() + "\" + $_.Name.TrimEnd(".wsp") + "_v" + $version + ".wsp"            
        Copy-Item $filenameOld $filenameNew            
    }            
}            
            
#-------------------------------------------------------------------------------            
# Parse arguments.            
#-------------------------------------------------------------------------------            
if ($args -ne $null) {            
    $version = $args[0]            
    if (($version -eq '/?') -or ($version -notmatch "[0-9]+(\.([0-9]+|\*)){1,3}")) {            
        Help            
        return;            
    }            
} else {            
    $version =  Generate-VersionNumber            
}            
            
Update-WSPFile $version

Credits

I made some small changes to the script which you can find here: http://www.luisrocha.net/2009/11/setting-assembly-version-with-windows.html

Ben Prins

What I want to remember about SharePoint

blog.frederique.harmsze.nl

my world of work and user experiences

Bram de Jager - Coder, Speaker, Author

Office 365, SharePoint and Azure