从 VB 6.0 或 .NET 中检索 Unix 服务器(通过 SFTP)上文件的大小
通过 SFTP 连接查询 Unix 服务器上文件的属性或下载文件到 Windows 服务器
引言
我的一个朋友有一个有点复杂的系统,某个作业在 Unix 机器上运行,将一些输出写入文件,之后 Windows 机器上的一个作业尝试拉取该文件信息并进行一些操作。暂不深究最初为何要设计这样一个连接系统,让我们看看我们正在使用的环境。Unix 机器(我不知道它运行的是哪个版本的 Unix)写入了一些文件 (data.dat),而运行在 Windows 服务器上的 VB 6.0 代码必须查询该文件 (data.dat) 的大小才能做出一些决策。所以我们遇到了这样一个问题,试图集思广益,如何从 VB 6.0 代码中查询 Unix 服务器上文件的大小。Telnet 是我首先想到的,后来,一时兴起,我问他,你是否曾通过 SFTP 连接到那台 Unix 机器。答案是肯定的,我们最终利用了那台服务器上的 SFTP 连接来检索文件属性和文件本身。
背景
我将在此处描述的步骤需要 WinSCP - http://winscp.net。我猜 WinSCP 在其 5.X 版本发布期间,发布了一个名为 WinSCP.dll 的 .NET 库的 Beta 版本。WinSCP 还将其自己的 tlb 文件暴露给 COM。所以我们的解决方案是简单地从 VB 6.0 代码中调用 WinSCP COM 来查询文件大小。然而,考虑到团队中不熟悉 COM 的新开发人员以及可维护性和易用性,我们决定在 WinSCP.dll 上编写一个 C# 包装器,只为了获取文件大小,并仅将该方法暴露给 COM 接口。我们最终将该包装器命名为 SFTPFileSizeGroper
,后来将其设置为 COM+,从而解决了问题。
我将假设您对 COM+、regasm.exe、gacutil.exe 有一定的了解。完整的功能集仅限于 WinSCP.dll 所暴露的功能,而本文将重点介绍仅检索 Unix 服务器上文件的大小。由于 WinSCP 是这里所有操作的核心,如果您以前没有使用过 WinSCP,请从 http://winscp.net/eng/download.php 下载 GUI 可执行文件并试用一下,然后我们再继续。由于讨论中的 Unix 服务器接受 SFTP 连接,因此在本文的其余部分,术语 Unix 服务器和 sftp 服务器将是同义词。
http://winscp.net/eng/docs/ssh 解释了 SSH 的基础知识。
SSH 认证
连接方可以通过多种方式使用 SFTP 对 Unix 服务器进行身份验证。我所知道的两种方式是使用 Active Directory 帐户或使用公钥/私钥对。
- 设置 AD 访问非常简单,您所要做的就是让您的 IT 创建一个 AD 组,或授予特定的 AD 用户访问该 Unix 服务器的权限。在这种情况下,您在连接到 Unix 服务器时需要提供您的凭据,形式为用户名和密码。
- 设置公钥/私钥对认证,要求您创建公钥/私钥对(使用 puttygen.exe 等工具),并让您的 IT 将公钥/私钥对的公钥部分添加到 Unix 服务器。在这种情况下,您在连接到服务器时需要提供公钥/私钥对的私钥。
为了阻止任何中间人攻击,WinSCP 强制您确认您尝试连接的 SFTP 服务器的 HostKey。
当您第一次使用 WinSCP 连接到 SFTP 服务器时,它会要求接受您尝试连接的服务器的 HostKey。成功连接到 STFP 服务器后,WinSCP 会将该服务器及其主机密钥(可能还有其他信息)添加到 WinSCP.ini 文件中。通常,WinSCP.ini 文件与 WinSCP.exe 位于同一位置。
所需参数
为了连接到 SFTP 服务器,我们需要以下信息
- 服务器名称:目标 SFTP 服务器的 FQDN
- 用户名和密码 / 私钥文件:用于连接的用户名和密码,或私钥文件
- HostKey:HostKey 是每台接受 SFTP 连接的机器(或者我相信是每台 Unix 机器?)的唯一标识符。当使用 WinSCP.dll 进行功能操作时,如果 WinSCP.ini 文件不包含我们尝试连接的服务器的 HostKey,则会抛出异常。为避免这种情况,请打开 WinSCP.exe GUI,尝试连接到 SFTP 服务器一次,当提示接受 HostKey 时,请继续。此步骤会将 HostKey 添加到 ini 文件中。现在,在部署时,使用相同的 WinSCP.ini 文件以避免异常。
- 文件路径:您要查询的文件路径。
WinSCP.net 提供了 WinSCP.dll 暴露的方法的示例代码和文档。因此,如果您对 WinSCP.dll 有疑问,请参阅 http://winscp.net/eng/docs/library 上的文档。
简而言之,以下是使用 WinSCP.dll 的步骤。(在开始查看设置 COM+ 应用程序之前,以下步骤与 COM 或 VB 没有任何特定关系。)
private static RemoteFileInfo GetRemoteFileInfo(string pFilePath)
{
RemoteFileInfo remoteFileInfo = default(RemoteFileInfo);
SessionOptions sessionOptions = WinSCPImpl.ObtainSessionInformation();
using (Session session = new Session())
{
session.ExecutablePath = winSCPExecutableLocation;
session.Open(sessionOptions);
remoteFileInfo = session.GetFileInfo(pFilePath);
}
return remoteFileInfo;
}
- 创建新的
Session
- 使用
session.Open(sessionOptions)
方法打开会话(连接到服务器)。SessionOptions
包含服务器名称、认证信息等。 - 使用
session.GetFileInfo("/obj/myfile.dat");
获取RemoteFileInfo
对象 - 现在,
remoteFileInfo
对象拥有一系列您可以立即查询的属性。Length
就是其中之一。
就是这样。这就是关键。名为 WinSCPImpl.cs 的文件中的其余代码非常简单。而 SFTPFileSizeGroper.cs 是一个公开了属性和方法的类(方法基本上调用 WinSCPImpl.cs 的方法)。SFTPFileSizeGroper.cs 文件中的属性和方法作为 COM 暴露。由于它们暴露给 COM,因此它们必须是非静态、公共的,没有引用参数以及所有这些限制。
从我们的 VB 代码中,我们可以实例化一个类型为 Server.CreateObject("SFTPFileSizeGroper.SFTPFileSizeGroper");
的 COM+ 对象,调用其 GetFileSize();
方法,该方法又调用 WinSCPImpl.GetRemoteFileInfo();
,后者将调用委托给 WinSCP.dll 的方法;而 WinSCP.dll 的方法实际上是使用命令行脚本参数调用 WinSCP.exe。
这就像有很多链式调用,但能完成任务。
我们还有一个小任务需要完成,才能使语句 Server.CreateObject("SFTPFileSizeGroper.SFTPFileSizeGroper");
工作。SFTPFileSizeGroper.cs 文件包含 SFTPFileSizeGroper
类,该类旨在导出到 COM,以便任何支持 COM 的技术都可以实例化它。
下面是一个 VB 代码,它将在名为 lblFileSize
的标签控件中获取文件大小。
lblFileSize.Caption = GetSFTPFileSize(txtFilePath.Text)
End Sub
Private Sub Form_Load()
txtFilePath.Text = "/opt/batchapps/edword/rtg/NVBBackend/Items.dbf"
txtHostName.Text = "myunixserver.domain.com"
txtHostUserName.Text = "usermgr"
txtHostPassword.Text = "He11o111"
txtHostSshHostKey.Text = "ssh-rsa 2048 fd:83:b9:85:91:dd:33:95:a2:46:61:4f:05:76:58:31"
txtHostSshPrivateKey.Text = ""
End Sub
Function GetSFTPFileSize(fileName)
Dim objSftpFileSizeGroper As Object
Set objSftpFileSizeGroper = CreateObject(sftpFileSizeGroper.sftpFileSizeGroper)
objSftpFileSizeGroper.FilePath = fileName
objSftpFileSizeGroper.HostName = txtHostName.Text
objSftpFileSizeGroper.HostUserName = txtHostUserName.Text
objSftpFileSizeGroper.HostPassword = txtHostPassword.Text
objSftpFileSizeGroper.HostSshHostKey = txtHostSshHostKey.Text
objSftpFileSizeGroper.HostSshPrivateKey = txtHostSshPrivateKey.Text
GetSFTPFileSize = objSftpFileSizeGroper.GetFileSize()
Set objSftpFileSizeGroper = Nothing
End Function
设置 COM+
此时,您可能会认为存在额外的工作/包装器,因为 WinSCP 已经有一个可以直接从 VB 6.0 使用的 COM 库。在我们的方法中,我们没有使用它,原因是我们有一批 C# 开发人员对 COM 接口不熟悉,而且我们还没有测试 WinSCP 的 COM 库,然而,用于 .NET Framework 的 WinSCP.dll 已经过全面测试,我们的一些应用程序已经在使用了。这是一个小小的“理论依据”,现在让我们快速了解一下如何将 SFTPFileSizeGroper.dll 作为 COM+ 进行安装。
您可以直接使用已构建版本的 SFTPFileSizeGroper.dll、SFTPFileSizeGroper.tlb 和 SFTPFileSizeGroper.msi。SFTPFileSizeGroperCOMInstaller.bat 包含一系列命令,这些命令应该能让您立即运行起来。但是,如果您想手动执行这些步骤,而不涉及太多细节,
展开 SFTPFileSizeGroper COM+ 应用程序节点,右键单击 Components,然后创建一个新的 Component;点击下一步,选择安装新组件,从浏览文件对话框中选择 SFTPFileSizeGroper.tlb,点击下一步,然后完成。
- 从 Visual Studio 构建
SFTPFileSizeGroper
项目。将 SFTPFileSizeGroper.dll 获取到文件系统上的某个位置。同时将 WinSCP.exe、WinSCP.dll 的副本获取到同一位置。 - 以管理员权限打开 Visual Studio 命令提示符,并按顺序运行以下命令。[将 WinSCP.dll 和 SFTPFileSizeGroper.dll 安装到 GAC;将 SFTPFileSizeGroper.dll 注册为 COM。]
@echo Install WinSCP.dll to the GAC gacutil /i WinSCP.dll @echo Install SFTPFileSizeGroper.dll to GAC gacutil /i SFTPFileSizeGroper.dll @echo Register the SFTPFileSizeGroper.dll as COM and generate a tlb file regasm /tlb /codebase SFTPFileSizeGroper.dll
- 让我们打开 comexp.msc(或 dcomcnfg)——组件服务并创建一个 COM+。这涉及一系列步骤,但基本思想是,我们正在尝试创建一个新的 COM+ 应用程序,并将我们的 SFTPFileSizeGroper.dll COM 接口添加到其中。(regasm.exe 命令注册了可用的 COM 接口)。我将引导您,一旦我们创建了 COM+,它可以很容易地导出到 MSI 文件,这可以稍后为我们省去下面的步骤或逐步创建 COM+。
请参阅 technet 链接 http://technet.microsoft.com/en-us/library/bb687389.aspx 以创建新的 COM+ 应用程序。一些首选设置是“
SFTPFileSizeGroper
”或步骤 4 中的任何名称;步骤 5(technet 链接)中的“服务器应用程序”;步骤 6(technet 链接)中的“网络服务”或任何具有创建和运行 COM+ 应用程序权限的用户身份。创建此组件后的最后一步是转到安全选项卡并取消勾选对此应用程序强制实施访问检查复选框。 - 一旦我们创建了一个 COM+ 应用程序,我们就必须向其中添加一个组件。在我们的例子中,我们要添加的组件(COM)称为
SFTPFileSizeGroper
。当我们运行 reagasm /tlb/ codebase SFTPFileSizeGroper.dll 时,除了注册可用的 COM 接口外,该命令还在与 DLL 相同的位置为我们生成了一个类型库,名为 SFTPFileSizeGroper.tlb。我们将使用此类型库文件并将组件添加到我们新创建的 COM+ 应用程序 -SFTPFileSizeGroper
中。 - 如果您想在其他计算机上部署此 COM+ 应用程序,请右键单击
SFTPFileSizeGroper
COM+ 并选择导出,按照步骤操作,一个 MSI 文件即可移植到多台计算机。需要注意的是,MSI 安装会记住所有 COM+ 属性,但身份除外。也就是说,在我们的示例中,我们选择了网络服务,然后从中导出了一个 MSI 文件。如果我们将此 MSI 文件用于在其他计算机上安装 COM+,那么在安装之后,如果您浏览并查看 COM+ 的身份属性,它将不是网络服务,请务必在 MSI 安装 COM+ 后修改此身份属性。
附件
解压附件 - 文件夹名为。
SFTPFileSizeGroperCOM-CompletePackage
- 包含 SFTPFileSizeGroper DLL、tlb 文件、用于安装 COM+ 的 MSI 文件、WinSCP.dll 和 WinSCP.exe。该文件夹还包含 gacutil.exe 和 regasm.exe 以帮助移植。
这些二进制文件可以直接使用,而无需清理和构建原始的 SFTPFileSizeGroper
VS 项目。
关注点
如果您在实例化 COM+ 时遇到“访问被拒绝”错误,请确保 COM+ 属性的“安全性”选项卡下的“对此应用程序强制实施访问检查”复选框处于未选中状态。如果您遇到臭名昭著的“ActiveX 组件无法创建对象”错误,请确保您已安装包含名为 SFTPFileSizeGroper
组件的 COM+。如果您从经典 ASP 页面调用它,请调整 IIS AppPool 的“启用 32 位应用程序”设置。另外,请检查 COM 属性的“高级”选项卡下的“允许 IIS 固有属性”复选框。
历史
- 2013 年 2 月 17 日:初始版本
- 2013 年 2 月 18 日:在文章顶部添加了下载选项