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

GadgetPacker - Windows 小工具构建工具

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (21投票s)

2010年11月2日

CPOL

6分钟阅读

viewsIcon

78092

downloadIcon

2215

一个简单的自动化构建工具,用于辅助 Windows 小工具开发。

引言

在为 Windows 7 开发桌面小工具时,构建过程变得非常麻烦。我决定编写一个简单的自动化工具会更容易,它可以处理必要的步骤。这将加快整体开发和测试阶段。

本文不详细介绍整个桌面小工具开发过程,也不详细介绍使用的代码库。

本文旨在为正在开发小工具的社区成员提供一个可能希望用于辅助其过程的工具。本文将介绍过程中执行的步骤,并简要介绍代码的工作原理。

该工具使用 Visual Studio 2010 (VB.NET) 构建,目标为 .NET 4.0,在 Windows 7 Ultimate 安装上运行。

背景

桌面小工具实际上是文件和文件夹的集合,主要是 HTML 文件、CSS 文件、图像文件、JavaScript 文件,当然还有定义小工具的小工具清单。文件和文件夹可以深度嵌套,也可以是包含必要文件的单个扁平文件夹。

小工具文件是一个 zip 文件,其中包含所有文件和文件夹,小工具根文件夹(包含 manifest.xml 的文件夹)位于树的顶部,所有其他文档都相对于该文件夹。

当您更改小工具的源代码时,必须经过打包和安装过程才能测试小工具。

打包小工具所需的步骤是:

  • 从开发文件夹中删除旧的 .gadget 文件。
  • 创建一个包含所有文件(包括文件夹)的 zip 文件,只需选择所有文件和文件夹,然后选择“发送到”->“压缩(zipped)文件夹”即可轻松完成。
  • 将 zip 文件重命名为 .gadget 扩展名。
  • 执行小工具文件进行安装。

现在,您可以想象,为了测试小工具的更改而反复执行此操作会变得非常乏味,在资源管理器中进行的每次左键单击、右键单击、发送到、重命名等操作最终都会让您抓狂。是时候让自动化来完成工作了!

使用 GadgetPacker

该工具不需要设置任何设置,它没有选项,设计非常简单。该工具的编写方式是,如果您正在开发多个小工具,您可以简单地将应用程序的 EXE 复制并粘贴到每个开发文件夹中。

您需要做的是将 GadgetPacker.exe 文件复制到开发文件夹,并将其重命名为您的最终小工具将要使用的名称。例如,如果您的最终小工具名称将是 SomeGadget.gadget,那么您将 GadgetPacker.exe 重命名为 SomeGadget.exe,就是这样。

当您准备好构建小工具时,只需双击/运行 GadgetPacker EXE。然后它将按照下面确定的步骤来构建小工具。

只有一个隐藏功能,那就是“AutoClose”覆盖。您可以在上面应用程序的屏幕截图中看到它已激活。您所需要做的就是在应用程序运行时按住 Shift 键,这样就可以阻止应用程序关闭,让您可以阅读日志(如果您愿意)。还有一个“ReRun”按钮,如果您想在阻止“AutoClose”后手动重新启动过程,可以按下该按钮。

采取了哪些步骤?

构建小工具时,该工具将执行以下步骤:

  1. 确定小工具根目录的路径,以及小工具和临时构建文件的适当文件名。
  2. 删除可能存在的任何先前临时小工具文件(仅在应用程序意外崩溃时发生!)。
  3. 对所有文件夹和文件执行完整的目录和子目录扫描。
  4. 从发现的文件列表中删除 GadgetPacker 和任何先前的 Gadget 文件。
  5. 创建一个新的临时 zip gadget 文件。
  6. 将步骤 #3 中的所有文件添加到 zip 文件中,包括从 Windows 注册表中查找的每个文件的 mime 类型。
  7. 将临时 gadget zip 文件复制到最终的 gadget 文件名,如果已存在则覆盖。
  8. 删除临时 gadget zip 文件。
  9. 执行 gadget 文件以启动 Windows 小工具安装。
  10. 如果未按下 Shift 键,则退出工具,否则不退出。

