27 Nisan 2021 Salı

AX 2012 - SFTP Download

SFTP service of one of our customers had upgraded. Old code had been written with Tamir.SharpSSH.DLL which didn't upgraded since 2007. Unfortunately service won't work with Tamir anymore, given with "Tamir.SharpSsh.jsch.JSchException: Algorithm negotiation fail" error. None of the solutions about I fond at internet worked with me. 

I see SSH.NET adviced ad forums. When I tried to copy SSH.NET's DLL to AX folders and add as reference unfortunately I see an optional paremeter of download method uses  Action<ulong> data type which doesn't supported by X++ and worse X++ makes this optional parameter as mandatory. First tried a solution which I see at a blog suggest overload the method, seem a good solution because of SSH.NET is an open source library. But I got some errors when compiled and didn't messed with these errors, instead of wrote a small C# code and build a small DLL. It was easier and in this case never need code update and recompile with new SSH.NET versions.

Compiled this code with just a few modifications which I found a blog page written for Dynamics 365 F&O:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
using System.IO;

namespace SSHNet2
{
    public class SSHNet2
    {
        public SftpClient sftpClient;
        public void OpenSFTPConnection(string host, int port, string username, string password)
        {
            if (this.sftpClient == null)
            {
                this.sftpClient = new Renci.SshNet.SftpClient(host, port, username, password);
            }
            if (!this.sftpClient.IsConnected)
            {
                this.sftpClient.Connect();
            }
        }
        public List<string> GetDirectories(string path)
        {
            return this.sftpClient.ListDirectory(path).Select(n => n.Name).ToList();
        }
        public void MoveFile(string sourcePath, string destinationPath, bool isPosix)
        {
            this.sftpClient.RenameFile(sourcePath, destinationPath, isPosix);
        }

         public void DeleteFile(string sourcePath)
        {
            this.sftpClient.DeleteFile(sourcePath);
        }
        public Stream DownloadFile(string sourcePath)
        {
            var memoryStream = new MemoryStream();
            this.sftpClient.DownloadFile(sourcePath, memoryStream);
            memoryStream.Position = 0;
            return memoryStream;
        }
    }
}

Copied new DLL and SSH.NET's own DLL to AX folders and my SFTP download problem is solved:

System.IO.StreamReader          streamReader; 

System.IO.StreamWriter          streamWriter; 

 SSHNet2.SSHNet2                 sftp = new SSHNet2.SSHNet2();

System.IO.Stream                stream;

 sftp.OpenSFTPConnection(_RemoteAddress,any2int(_RemotePort), _RemoteUser, _RemotePassword);

            stream = sftp.DownloadFile(_RemoteFileName);

streamReader = new System.IO.StreamReader(stream);

streamWriter = new System.IO.StreamWriter("c:\test\test.txt");

streamWriter.Write(_StreamReader.ReadToEnd());

streamWriter.Flush();

streamWriter.Close();

streamReader.Close();