I had a question from someone that had an interesting scenario: they had a series of reports that their manufacturing company generates on a daily basis, and they wanted to automate uploading those files over FTP from their factory to their headquarters. Their existing automation created report files with names like Widgets.log, Sprockets.log, Gadgets.log, etc.
But they had an additional request: they wanted the reports dropped into folders based on the day of the week. People in their headquarters could retrieve the reports from a share on their headquarters network where the FTP server would drop the files, and anyone could look at data from anytime within the past seven days.
This seemed like an extremely trivial script for me to write, so I threw together the following example batch file for them:
for /f "usebackq delims= " %%a in (`date /t`) do (
echo open MyServerName>ftpscript.txt
echo mkdir %%a>>ftpscript.txt
echo cd %%a>>ftpscript.txt
echo mput *.log>>ftpscript.txt
This would have worked great for most scenarios, but they pointed out a few problems in their specific environment: manufacturing and headquarters were in different geographical regions of the world, therefore in different time zones, and they wanted the day of the week to be based on the day of the week where their headquarters was located. They also wanted to make sure that if anyone logged in over FTP, they would only see the reports for the current day, and they didn't want to take a chance that something might go wrong with the batch file and they might overwrite the logs from the wrong day.
With all of those requirements in mind, this was beginning to look like a problem for a custom home directory provider to tackle. Fortunately, this was a really easy home directory provider to write, and I thought that it might make a good blog.
Note: I wrote and tested the steps in this blog using both Visual Studio 2010 and Visual Studio 2008; if you use an different version of Visual Studio, some of the version-specific steps may need to be changed.
The following items are required to complete the procedures in this blog:
In this step, you will create a project in Microsoft Visual Studio for the demo provider.
net stop ftpsvc call "%VS100COMNTOOLS%\vsvars32.bat">null gacutil.exe /if "$(TargetPath)" net start ftpsvc
net stop ftpsvc call "%VS90COMNTOOLS%\vsvars32.bat">null gacutil.exe /if "$(TargetPath)" net start ftpsvc
In this step, you will implement the extensibility interfaces for the demo provider.
public class FtpDayOfWeekHomeDirectory :
// Store the path to the default FTP folder.
private static string _defaultDirectory = string.Empty;
// Override the default initialization method.
protected override void Initialize(StringDictionary config)
// Retrieve the default directory path from configuration.
_defaultDirectory = config["defaultDirectory"];
// Test for the default home directory (Required).
throw new ArgumentException(
"Missing default directory path in configuration.");
// Define the home directory provider method.
// Return the path to the folder for the day of the week.
Note: If you did not use the optional steps to register the assemblies in the GAC, you will need to manually copy the assemblies to your IIS 7 computer and add the assemblies to the GAC using the Gacutil.exe tool. For more information, see the following topic on the Microsoft MSDN Web site:
Global Assembly Cache Tool (Gacutil.exe)
Global Assembly Cache Tool (Gacutil.exe)
In this step, you will add your provider to the global list of custom providers for your FTP service, configure your provider's settings, and enable your provider for an FTP site.
Note: If you prefer, you could use the command line to add the provider to FTP by using syntax like the following example:
cd %SystemRoot%\System32\Inetsrv appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"[name='FtpDayOfWeekHomeDirectory',type='FtpDayOfWeekHomeDirectory,FtpDayOfWeekHomeDirectory,version=184.108.40.206,Culture=neutral,PublicKeyToken=426f62526f636b73']" /commit:apphost
At the moment there is no user interface that allows you to configure properties for a custom home directory provider, so you will have to use the following command line:
cd %SystemRoot%\System32\Inetsrv appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"activation.[name='FtpDayOfWeekHomeDirectory']" /commit:apphost appcmd.exe set config -section:system.ftpServer/providerDefinitions /+"activation.[name='FtpDayOfWeekHomeDirectory'].[key='defaultDirectory',value='C:\Inetpub\ftproot']" /commit:apphost
Note: The highlighted area contains the value that you need to update with the root directory of your FTP site.
At the moment there is no user interface that allows you to enable a custom home directory provider for an FTP site, so you will have to use the following command line:
cd %SystemRoot%\System32\Inetsrv appcmd.exe set config -section:system.applicationHost/sites /+"[name='My FTP Site'].ftpServer.customFeatures.providers.[name='FtpDayOfWeekHomeDirectory']" /commit:apphost appcmd.exe set config -section:system.applicationHost/sites /"[name='My FTP Site'].ftpServer.userIsolation.mode:Custom" /commit:apphost
Note: The highlighted areas contain the name of the FTP site where you want to enable the custom home directory provider.
In this blog I showed you how to:
When users connect to your FTP site, the FTP service will drop their session in the corresponding folder for the day of the week under the home directory for your FTP site, and they will not be able to change to the root directory or a directory for a different day of the week.
Can you explain when IFtpHomeDirectoryProvider.GetUserHomeDirectoryData is called?
It is called when start a new session (called one time in one session) or when FTP client
upload a file to FTP server in session (called many times in one session).
@DangNguyen - GetUserHomeDirectoryData is called only at the beginning of a session to establish the home directory for the current session; all operations for that session will use that home directory. If a client disconnects and reconnects, GetUserHomeDirectoryData will be called when the new sessions is established, which might get a different home directory (depending on what your implementation is trying to do).