SharePoint 2013 Design Packages: Import with PowerShell (Part 2 of 2)

Last Thursday I wrote about “Exporting SharePoint 2013 Design Packages with PowerShell”. Today I’d like to show you the import function. This functions can be used to handle with SharePoint 2013 Design Packages with PowerShell, e.g. in deployment scenarios. Therefore it should by very useful. (I hope so 😉 ) FEEDBACK WELCOME!!!

You can download the scripts here:

http://gallery.technet.microsoft.com/Export-and-Import-0f41b376

Here you can find the blog article about “Export-SPDesignPackage”: https://blog.kenaro.com/2013/02/14/sharepoint-2013-design-packages-export-with-powershell-part-1-of-2

 

The import function is called “Import-SPDesignPackage” and here are the details:

Import-SPDesignPackage

Here are some samples

#First sample

Import-SPDesignPackage -SiteUrl "http://sharepoint.local/publishing" -ImportFileName "C:\temp\publishing2.wsp" -PackageName "P2" -Apply $true

#Second sample


(
    @{ SiteUrl ="http://sharepoint.local/sites/publishing1";
       ImportFileName ="C:\temp\publishing1.wsp";
       PackageName ="P1";
       Apply=$true
    },
    @{ SiteUrl ="http://sharepoint.local/sites/publishing2";
       ImportFileName ="C:\temp\publishing2.wsp";
       PackageName ="P2";
       Apply=$true
    }
) | New-ObjectFromHashtable | Import-SPDesignPackage

The first sample shows you how to import one design package to a dedicated site. By using the “Apply” parameter the design package will be applied to the site immediately.

The second sample shows you hot to import two different packages to two different site collections. In the sample I use a hashtable for input parameters. They are assigned to the function parameters by “property name binding”. See “http://technet.microsoft.com/en-us/library/hh847743.aspx”: Section “ValueFromPipelineByPropertyName”:

[…]
For example, if the function has a ComputerName parameter, and the 
piped object has a ComputerName property, the value of the ComputerName
property is assigned to the ComputerName parameter of the function.

The following example declares a ComputerName parameter that is 
mandatory and accepts input from the ComputerName property of the 
object that is passed to the function through the pipeline.
[…]

Some more details about that. Skip it if you are not interested…

 

<begin/>

 

This “property name binding” does not work with hashtables. Therefore I created a helper function “New-ObjectFromHashtable” that creates a PowerShell object (“PSObject”). This function is generic. (It’s also included in the script files.)

 

On the one hand with “new-object System.Management.Automation.PSObject” you can create a new “empty” PowerShell object that can be used in your script as every other object, e.g. a SharePoint object like an instance of class SPSite. With cmdlet “Add-Member” you can add new members to the object. – On the other hand you have a hashtable with named values. You can access the collection of names = keys and with each key you can access the value. – Let’s combine it: You can iterate through the keys collection and create a new member in an empty PSObject instance.

 

functionNew-ObjectFromHashtable {
    #written by Ingo Karstein (https://blog.kenaro.com)# v1.0#Use this function to convert a hashtable to a PowerShell object ("PSObject"), e.g. for using hashtables for property name binding in# PowerShell pipelines
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true)]
        [Hashtable]
        $Hashtable
    )

    begin {
        $results= @()
    }

    process {
        $r=new-objectSystem.Management.Automation.PSObject$Hashtable.Keys | % {
            $key=$_$value=$Hashtable[$key]
            $r | Add-Member-MemberTypeNoteProperty-Name$key-Value$value-Force
        }

        $results+=$r
    }

    end {
        $results
    }

}

The resulting object can be passed to each “property name binding” enabled cmdlet. – The PowerShell engine tries to match input object property names and cmdlet parameter names. If there is a match the input object property value gets assigned to the cmdlets input parameter.

 

The cmdlet can also convert a list of hashtables to a list of objects. That is used in the “Import-SPDesignPackage” script.

 

<end/>

Parameters

Parameter Name Parameter Set Name Mandatory? Position Description
SiteUrl Default Yes 0 Site Url for import
Site Site Yes 0 SPSite object for import
ImportFileName DefaultSite Yes 1 Filename and path of the design package for import
Apply DefaultSite Yes 2 $true = Apply the design package after import$false = Only install the design package for later activation
PackageName DefaultSite No 3 Package name. If not specified it uses the file name without extension. The package name will be used for naming the imported file in the solution gallery of the site collection
MajorVersion DefaultSite No Version number of the design package. If not specified it uses “1” for the major version.
MinorVersion DefaultSite No Version number of the design package. If not specified it uses “0” for the minor version.

 

The function returns an object for each processed (or not processed) site collection:

image

Object Property Description
SiteUrl Url of the processed site
Success $true = Import and “Apply” (if specified) was successful
InputFileFound $true = File found$false = File not found
InputFileExtensionValid $true = Input file has extension “.wsp”$false = Input file hat not extension “.wsp”
SiteFound $true = The specified site was found
SolutionFileName The name of the solution is auto generated from package name or file name and major and minor version number. This is the name of the package in the site collections solution gallery.
PackageAlreadyExsits $true = the solution does already exist in the solution gallery.

Some additions

The import process requires the package to be stored inside the site collection before the the last input step. Therefore the function creates a folder named “tmp_importspdesignpackage_15494B80-89A0-44FF-BA6C-208CB6A053D0” in the site collections root web root folder. In this folder the package gets uploaded. From the location the package is imported. The folder will be deleted after successful or not failed import.

