MFC实现文件监控与FTP上传

在vc6.0 mfc 环境下新建工程名称FileMonitor 的MFC Appwizard(exe) 对话框,添加一个启动监控按钮,一个关闭监控按钮。ftp服务器ip 192.168.3.100 匿名身份验证物理路径 d:\FTPRoot 被监控电脑上被监控文件夹是d:\1。点击启动监控按钮时,当被监控电脑上被监控文件夹d:\1下文件更新时将这些文件以相同的文件名实时传输到FTP服务器根目录,点击关闭监控按钮时关闭文件实时传送。

StdAfx.h

cpp 复制代码
// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__2915B623_03D7_4EF3_AA50_5A27DB889CDB__INCLUDED_)
#define AFX_STDAFX_H__2915B623_03D7_4EF3_AA50_5A27DB889CDB__INCLUDED_
#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxdisp.h>        // MFC Automation classes
#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>			// MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT


//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__2915B623_03D7_4EF3_AA50_5A27DB889CDB__INCLUDED_)

FileMonitorDlg.h

cpp 复制代码
// FileMonitorDlg.h : header file
//

#if !defined(AFX_FILEMONITORDLG_H__30A536A0_330D_4CCF_B982_FC311BB3A8FE__INCLUDED_)
#define AFX_FILEMONITORDLG_H__30A536A0_330D_4CCF_B982_FC311BB3A8FE__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CFileMonitorDlg dialog
#include <afxinet.h>
#include <afxmt.h>

class CFileMonitorDlg : public CDialog
{
// Construction
public:
	CFileMonitorDlg(CWnd* pParent = NULL);	// standard constructor
	static UINT MonitorThread(LPVOID pParam);
BOOL UploadFileToFTP(const CString& strLocalFile, const CString& strRemoteFile);
// Dialog Data
	//{{AFX_DATA(CFileMonitorDlg)
	enum { IDD = IDD_FILEMONITOR_DIALOG };
	CButton	m_btnStop;
	CButton	m_btnStart;
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CFileMonitorDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	HICON m_hIcon;
    CWinThread* m_pMonitorThread;
    HANDLE m_hStopEvent;
    CEvent m_StopEvent;
    BOOL m_bMonitoring;
    CString m_strLocalPath;
    CString m_strFTPServer;
    CString m_strFTPPath;
	// Generated message map functions
	//{{AFX_MSG(CFileMonitorDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	afx_msg void OnStartMonitor();
	afx_msg void OnStopMonitor();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_FILEMONITORDLG_H__30A536A0_330D_4CCF_B982_FC311BB3A8FE__INCLUDED_)

FileMonitorDlg.cpp

cpp 复制代码
// FileMonitorDlg.cpp : implementation file
//

#include "stdafx.h"
#include "FileMonitor.h"
#include "FileMonitorDlg.h"
#include "stdafx.h"
#include "FileMonitor.h"
#include "FileMonitorDlg.h"
#include <io.h>
#include <sys/stat.h>
#include <afxinet.h>
#include <afxmt.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileMonitorDlg dialog

CFileMonitorDlg::CFileMonitorDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFileMonitorDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CFileMonitorDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pMonitorThread = NULL;
    m_bMonitoring = FALSE;
    m_strLocalPath = _T("d:\\1");
    m_strFTPServer = _T("192.168.3.100");
    m_strFTPPath = _T("/");
}

void CFileMonitorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFileMonitorDlg)
	DDX_Control(pDX, IDC_STOP_MONITOR, m_btnStop);
	DDX_Control(pDX, IDC_START_MONITOR, m_btnStart);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFileMonitorDlg, CDialog)
	//{{AFX_MSG_MAP(CFileMonitorDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_START_MONITOR, OnStartMonitor)
	ON_BN_CLICKED(IDC_STOP_MONITOR, OnStopMonitor)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileMonitorDlg message handlers

