Sep 262007

We are implementing a new solution for a client that requires that we connect to an FTP site to gather their data. This is normal stuff. The challenge came when the requirement was brought to our attention that the FTP password was going to be changed every 30 days. We did not want to have to coordinate when the password was going to change and who was going to be doing it. We needed a way to programmatically change the password of the FTP receive location so we did not have to baby sit the receive location.

Taking the SDK as our base, we developed some code that interrogated the ReceivePort, its RecieveLocations, and then once found it, would modify the IReceiveLocation.TransportTypeData.

What started off as a simple request to change the password ballooned to many other properties of the FTP adapter. I was happily coding until I got to the URI, and realized that it had a bunch of downstream affect, where I then gave up. The following code only deals with a few of the properties that can be changed in the FTP adapter, but it gives you a starting point to develop more code against.

This code assumes a few things; you accept the disclaimer to the right and that you already know which port and which receive location you want to change, and it will go in an change the particular property in the adapter.

We also had the requirement to change a pipeline component password (it picks up a zipped file that has a password, so the same logic can be used, and instead of modifying location.TransportTypeData, you simply modified IReceiveLocation.ReceivePipelineData.

using System; using System.Collections.Generic; using System.Text; using Microsoft.BizTalk.ExplorerOM; namespace ChangeConfigration { public enum Properties { Password, UserName, RepresentationType, MaximumNumberOfFiles, PassiveMode, FirewallType, FirewallPort, PollingUnitOfMeasure, pollingInterval, ErrorThreshold, MaxFileSize } public class ReceiveLocations { static void ChangeExistingFTPLocation(string ReceivePort, string ReceiveLocation, Properties PropertyType, string NewProperty) { string thisPropertyType; switch ((int)PropertyType) { case 0:thisPropertyType = "password"; break; case 1:thisPropertyType = "userName"; break; case 2:thisPropertyType = "representationType"; break; case 3: thisPropertyType = "maximumNumberOfFiles"; break; case 4: thisPropertyType = "passiveMode"; break; case 5: thisPropertyType = "firewallType"; break; case 6: thisPropertyType = "firewallPort"; break; case 7: thisPropertyType = "pollingUnitOfMeasure"; break; case 8: thisPropertyType = "pollingInterval"; break; case 9: thisPropertyType = "errorThreshold"; break; case 10: thisPropertyType = "maxFileSize"; break; default: thisPropertyType = "unknown"; break; } BtsCatalogExplorer root = new BtsCatalogExplorer(); try { root.ConnectionString = "Server=.;Initial Catalog=BizTalkMgmtDb;Integrated Security=SSPI;"; //Enumerate the receive locations in each of the receive ports. foreach (ReceivePort receivePort in root.ReceivePorts) { if (receivePort.Name == ReceivePort) { foreach (ReceiveLocation location in receivePort.ReceiveLocations) if (location.Name == ReceiveLocation) { string OldTransportTypeData = location.TransportTypeData; int start = OldTransportTypeData.IndexOf("<" + thisPropertyType + ">") + Convert.ToString(thisPropertyType).Length + 8; int end = OldTransportTypeData.IndexOf("</" + thisPropertyType + ">"); int length = end - start; string ExistingProperty = OldTransportTypeData.Substring(start, length); string NewTransportTypeData = OldTransportTypeData.Replace( "<" + thisPropertyType + ">" + ExistingProperty + "</" + thisPropertyType + ">", "<" + thisPropertyType + ">" + NewProperty + "</" + thisPropertyType + ">"); location.TransportTypeData = NewTransportTypeData; location.Enable = true; } } } root.SaveChanges(); } catch (Exception e)//If it fails, roll-back all changes. { throw e; root.DiscardChanges(); } } } }

This goes without saying that we picked up the file and then waited for a given amount of time and then changed the password for the ftp receive location and logged what that password is in BAM so that if we ever needed to find out what the password is, we could look at the BAM view.

Yes, I know I have the possibility of getting hate mail by stating that I am going to log the password as a clear text value in BAM, however, using the IReceiveLocation Interface API, I can see what the password is in clear text anyway. I might as well make it easy for the support staff to log into an internal web site and see what the password currently is so they can go out to the FTP site and see if there are files outstanding than having to call up the client to find out what the password is, or having to call the BizTalk team to have them have a program that goes in and pulls the data and sees what the password is and tells them what it is. (whew, I almost ran out of breath with that run-on sentence!)