In this article, let us see how to Export and Import Nintex Forms in SharePoint using CSOM PowerShell Script.
The code is self-explanatory.
01.ExportNintexForms.ps1
function Export-NintexForm {
<# .SYNOPSIS Exports a Nintex form XML to a local directory. .DESCRIPTION Exports a Nintex form XML to a local directory. #>
[CmdletBinding()]
[OutputType([string])]
param(
[string]$WebUrl = $(throw "Required parameter -WebUrl missing"),
[string]$ListName = $(throw "Required parameter -ListName missing"),
[string]$FilePath = $(throw "Required parameter -FilePath missing")
)
begin {
if(!(Get-PnPConnection)) {
throw "There is no PnPConnection"
}
Write-Host "---- Exporting Nintex form for '$ListName' ----" -ForegroundColor Yellow
}
process {
$xmlFilePath ="";
$list = Get-PnPList -Identity $ListName
$addressUrl = "$WebUrl/_vti_bin/NintexFormsServices/NfRestService.svc/GetFormXml"
$addressUri = New-Object System.Uri($addressUrl)
# Create the web request
[System.Net.HttpWebRequest] $request = [System.Net.WebRequest]::Create($addressUri)
# Add authentication to request
$request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
# Set type to POST
$request.Method = "POST";
$request.ContentType = "application/json; charset=utf-8";
$request.Accept = "application/json, text/javascript, */*; q=0.01"
$request.Headers.Add("X-Requested-With", "XMLHttpRequest")
# Create the data we want to send
$id = "{$($list.ID)}"
$contentTypeID = "{0x01000***********}" #Give the content Type ID
$data = "{`"contentTypeId`": `"$contentTypeID`", `"listId`": `"$id`" }"
# Create a byte array of the data we want to send
$utf8 = New-Object System.Text.UTF8Encoding
[byte[]] $byteData = $utf8.GetBytes($data.ToString())
# Set the content length in the request headers
$request.ContentLength = $byteData.Length;
# Write data
try {
$postStream = $request.GetRequestStream()
$postStream.Write($byteData, 0, $byteData.Length);
}
catch [Exception]{
Write-Host -f red $_.Exception.ToString()
}
finally {
if($postStream) { $postStream.Dispose() }
}
# Get response
try {
[System.Net.HttpWebResponse] $response = [System.Net.HttpWebResponse] $request.GetResponse()
# Get the response stream
[System.IO.StreamReader] $reader = New-Object System.IO.StreamReader($response.GetResponseStream())
try {
$strResult = $reader.ReadToEnd()
$xml = [System.Web.HttpUtility]:: HtmlDecode($strResult)
#Once Deserialized XML will get generated with below string tag, insted of going for XML manupulation I have removed the string tag from the xml
$xmlExcludedStringTag = $xml -replace "" , "";
$xmlExcludedStringTag = $xmlExcludedStringTag -replace "" , "";
$timeStampString = [DateTime]::Now.ToString("yyyyMMdd-HHmmss")
# Get XML New File path
$xmlFilePath = "$FilePath$($ListName)Form-$timeStampString.xml";
#Save XML File to Disk
#$xmlExcludedStringTag | Out-File $xmlFilePath
$enc = [system.Text.Encoding]::Unicode
$encodedData = $enc.GetBytes($xmlExcludedStringTag)
$encodedData | Set-Content $xmlFilePath -Encoding Byte
Write-Host "Nintex form exported successfully to '$xmlFilePath'" -ForegroundColor Green
return $xmlFilePath
}
catch [Exception] {
Write-Host -f red $_.Exception.ToString()
}
}
catch [Exception] {
Write-Host -f red $_.Exception.ToString()
}
finally {
if($response) { $response.Dispose() }
}
$xmlFilePath
}
end { }
}
02.ImportNintexForms.ps1
function Read-FileBytes($Filename)
{
try {
[system.io.stream] $stream = [system.io.File]::OpenRead($Filename)
try {
[byte[]] $filebytes = New-Object byte[] $stream.length
[void] $stream.Read($filebytes, 0, $stream.Length)
return $filebytes
}
finally {
$stream.Close()
}
}
catch {
return
}
return $true;
}
function Get-FormDigest($webUrl )
{
[System.Reflection.Assembly]::LoadWithPartialName("System.IO") >> $null
#$formDigestRequest = [Microsoft.SharePoint.Utilities.SPUtility]::ConcatUrls($webUrl, "_api/contextinfo")
$formDigestRequest = $webUrl + "/_api/contextinfo"
$formDigestUri = New-Object System.Uri($formDigestRequest)
$credCache = New-Object System.Net.CredentialCache
$credCache.Add($formDigestUri, "NTLM", [System.Net.CredentialCache]::DefaultNetworkCredentials)
$spRequest = [System.Net.HttpWebRequest] [System.Net.HttpWebRequest]::Create($formDigestRequest)
$spRequest.Credentials = $credCache
$spRequest.Method = "POST"
$spRequest.Accept = "application/json;odata=verbose"
$spRequest.ContentLength = 0
[System.Net.HttpWebResponse] $endpointResponse = [System.Net.HttpWebResponse] $spRequest.GetResponse()
[System.IO.Stream]$postStream = $endpointResponse.GetResponseStream()
[System.IO.StreamReader] $postReader = New-Object System.IO.StreamReader($postStream)
$results = $postReader.ReadToEnd()
$postReader.Close()
$postStream.Close()
#Get the FormDigest Value
$startTag = "FormDigestValue"
$endTag = "LibraryVersion"
$startTagIndex = $results.IndexOf($startTag) + 1
$endTagIndex = $results.IndexOf($endTag, $startTagIndex)
[string] $newFormDigest = $null
if (($startTagIndex -ge 0) -and ($endTagIndex -gt $startTagIndex))
{
$newFormDigest = $results.Substring($startTagIndex + $startTag.Length + 2, $endTagIndex - $startTagIndex - $startTag.Length - 5)
}
return $newFormDigest
}
function Nintex-GetJsonFormFromXml($FileName)
{
[System.Reflection.Assembly]::LoadWithPartialName("Nintex.Forms.SharePoint") >> $null
[System.Reflection.Assembly]::LoadWithPartialName("Nintex.Forms") >> $null
[byte[]] $fileBytes = Read-FileBytes -FileName $FileName
try
{
$form = [Nintex.Forms.FormsHelper]::XmlToObject([Nintex.Forms.NFUtilities]::ConvertByteArrayToString($fileBytes))
}
catch [Exception]
{
$form = [Nintex.Forms.FormsHelper]::XmlToObject([Nintex.Forms.NFUtilities]::ConvertByteArrayToString($fileBytes, [System.Text.Encoding]::UTF8))
}
$form.LiveSettings.Url = ""
$form.LiveSettings.ShortUrl = ""
$form.RefreshLayoutDisplayNames()
$form.Id = [guid]::NewGuid()
$json = [Nintex.Forms.FormsHelper]::ObjectToJson($form);
return $json;
}
function Import-NintexForm {
<# .SYNOPSIS Imports a Nintex form XML to a local directory. .DESCRIPTION Imports a Nintex form XML to a local directory. #>
[CmdletBinding()]
[OutputType([string])]
param(
[string]$webUrl = $(throw "Required parameter -WebUrl missing"),
[string]$listName = $(throw "Required parameter -ListName missing"),
[string]$filePath = $(throw "Required parameter -FilePath missing")
)
begin {
if(!(Get-PnPConnection)) {
throw "There is no PnPConnection"
}
Write-Host "---- Importing Nintex form for '$listName' ----" -ForegroundColor Yellow
}
process {
$list = Get-PnPList -Identity $listName
$formDigest = Get-FormDigest $webUrl
$addressUrl = $webUrl + "/_vti_bin/NintexFormsServices/NfRestService.svc/PublishForm"
$addressUri = New-Object System.Uri($addressUrl)
# Create the web request
[System.Net.HttpWebRequest] $request = [System.Net.WebRequest]::Create($addressUri)
# Add authentication to request
$request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
# Set type to POST
$request.Method = "POST";
$request.ContentType = "application/json; charset=utf-8";
$request.Accept = "application/json, text/javascript, */*; q=0.01"
$request.Headers.Add("X-RequestDigest", $formDigest);
$request.Headers.Add("X-Requested-With", "XMLHttpRequest")
$form = Nintex-GetJsonFormFromXml -FileName $filePath
# Create the data we want to send
$id = "{$($list.ID)}"
$data = "{`"contentTypeId`": `"`", `"listId`": `"$id`", `"form`": $form }"
# Create a byte array of the data we want to send
$utf8 = New-Object System.Text.UTF8Encoding
[byte[]] $byteData = $utf8.GetBytes($data.ToString())
# Set the content length in the request headers
$request.ContentLength = $byteData.Length;
# Write data
try {
$postStream = $request.GetRequestStream()
$postStream.Write($byteData, 0, $byteData.Length);
}
catch [Exception]{
write-host -f red $_.Exception.ToString()
}
finally {
if($postStream) { $postStream.Dispose() }
}
# Get response
try {
[System.Net.HttpWebResponse] $response = [System.Net.HttpWebResponse] $request.GetResponse()
# Get the response stream
[System.IO.StreamReader] $reader = New-Object System.IO.StreamReader($response.GetResponseStream())
try {
$strResult = $reader.ReadToEnd()
$jsonResult = ConvertFrom-Json $strResult
$jsonResult
$jsonResult.PublishFormResult.Url
$jsonResult.PublishFormResult.Version
}
catch [Exception] {
write-host -f red $_.Exception.ToString()
}
}
catch [Exception] {
write-host -f red $_.Exception.ToString()
}
finally {
if($response) { $response.Dispose() }
}
}
end{}
}
Run.ps1
#=========================================== Description Start ========================================= #
# Deploy from a List
# Author : Sathish Nadarajan
# Date : 03-Feb-2021
#=========================================== Description End====================================== #
# ============================================ PreRequisites Start ================================= #
#Get-Module -Name *pnp*
#Pre Req - SharePoint PnP PowerShell Version 2.25.1804.1
#=============================================PreRequisites End =============================== #
#============================================= Initial Setup Start =============================== #
cls
$Host.UI.RawUI.WindowTitle = "-- Deploy Assets --"
$StartDate = Get-Date
Write-Host -ForegroundColor White "------------------------------------"
Write-Host -ForegroundColor White "| Deploy Assets |"
Write-Host -ForegroundColor White "| Started on: $StartDate |"
Write-Host -ForegroundColor White "------------------------------------"
#Add-PSSnapin Microsoft.SharePoint.PowerShell
$LogTime = Get-Date -Format yyyy-MM-dd_hh-mm-ss
$scriptBase = split-path $SCRIPT:MyInvocation.MyCommand.Path -parent
Set-Location $scriptBase
# Create Log File Folder3
if(!(TEST-PATH ".Logs-$LogTime")){
NEW-ITEM ".Logs-$LogTime" -type Directory
}
# Assign the Log and Progress Files
$TranscriptFile = ".Logs-$LogTimeDeploy.Transcript.rtf"
try{
stop-transcript|out-null
}
catch [System.InvalidOperationException]{}
start-transcript $TranscriptFile
#============================================= Initial Setup End =============================== #
# ============================================ Setup Input Paths Start ================================= #
#connect to the SharePoint list
$sourceWebUrl = 'http://SiteCollectionURL/sites/newsite/'
$sourceListname = "MyList"
$outputFolderPath = ".Logs-$LogTime"
$targetWebUrl = 'http://TargetSiteCollectionURL/sites/newsite/'
$targetListname = "TargetMyList"
# ============================================ Setup Input Paths End ================================= #
Import-Module ". 1.ExportNintexForms.ps1"
Import-Module ". 2.ImportNintexForms.ps1"
Write-Host "Begin to Execute.." -ForeGroundColor Yellow
"Begin to Execute..." | Out-File -FilePath $TranscriptFile -Append
Connect-PnPOnline -Url $sourceWebUrl -CurrentCredentials -ErrorAction Inquire
$nintexFormXMLPath = Export-NintexForm $sourceWebUrl $sourceListname $outputFolderPath
Import-NintexForm $targetWebUrl $targetListname $nintexFormXMLPath
Disconnect-PnPOnline
Write-Host "Update Completed.. Press Enter to Exit" -ForeGroundColor Green
try{
stop-transcript|out-null
}
catch [System.InvalidOperationException]{}
Happy Coding
Sathish Nadarajan
Leave a comment