BOOL CFileMonitorDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_btnStop.EnableWindow(FALSE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CFileMonitorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CFileMonitorDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CFileMonitorDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CFileMonitorDlg::OnStartMonitor() 
{
	if (m_bMonitoring)
        return;

    m_bMonitoring = TRUE;
    m_StopEvent.ResetEvent();
    m_btnStart.EnableWindow(FALSE);
    m_btnStop.EnableWindow(TRUE);

    m_pMonitorThread = AfxBeginThread(MonitorThread, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
    if (m_pMonitorThread)
    {
        m_pMonitorThread->m_bAutoDelete = FALSE;
        m_pMonitorThread->ResumeThread();
    }
    else
    {
        AfxMessageBox(_T("无法创建监控线程!"));
        m_bMonitoring = FALSE;
        m_btnStart.EnableWindow(TRUE);
        m_btnStop.EnableWindow(FALSE);
    }
	
}

void CFileMonitorDlg::OnStopMonitor() 
{
	if (!m_bMonitoring)
        return;

    m_bMonitoring = FALSE;
    m_StopEvent.SetEvent();

    if (m_pMonitorThread)
    {
        WaitForSingleObject(m_pMonitorThread->m_hThread, INFINITE);
        delete m_pMonitorThread;
        m_pMonitorThread = NULL;
    }

    m_btnStart.EnableWindow(TRUE);
    m_btnStop.EnableWindow(FALSE);
	
}



UINT CFileMonitorDlg::MonitorThread(LPVOID pParam)
{
    CFileMonitorDlg* pDlg = (CFileMonitorDlg*)pParam;
    
    // 确保目录路径以反斜杠结尾
    CString strDirPath = pDlg->m_strLocalPath;
    if (strDirPath.Right(1) != _T("\\"))
        strDirPath += _T("\\");

    HANDLE hDir = CreateFile(
        strDirPath,
        FILE_LIST_DIRECTORY,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
        NULL);

    if (hDir == INVALID_HANDLE_VALUE)
    {
        AfxMessageBox(_T("无法打开监控目录!"));
        return 1;
    }

    BYTE buffer[1024];
    DWORD bytesReturned;
    OVERLAPPED overlapped;
    ZeroMemory(&overlapped, sizeof(overlapped));
    overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    while (pDlg->m_bMonitoring)
    {
        ZeroMemory(buffer, sizeof(buffer));
        bytesReturned = 0;

        if (ReadDirectoryChangesW(
            hDir,
            buffer,
            sizeof(buffer),
            TRUE,
            FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
            &bytesReturned,
            &overlapped,
            NULL))
        {
            HANDLE handles[2] = { overlapped.hEvent, pDlg->m_StopEvent };
            DWORD waitResult = WaitForMultipleObjects(2, handles, FALSE, INFINITE);

            if (waitResult == WAIT_OBJECT_0)
            {
                FILE_NOTIFY_INFORMATION* pInfo = (FILE_NOTIFY_INFORMATION*)buffer;
                while (pInfo)
                {
                    if (pInfo->Action == FILE_ACTION_MODIFIED || 
                        pInfo->Action == FILE_ACTION_ADDED)
                    {
                        CString strFileName;
                        int len = WideCharToMultiByte(CP_ACP, 0, pInfo->FileName, 
                            pInfo->FileNameLength / sizeof(WCHAR), NULL, 0, NULL, NULL);
                        WideCharToMultiByte(CP_ACP, 0, pInfo->FileName, 
                            pInfo->FileNameLength / sizeof(WCHAR), 
                            strFileName.GetBuffer(len), len, NULL, NULL);
                        strFileName.ReleaseBuffer();

                        CString strFullPath = strDirPath + strFileName;
                        CString strRemoteFile = pDlg->m_strFTPPath + strFileName;

                        pDlg->UploadFileToFTP(strFullPath, strRemoteFile);
                    }

                    if (pInfo->NextEntryOffset == 0)
                        break;

                    pInfo = (FILE_NOTIFY_INFORMATION*)((BYTE*)pInfo + pInfo->NextEntryOffset);
                }
            }
            else
            {
                break;
            }
        }
    }

    CloseHandle(overlapped.hEvent);
    CloseHandle(hDir);
    return 0;
}

BOOL CFileMonitorDlg::UploadFileToFTP(const CString& strLocalFile, const CString& strRemoteFile)
{
    CInternetSession session(_T("FileMonitor"));
    CFtpConnection* pConnection = NULL;

    try
    {
        pConnection = session.GetFtpConnection(
            m_strFTPServer,
            _T(""),    // 匿名登录
            _T(""),    // 密码为空
            21,        // FTP端口
            FALSE);    // 不使用被动模式

        if (pConnection)
        {
            if (!pConnection->PutFile(strLocalFile, strRemoteFile))
            {
                AfxMessageBox(_T("文件上传失败!"));
                pConnection->Close();
                delete pConnection;
                session.Close();
                return FALSE;
            }

            pConnection->Close();
            delete pConnection;
            session.Close();
            return TRUE;
        }
    }
    catch (CInternetException* pEx)
    {
        TCHAR szError[1024];
        pEx->GetErrorMessage(szError, 1024);
        AfxMessageBox(szError);
        pEx->Delete();

        if (pConnection)
        {
            pConnection->Close();
            delete pConnection;
        }
        session.Close();
        return FALSE;
    }

    return FALSE;
}

运行程序

相关推荐
2301_789015622 小时前
C++:set/multiset和map/multimap文档详细解析
c语言·开发语言·c++·vscode·排序算法·set·map
CoderCodingNo2 小时前
【GESP】C++五级真题(数论-素数思想考点) luogu-P10720 [GESP202406 五级] 小杨的幸运数字
开发语言·c++·算法
zmzb01032 小时前
C++课后习题训练记录Day59
开发语言·c++
小李小李快乐不已2 小时前
算法技巧理论基础
数据结构·c++·算法·leetcode·hot100
咕咕嘎嘎10242 小时前
C++仿muduo库onethreadoneloop高并发服务器
服务器·网络·c++
Bruce_kaizy2 小时前
c++图论——最短路之Johnson算法
开发语言·数据结构·c++·算法·图论
Lion Long2 小时前
在 Windows 上快速搭建 VSCode 的 C++ 开发环境(基于 WSL)
linux·c++·windows·vscode·wsl
idontknow2332 小时前
从零开始编写 webserver (三) 线程池与数据库连接池
c++
石去皿3 小时前
C++校招通关秘籍:从高频考点到工程思维的跃迁
java·服务器·c++