Create Provider Hosted High Trust App for SharePoint 2013 (Short Guide)

About this topic there are several guides. I can’t say that I have to add anything new 😉 But… as always… this blog is a kind of notebook for me. So I post this small guide.

1. You need to have or create a certificate that is used as “security token issuer”. This certificate can be created using IIS Manager or any other tool.

I use “XCA” (http://xca.sourceforge.net/). With that tool you can create your own Certification Authority. (Of course you can use the Windows Server Certification Authority.) – I use XCA because it’s easy to manage this kind of certificates there and I use the certificates on several dev machines.

If you do so too you need to create a root certificate for your Certification Authority and install it in the “Trusted Root Certification Authrities” of your Local Computer (not only your personal cert store).

image

2. The first step is to register (or create) the certificate within IIS Manager:

Right click on the server node and choose “Server Certificates”.

image

Use “Import” to apply an existing certificate. Or use “Create Self-Signed Certificate” to create a new certificate.

image

This are the steps to create a new self-signed certificate:

image

After commit (“OK”) you need to export the certificate with private key and a second time without private key.

image

image

image

image

image

image

image

image

3. Open Visual Studio 2012. Create a new project:

image

image

image

For “Issuer ID” you need to create a GUID using Visual Studio or PowerShell. Here is the PowerShell way:

Start PowerShell.

image

Enter:

[guid]::newguid().tostring().tolower()

image

Copy to output into the dialog in Visual Studio 2012.

image

4. Open a Windows PowerShell ISE, create a new PowerShell script file and copy the following code to it. Most of the code comes from here: http://msdn.microsoft.com/en-us/library/fp179901.aspx. With some additions from Steve Peschka’s Blog articles: http://blogs.technet.com/b/speschka/archive/2012/09/27/another-apps-for-sharepoint-tip-with-the-error-quot-the-issuer-of-the-token-is-not-a-trusted-issuer-quot.aspx and http://blogs.technet.com/b/speschka/archive/2012/11/01/more-troubleshooting-tips-for-high-trust-apps-on-sharepoint-2013.aspx.

###http://msdn.microsoft.com/en-us/library/fp179901.aspx

$publicCertPath = "C:\root\High_Trust_App_1.cer"

#$issuerId = [System.Guid]::NewGuid().ToString()
$issuerId = ([Guid]"4729b8e2-073a-47f0-8538-105ec865f3d2").ToString()

$spurl ="http://sharepoint.local"

$spweb = Get-SPWeb $spurl

$sc = Get-SPServiceContext $spweb.site

$realm = Get-SPAuthenticationRealm -ServiceContext $sc

$certificate = Get-PfxCertificate $publicCertPath

$fullIssuerIdentifier = $issuerId + '@' + $realm

New-SPTrustedSecurityTokenIssuer -Name $issuerId -Certificate $certificate -RegisteredIssuerName $fullIssuerIdentifier –IsTrustBroker

iisreset

write-host "Full Issuer ID: " -nonewline
write-host $fullIssuerIdentifier -ForegroundColor Red
write-host "Issuer ID for web.config: " -nonewline
write-host $issuerId -ForegroundColor Red

#Disable OAuth HTTPS requirement FOR DEV!!

$serviceConfig = Get-SPSecurityTokenServiceConfig
$serviceConfig.AllowOAuthOverHttp = $true
$serviceConfig.Update()


New-SPTrustedRootAuthority -Name "$($certificate.Subject)_$($certificate.Thumbprint)" -Certificate $certificate 

Be sure to change any parameter that does not fit your environment. After that the script should look like this:

image

 

The following script lines are needed in order to get it working using a SharePoint site without SSL!!

$serviceConfig = Get-SPSecurityTokenServiceConfig

$serviceConfig.AllowOAuthOverHttp = $true

$serviceConfig.Update()

If you use SSL (e.g. https://sharepoint.local) you can skip this.

No other steps are required. I’ve tested this several times with always fresh SP 2013 environments because I had some difficulties to get this set up.

5. At this point I have not changed anything in Visual Studio after creating the project(s) (there are two) through the wizard.

Check the “web.config” file in you web project.

image

There you find the issuer ID again.

6. Now run the project. You need to trust the app.

image

image

image

Short Note About Error While Creating Search Service Application for SharePoint 2013 by PowerShell: “Value cannot be null. Parameter name: indexLocation”

Today I got an error while creating a Search Service Application for SharePoint 2013:

PS C:\> $SearchSA = New-SPEnterpriseSearchServiceApplication –Name “Enterprise Search Service Application” –ApplicationPool “Search App Pool” –DatabaseName “Search”

New-SPEnterpriseSearchServiceApplication : Value cannot be null.
Parameter name: indexLocation

To resolve this I just started the Search Service Instance on each (search) server in the farm and set it’s “DefaultIndexLocation” property.

After that I could create the Search Service App.

PS snippet:

"SearchServer1", "SearchServer2" | % {
    $svcInst = (Get-SPServer -Identity $_).serviceinstances | ? { $_.GetType().FullName -eq "Microsoft.Office.Server.Search.Administration.SearchServiceInstance" }
    $svcInst.DefaultIndexLocation = $defaultIndexLocation
    $svcInst.Update()
    $svcInst.Provision()
}

This did it.