We use PuTTY (psftp.exe), which is freely available.
PuTTY download page
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
PuTTY psftp.exe documentation
http://the.earth.li/~sgtatham/putty/0.53b/htmldoc/Chapter6.html
We call psftp.exe using command line parameters and, in more complicated cases, a script file written in psftp's scripting language.
Psftp.exe is called from a batch file (.bat) which enables us to respond to prompts that psftp generates and also provide a basic level of error checking.
I did not yet add code to detect that psftp.exe is available in the working directory or the PATH environment variable. If it is not available, the example code will appear to run and give no indication that it failed.
So, here's the code with more specific in-code notes/documentation:
//NDP 12/9/2012 - example job code to connect via SFTP (SSH File Transfer Protocol, aka Secure FTP) and transfer a file from Microsoft Dynamics AX 2012
static void uploadFileWithPSFTP(Args _args)
{
TextIo textIoFile;
Set permissionSet;
FileName filePath, filename, batchFileName, scriptFileName, errorThrownFile, errorThrownFileWithPath;
InteropPermission interopPerm;
System.Diagnostics.Process process;
System.Diagnostics.ProcessStartInfo processStartInfo;
;
filePath = 'c:\\Export'; //local working folder
fileName = 'fileToSend.txt'; //file existing in local working folder that is to be sent via SFTP
errorThrownFile = 'ftpError.txt'; //file used to detect exit codes from psftp
errorThrownFileWithPath = filePath + '\\' + errorThrownFile;
batchFileName = filePath + '\\sendfile.bat'; //batch file used to call psftp.exe
scriptFileName = filePath + '\\psftp.script'; //script file used to instruct psftp to follow scripted steps.
//delete file batch and script file if they exists
interopPerm = new InteropPermission(InteropKind::ClrInterop);
interopPerm.assert();
if(System.IO.File::Exists(batchFileName))
{
System.IO.File::Delete(batchFileName);
}
if(System.IO.File::Exists(scriptFileName))
{
System.IO.File::Delete(scriptFileName);
}
CodeAccessPermission::revertAssert();
//write the batch file
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(batchFileName, "W"));
CodeAccessPermission::assertMultiple(permissionSet);
textIoFile = new TextIo(batchFileName , "W", 0);
CodeAccessPermission::revertAssert();
//the 'echo n|' in the line below will answer 'no' to the question that psftp will ask to trust/store the certificate from the ftp server.
textIoFile.write(strFmt('echo n|psftp ftpaddress.com -P 23 -l username -pw password -b %1',scriptFileName));
//this creates an empty file if the exit code/errorlevel from psftp is 1 (meaning there was an error)
textIoFile.write(strFmt('IF ERRORLEVEL 1 echo. 2>%1',errorThrownFile));
textIoFile = null;
//write the script file that psftp uses
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIoPermission(scriptFileName, "W"));
CodeAccessPermission::assertMultiple(permissionSet);
textIoFile = new TextIo(scriptFileName , "W", 0);
CodeAccessPermission::revertAssert();
textIoFile.write('cd /subfolder'); //change folders on the FTP server, optional
textIoFile.write(strFmt('put %1',fileName)); //send the file
textIoFile.write('quit');
textIoFile = null;
//run the batch file
new InteropPermission(InteropKind::ClrInterop).assert();
process = new System.Diagnostics.Process();
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.set_FileName(batchFileName);
processStartInfo.set_WorkingDirectory(filePath);
process.set_StartInfo(processStartInfo);
process.Start();
process.WaitForExit();
//process.get_ExitCode() does not seem to be implemented in AX 2012. Instead we're using the 'errorthrownfile' method above.
CodeAccessPermission::revertAssert();
interopPerm = new InteropPermission(InteropKind::ClrInterop);
interopPerm.assert();
//delete the files that were used to facilitate the transfer
if(System.IO.File::Exists(batchFileName))
{
System.IO.File::Delete(batchFileName);
}
if(System.IO.File::Exists(scriptFileName))
{
System.IO.File::Delete(scriptFileName);
}
//determinte if an error was thrown by psftp. Clean up the error indicator file.
if(System.IO.File::Exists(errorThrownFileWithPath))
{
warning ("Error occured during SFTP transfer");
System.IO.File::Delete(errorThrownFileWithPath);
}
else
{
info("SFTP transfer was successful");
}
//delete the file that was sent - you might not want to do this in your application
if(System.IO.File::Exists(fileName))
{
System.IO.File::Delete(fileName);
}
CodeAccessPermission::revertAssert();
}
Have fun!
Thank you!
ReplyDeleteHi Sir,
ReplyDeletePlease give me the steps to do It in Ax 4.0
Regards,
Johnkrish