65.9K
CodeProject 正在变化。 阅读更多。
Home

文件监视器自动将您的工作文件从 VS.NET 项目文件夹移动

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (10投票s)

2006 年 2 月 16 日

3分钟阅读

viewsIcon

51425

downloadIcon

1528

一篇关于将工作文件与 Visual Studio .NET 2003 解决方案分离的文章。

Sample Image - WenjunSFW.jpg

引言

Visual Studio .NET 2003 及其早期版本非常棒,并且正在成为 .NET 应用程序开发人员的首选。您创建一个新项目,然后开发和编译代码。但是,当您想要将您的工作文件部署到生产环境时,会很痛苦。虽然您可以创建一个部署项目来构建 MSI 安装程序,但在许多情况下,您不想构建 MSI。您只是想拥有一个干净的文件夹,其中仅包含工作文件夹/文件,并将它交给您的客户,而不是一堆与您的工作文件混在一起的垃圾文件。

当您使用 Visual Studio .NET 2003 创建一个项目时,它会自动生成几个文件

xxx.csproj
xxx.csproj.user
xxx.sln
xxx.suo
AssemblyInfo.cs
...

如果您的项目与 SourceSafe 链接,您将拥有更多垃圾文件。当您将您的应用程序交付给客户时,这些文件通常不需要包含在您的应用程序中。

假设您有一个非常大的项目,由几个项目组成;将工作文件与这些项目/解决方案分开是一件非常痛苦的事情。

本文试图演示如何解决此问题。我构建了一个文件监视器对象来监视项目根文件夹;每当创建、删除、重命名或更改文件/文件夹时,它会将此文件/文件夹移动到单独的目标(项目发布文件夹)。

在这种情况下,在您进行开发时,工作文件/文件夹将被移动到目标位置。当您的开发完成时,您已经创建了干净的工作文件夹。您只需复制整个目标文件夹并将其部署给您的客户。听起来不错吗?

背景

解决此问题的一般思路是

  1. 定义两个文件夹
    • FROM:您开发项目的根文件夹。
    • TO:您要部署应用程序的部署文件夹。

      此文件夹包含两个子文件夹:EngineBinEngine 用于内容文件和相关文件夹。Bin 用于所有 .dll.pdb 文件。

  2. 创建一个配置文件,指示在哪里以及如何处理您的项目。配置文件采用 XML 格式,如下所示
    <Watchers>
      <Watcher>
       <Source>c:\filewatcher\testfolder\from</Source>
       <ProjectDestination>c:\filewatcher\testfolder
                      \to\Bin</ProjectDestination>
       <EngineDestination>c:\filewatcher\testfolder
                      \to\Engine</EngineDestination>
       <FileExtensions>dll,pdb,ascx,xml,gif,jpeg,dis,js,xsl,
                       xls,htc,txt,config,asp,aspx,asmx</FileExtensions>
       <Events>Created,Changed,Renamed,Deleted</Events>
       <Trace>yes</Trace>
      </Watcher>
    </Watchers>
  3. 构建一个文件监视器来监视 FROM 文件夹;基于配置文件,它将文件/文件夹从源文件夹移动/更改到目标文件夹。

使用代码

只有一个类来执行文件监视工作:FileWatcher。此类中有三个重要的方法:ProcessWatcherProcessTaskCopyDeleteFile。我将逐一描述这些方法。

ProcessWatcher 创建监视器对象的实例。它创建了四个事件:FileChangedFileCreatedFileReNamedFileDeleted。在配置文件中,您指定要跟踪哪个事件。

/// <summary>
/// Create the instance of the watcher object
/// and fire the monitoring events.
/// After this method has executed,
/// the process is ready to monitor
/// </summary>
private void ProcessWatcher()
{
    sourcePath = GetWatcherInfo("Source");
    pDestinationPath = GetWatcherInfo("ProjectDestination");
    eDestinationPath = GetWatcherInfo("EngineDestination");
    watchFileExtension = GetWatcherInfo("FileExtensions");
    trace = GetWatcherInfo("Trace").ToLower();
    string eventName = GetWatcherInfo("Events");
    string [] arrEvents = eventName.Split(",".ToCharArray());
    int i = 0;

    pDest = pDestinationPath.Split(";".ToCharArray());

    WatchFile = new FileSystemWatcher(sourcePath, "*");
    WatchFile.IncludeSubdirectories = true;
    WatchFile.NotifyFilter = NotifyFilters.Size | 
              NotifyFilters.LastWrite | 
              NotifyFilters.FileName | 
              NotifyFilters.DirectoryName;

    for (i=0;i<arrEvents.Length;i++)
    {
        switch(arrEvents[i])
        {
            case "Changed":
                WatchFile.Changed += new 
                       FileSystemEventHandler(FileChanged);
                break;
            case "Created":
                WatchFile.Created += new 
                       FileSystemEventHandler(FileCreated);
                break;
            case "Renamed":
                WatchFile.Renamed += new 
                       RenamedEventHandler(FileReNamed);
                break;
            case "Deleted":
                WatchFile.Deleted += new 
                       FileSystemEventHandler(FileDeleted);    
                break;
        }
    }

    WatchFile.EnableRaisingEvents = true;
}