关注点

  1. 目录扫描是一个简单的递归循环,它使用 list<of String> 填充所有找到的文件。
    Private Sub Dir(ByVal Path As String)
    
        Dim files As New List(Of String)
        Dim dirs As New List(Of String)
    
        files = Directory.GetFiles(Path).ToList
        dirs = Directory.GetDirectories(Path).ToList
    
        For Each item As String In files
            buildFiles.Add(item.ToLower)            'switch everything to lower case
            WriteMessage(item, True)
        Next
    
        For Each item As String In dirs
            Dir(item)
        Next
    
    End Sub
  2. WindowsBase DLL 中找到的 System.IO.Packaging 命名空间包含创建和处理 zip 文件所需的类。下面的例程展示了如何将每个文件添加到新创建的 zip 文件中。
    Private Sub buildGadget()
        WriteMessage(String.Empty, True)
        WriteMessage("Build Gadget File.........", True)
    
        Dim progressStartVal = ProgressBar.Value
        Dim progressTargetVal = 90
    
        Dim fileCount As Integer = 0
        'Create the temp package
        Using zip As ZipPackage = ZipPackage.Open(zipFilePath + "\" + _
    	zipFileNameTemp, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None)
    
            'Process each part
            For Each item As String In buildFiles
                'Take each file, create the relevant info for the zip file
                Dim partUri As Uri = PackUriHelper.CreatePartUri(New Uri(getURI(item), _
    		UriKind.Relative))
                WriteMessage("Adding: " + partUri.ToString, True)
    
                'Create the package part
                Dim zipPart As ZipPackagePart = _
    		zip.CreatePart(partUri, getMimeType(item))
    
                'Copy the Source data to the package part
                Using fileStream As New FileStream(item, FileMode.Open, FileAccess.Read)
                    CopyStream(fileStream, zipPart.GetStream())
                End Using
    
                fileCount += 1
    
                ProgressBar.Value = ((progressTargetVal - progressStartVal) * _
    		(fileCount / buildFiles.Count)) + progressStartVal
    
            Next
    
        End Using
    
        WriteMessage("Added " + fileCount.ToString + " item(s) to gadget.", True)
    
    End Sub

    使用打包时需要注意的一点是,如果您使用资源管理器打开 zip 文件,您会注意到一个名为 [ContentTypes].xml 的文件,其中包含所有已识别的 mime 类型。此文件是自动添加的,无法删除。但是,它对整体小工具没有任何影响。基于此,我没有尝试删除它,也没有寻找其他 zip 库来替代框架中包含的库。

  3. mime 类型查找是通过获取每个文件的扩展名,并在注册表中查找来完成的。如果找不到特定的扩展名,则使用自定义 mime 类型。这些记录在 [ContentTypes].xml 文件中,因此对于小工具而言没有影响。执行查找的代码如下所示。

    Private Function getMimeType(ByVal path As String) As String
    
        Dim mime = String.Empty
        Dim ext = System.IO.Path.GetExtension(path).ToLower()
    
        Dim rk As Microsoft.Win32.RegistryKey = _
    	My.Computer.Registry.ClassesRoot.OpenSubKey(ext)
    
        Try
            mime = rk.GetValue("Content Type").ToString()
        Catch ex As Exception
            WriteMessage("ERROR: Cannot determine content type for: _
    	" + path + "; Setting to contentype/unknown", True)
            mime = "contenttype/uknown"
        End Try
    
        Return mime
    
    End Function
  4. 通过使用 Process.Start("gadgetpathandname") 来启动小工具安装过程,这会使 Windows 提示用户确认他们是否希望安装该小工具。如果该小工具已存在,Windows 还会提示用户是否希望覆盖它。

  5. 您会注意到代码片段中的 WriteMessage(),这是一个用于更新窗体上日志条目的简单助手,它有两个重载,一个只追加消息,另一个添加 CRLF 序列。

参考文献 / 扩展阅读

在开发小工具和构思此工具时,以下是一些您可能感兴趣的网站:

下一步

好了,真的没有什么别的要补充的了,这个工具可以免费使用。如果您有任何想法等,请告诉我。

现在我可以回到开发我的第一个桌面小工具了,所以希望有一天,也会有一篇关于它的文章!

感谢阅读...

历史

(版本号与代码更改相关,而不是文章修订版。)

  • V1.0 - 2010 年 11 月 3 日:初始文章和代码发布
© . All rights reserved.