现代Visual Studio下的开发,大家一定用过,或者听说过nuget,不知道的可以去面壁了。代码写多了,经验越来越丰富,但人越来越懒,是啊,谁愿意重复造轮子?谁又愿意陷入版本管理的地狱?所以有了很多包管理的工具或平台,但是这里我不是要讲这个 nuget ,而是自己搭建一个包管理平台,原因嘛,当然是因为不想开源嘛(其实是自己造的轮子很垃圾,只能自己玩玩)

要搭建自己的包管理平台,方法很多,比如用 baget,或者 Nexus,推荐用后者,因为人家那是专业的,而且除了搭建.net的包管理仓库,还可以搭建java的,docker的,很多很多。

Nexus 的搭建部署我就不写了,网上有很多文章,写的一定比我写的详细,我只介绍如何配合另一个工具,就是我们的主角 NuGet Package Explorer 来发布和管理开发好的库文件。

先做好 Nexus 的配置,创建 nuget 仓库,默认情况下, Nexus 已经预装好了 nuget 的仓库

里面有三种仓库,hosted,group 以及一个代理仓库,具体可以看看这篇文章: 编程玩家写的

接下来我们记录一下几个参数,一个是hosted的仓库地址,一个是密钥,仓库地址,点击上图中后面那个 copy 按钮就行了,密钥如下图所示:

记下后,我们开始配置 NuGet Package Explorer ,哦,先去下载 NuGetPackageExplorer

大家可以尝试不同的版本,我之前碰到一个怪事,下载了最新版的包管理器,编辑好了包描述文件后(文件后缀是 nupkg),发现并不能上传成功到自己搭建的包管理服务器,搞不懂是 Nexus 的问题,还是 NuGet Package Explorer 的问题,最后我慢慢试,下载了一个旧的NuGet Package Explorer版本,才搞好了。

为了更好的演示,我们来实际操作一下吧,先随便写一个.NET库,然后打开NuGet Package Explorer

选项依次是:打开一个本地包描述文件、在线获取一个包、新建包、阅读帮助文档。这里面的第二个选项非常好,大家可以通过它加载别人写的包描述文件是什么样的来学习学习。

接下来新建一个吧

这就是新建的界面,左边是当前包的一些描述信息,此时还是空的,等着我们去完善它,注意红框的两个按钮,第一个就是用来编辑你需要打包的文件的,另一个是有关包的描述的配置,我们点第一个

左边的窗口里,一些黑体的内容,是需要你去填写的,主要有这么几个内容:

  • Id 包的唯一编号,一般使用的是你需要打包的主文件的文件名,举个例子,微软的excel插件的id 是 Microsoft.Office.Interop.Excel
  • Version 版本号
  • Authors 作者
  • Description 描述
  • 现在,我们在右边的框里右键,引入需要打包的库文件

    右键菜单有很多选项,我也只是初步学习,一些菜单也不明白是做什么的,我就捡目前为止我知道的讲解一下,其他菜单等我搞明白后,我再来更新这篇文章。

    如果你的库只是一个单独的库,并且你在你自己的项目里并不关心框架的版本的话,那么选择 "Add Existing File..."就可以了,但是如果你有特殊需求,例如你的库可能面向不同的框架,那么你就需要选择 "Add Lib Folder" ,然后在创建的 lib 文件夹上右键,选择你当前需要打包的库所支持的框架版本,我建议这样做,因为这是更标准的做法,看下图所示:

    我之前随便创建的一个库,是.NET FRAMEWORK 4.6.2 的环境,所以我按上图选择了,选好后,在创建的文件夹上右键,导入你需要打包的库文件,然后编辑包的元信息,Id、版本、作者等等。注意在编辑包的元信息下面,还可以指定一些依赖项,例如你的包如果依赖了n,那么你可以点击"Edit dependencies"来添加这些依赖。这些依赖不会随你的包打包,而是在别人引入你的包的时候下载的:

    注意,除了引入互联网上的第三方包以外,还可以引入其他私服的,双击你需要依赖的包,然后回到上图,点右下角的加号就OK了。至此包描述文件就基本编辑完成了,保存一下这个文件,然后我们把它发布到开始搭建的包服务器上,选择 “File ---> Publish...”

    然后看看发布成功没有:

    已经发布上去了,接下来我们可以在工程里通过nuget引入这个包试试,记得nuget的地址要选择你自己的私服地址哦,大家去试试吧。

    后续:还有一些没涉及的功能,比如你的包引入的是c++开发的库,并不需要在引入nuget包的时候添加到项目里,那么怎么打包呢?等我研究研究再来更新这篇博文吧 ^^

    2021年5月10号更新:如何发布本地文件

    在有的场景中,大家开发的dll可能依赖了一些c++的库,或者一些资源文件,那么如何把这些文件一起打包,并在别人引入你的包的时候,在编译时拷贝到bin的debug或release目录里呢?

    我们打开 sqlite 的包来学习学习,具体方式就是 "Open from Feed...",或快捷键"Ctrl + G“,然后搜索到Sqlite,打开后如下所示:

    可以看看它的目录结构,那个runtimes文件夹,是自定义的,你可以任意命名,当然我们程序员一个好的习惯是不要随意命名,最好起一个有意义的名字。重点是那个 build 文件夹,这个文件夹里有两个重要的文件,一个 props,一个 targets,两个文件都是用来定义当包引入到项目中后,项目构建时期的动作的。前一个是在项目构建前执行,后一个是在构建完成之后执行。

    接下来我们重点说一下这两个文件的内容,在上述示例中,sqlite创建的是一个 props ,因为在项目构建的时候,需要导入的 dll 是必须存在的,否则会提示找不到文件。

    ItemGroup Condition=" (Exists('packages.config') Or Exists('packages.$(MSBuildProjectName).config')) And '$(Platform)' == 'AnyCPU'"

    这段代码,指定了build的条件,意思是如果存在 packages.config 或者 packages.$(MSBuildProjectName).config ,并且项目的目标平台是 AnyCPU,则执行其中的动作。

    $(MSBuildProjectName) 是一个预定义的常量,在解析时会替换为你项目的名称,大家可以看这里获取更多的 说明

    Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win7-x86\native\*"

    这段代码就是指定第三方库或者资源的目录,以便后面拷贝

    没看明白,╮(╯▽╰)╭

    CopyToOutputDirectory

    拷贝文件的方式,有三种:

    1. Never


    2. Always

    总是执行,哪怕目标目录文件已存在,也执行


    3. PreserveNewest

    Visible

    是否在工程里显示,我试了,也不知道什么效果 (*  ̄︿ ̄)

    这里有一个需要注意的,就是build文件夹里,需要创建相应的.net framework的版本文件夹,低于你的工程的版本才会执行,不要建无版本的,我踩了N个坑,试了N次才发现这个情况。

    OK,暂时就到这里,还有 tools 和 src 文件夹没讲了,后面研究清楚了再来更新吧。哦,还有一个 content 文件夹,这个文件夹里的内容,会拷贝到你的工程里,和你的代码在一个位置,就比如 App.config 这样的。