每当监视器触发一个事件时,它就会进入此处检查要执行什么类型的进程。

/// <summary>
/// Decide what kind of process needs to perform
/// </summary>
/// <param name="e">FileSystemEventArgs event argument</param>
/// <param name="checkType">Fired event type</param>
/// <param name="fileOrFolder">Is this a file or folder?</param>
private void ProcessTask(FileSystemEventArgs e, 
                         string checkType, string fileOrFolder)
{
    string fileName = string.Empty;
    fileName = GetNameOnly(e.Name);

    switch(checkType)
    {
        case "Created":
            CheckFolder(e.Name, fileName, fileOrFolder);
            CopyDeleteFile(e.FullPath, e.Name, fileName, 
                           "", fileOrFolder, false);
            break 
        case "Changed":
            CopyDeleteFile(e.FullPath, e.Name, fileName, 
                           "", fileOrFolder, false);
            break 
        case "Deleted":
            if (fileOrFolder == "file")
            {
                for (int i=0;i<pDest.Length;i++)
                {
                    File.Delete(pDest[i] + "\\" + fileName);
                    File.Delete(pDest[i] + "\\" + e.Name);
                }
            }
            else
            {
                Directory.Delete(eDestinationPath + 
                                 "\\" + e.Name, true);
            }
            break 
        default:
            break 
    }

    if (trace == "yes")
        WriteLog(e, checkType);
}

最后,执行方法 CopyDeleteFile:如果是重命名请求,此方法首先删除目标文件夹中的映射文件,然后将重命名的文件复制到目标映射文件夹。如果文件类型是文件夹,则其行为与文件相同。

/// <summary>
/// Whenever a file/folder has been renamed, deleted, created or modified, 
/// the destination will do the same process accordingly.
/// </summary>
/// <param name="source">The folder path is been monitoring</param>
/// <param name="watchedNamePath">The changed file/folder path</param>
/// <param name="fileName">Destination file path to be mapped</param>
/// <param name="oldName">Destination file/folder
///       path before the name changing.</param>
/// <param name="fileOrFolder">Indicates the
///           monitored object is a file or folder</param>
/// <param name="isRename">Is this fried for rename?</param>
private void CopyDeleteFile(string source, string watchedNamePath, 
        string fileName, string oldName, 
        string fileOrFolder, bool isRename)
{
    //Copy to project directory
    if(fileName.IndexOf(".dll") > 0 || fileName.IndexOf(".pdb") > 0)
    {
        for (int i=0;i<pDest.Length;i++)
        {
            File.Delete(pDest[i] + "\\" + fileName);
            File.Copy(source, pDest[i] + "\\" + fileName, true);
            File.SetAttributes(pDest[i] + "\\" + fileName, 
                                   FileAttributes.Normal);
        }
    }
    else
    {
        //Copy to engine directory. Only copy when file changed
        if (oldName == "" && fileOrFolder == "file")
        {
            File.Copy(source, eDestinationPath + "\\" + 
                              watchedNamePath, true);
            File.SetAttributes(eDestinationPath + "\\" + 
                               watchedNamePath, FileAttributes.Normal);
        }
        else
        {
            if (fileOrFolder == "file")
            {
                File.Delete(eDestinationPath + "\\" + oldName);

                if (isRename)
                    File.Copy(source, eDestinationPath + 
                          "\\" + watchedNamePath, true);
            }
            else if (fileOrFolder == "folder" && oldName != "")
            {
                Directory.Move(eDestinationPath + "\\" + oldName, 
                      eDestinationPath + "\\" + watchedNamePath);
            }
        }
    }
}

运行演示程序

下载演示 Zip 文件并将其解压缩到您的 c: 驱动器。打开根目录 FileWatchDemo 文件夹,您应该看到以下文件和文件夹

c:\FileWatcherDemo\TestFolder
C:\FileWatcherDemo\CustomWatcher.config
C:\FileWatcherDemo\FileWatcher.exe

双击 FileWatcher.exe,并将一个 DLL 复制到 C:\FileWatcherDemo\TestFolder\From 文件夹。您应该看到此 DLL 已被添加到 C:\FileWatcherDemo\TestFolder\To\bin 文件夹中。

将一个 GIF 文件复制到 C:\FileWatcherDemo\TestFolder\From 文件夹,您应该看到此 GIF 文件已添加到 C:\FileWatcherDemo\TestFolder\To\engine 文件夹中。

文件监视器自动将您的工作文件从 VS.NET 项目文件夹移动 - CodeProject - 代码之家
© . All rights reserved.