BizTalk 2016 – SFTP Adapter – How to set it up properly

Cutting a long story short I was exploring migrating a BizTalk 2013 solution to BizTalk 2016.  The solution uses SFTP and I wanted to migrate from the open source Blogical SFTP adapter to the out of the box SFTP adapter which has had some enhancements.  The documentation around this enhancement and in particular the setup is lacking.  It will not work out of the box from a BizTalk install unless you additionally setup WinSCP.  The problems are:

  1. The BizTalk documentation lists the wrong version on the dependencies, you need 5.7.7 not 5.7.5
  2. The WinSCP pages cover lots of other versions and it can be confusing because while their documentation is good and detailed, it talks about using WinSCP with the GAC which you will assume you need for BizTalk.  This is a red herring so dont read this bit unless you need to
  3. There is WinSCP and WinSCP .net library.  I got confused between the two and didnt initially realise I need both

To get this up and running the steps you need to follow are:

  1. Download WinSCP and the .net Library making sure you get the right versions
  2. Copy the .exe and .dll to the BizTalk installation folder
  3. DO NOT gac anything.  If you GAC the .net library it will not work because it expects WinSCP.exe to be in the same path so thats why they both go in the BizTalk installation folder

This is pretty simple enough in the end but I felt the easiest way to ensure you get the right version is to use NuGet to get version 5.7.7 and to make your life even simpler just use the powershell script below once you have setup your BizTalk environment and it will do it for you.  You just need to set the path for your BizTalk install folder and also where you want to download NuGet stuff to.

 

#Parameters
$downloadNoGetTo = “F:\Software\WinSCP”
$bizTalkInstallFolder = “F:\Program Files (x86)\Microsoft BizTalk Server 2016”

#Download NuGet
Write-Host “Downloading Nuget”
$sourceNugetExe = “https://dist.nuget.org/win-x86-commandline/latest/nuget.exe”
$targetNugetExe = “$downloadNoGetTo\nuget.exe”
Invoke-WebRequest $sourceNugetExe -OutFile $targetNugetExe

#Download the right version of WinSCP
Write-Host “Downloading WinSCP from NuGet”
Invoke-Expression “$targetNugetExe Install WinSCP -Version 5.7.7 -OutputDirectory $downloadNoGetTo”

#Copy WinSCP items to BizTalk Folder
Write-Host “Copying WinSCP Nuget to BizTalk Folder”
Copy-Item “$downloadNoGetTo\WinSCP.5.7.7\content\WinSCP.exe” $bizTalkInstallFolder
Copy-Item “$downloadNoGetTo\WinSCP.5.7.7\lib\WinSCPnet.dll” $bizTalkInstallFolder

 

Update 2017-07-22

My good friend Tom Canter has written a better version of my script which is a bit more robust and handy if your setup is different to my assumed one above.  Toms script is below, and if you would like to check out some more of toms work see his blogs below

 

#Parameters
Param([Parameter(Mandatory=$true)][string]$downloadNoGetTo)
$Continue = $true

$downloadNoGetToExists = Test-Path $downloadNoGetTo
if (-not $downloadNoGetToExists)
{
New-Item -Path $downloadNoGetTo -ItemType “Directory”
}
if (-not $downloadNoGetToExists)
{
$Continue = $false
Write-Host “An attempt to us the ” $downloadNoGetTo ” directory for a download target failed”
}
if ($Continue)
{
$bizTalkInstallFolder = (Get-Item Env:BTSINSTALLPATH).Value
if ($bizTalkInstallFolder -eq “”)
{
$bizTalkInstallFolder = (get-itemPropertyValue ‘HKLM:\SOFTWARE\Microsoft\BizTalk Server\3.0’ -Name ‘InstallPath’)
if ($bizTalkInstallFolder -eq “”)
{
$bizTalkInstallFolder = “C:\Program Files (x86)\Microsoft BizTalk Server 2016\”
}
}
$bizTalkInstallFolderExists = Test-Path $bizTalkInstallFolder
if (-not $bizTalkInstallFolderExists)
{
$Continue = $false
Write-Host “The BizTalk Installation was not found by inspecting the enviornment or registry.”
}
if ($Continue)
{
#Download NuGet
$sourceNugetExe = “https://dist.nuget.org/win-x86-commandline/latest/nuget.exe”
Write-Host “Downloading Nuget from ” $sourceNugetExe
$targetNugetExe = “$downloadNoGetTo\nuget.exe”
Invoke-WebRequest $sourceNugetExe -OutFile $targetNugetExe
$targetNugetExeExists = Test-Path $targetNugetExe
if (-not $targetNugetExeExists)
{
$Continue = $false
Write-Host “The download of the Nuget EXE from ” $sourceNugetExe ” did not succeed”
}
if ($Continue)
{
#Download the right version of WinSCP
Write-Host “Downloading WinSCP from NuGet ” + $sourceNugetExe
Invoke-Expression “$targetNugetExe Install WinSCP -Version 5.7.7 -OutputDirectory $downloadNoGetTo”
$WinSCP = “$downloadNoGetTo\WinSCP.5.7.7\content\WinSCP.exe”
$WinSCPDll = “$downloadNoGetTo\WinSCP.5.7.7\lib\WinSCPnet.dll”
$WinSCPExists = Test-Path $WinSCP
$WinSCPDLLExists = Test-Path $WinSCPDll
if (-not $WinSCPExists -or -not $WinSCPDLLExists)
{
$Continue = $false
Write-Host “WinSCP 5.7.7 was not properly downloaded”
}
if ($Continue)
{
#Copy WinSCP items to BizTalk Folder
Write-Host “Copying WinSCP Nuget to BizTalk Folder”
Copy-Item $WinSCP $bizTalkInstallFolder
Copy-Item $WinSCPDll $bizTalkInstallFolder
$WinSCPBTSExists = Test-Path “$bizTalkInstallFolder\WinSCP.exe”
$WinSCPDLLBTSExists = Test-Path “$biztalkInstallFolder\WinSCPnet.dll”
if (-not $WinSCPBTSExists)
{
$Continue = $false
Write-Host “The WinSCP.exe file was not properly copied to the target folder ” $bizTalkInstallFolder
}
if (-not $WinSCPDLLBTSExists)
{
$Continue = $false
Write-Host “The WinSCPnet.exe file was not properly copied to the target folder ” $bizTalkInstallFolder
}
}
}
}
if (-not $Continue)
{
Write-Host “Something went wrong during installation and the installation is not working”
Write-Host “Please inspect the errors above and resolve them”
}
else
{
Write-Host “WinSCP has been properly installed for BizTalk’s SFTP Adapter”
}
}