C# 跟C和CPP算是远亲,C之后是CPP,之后又衍生了C#,少了点CPP的复杂度,多了点C的易用性。
1 开发环境搭建
有两种主要的方式来编译 C# (CSharp)代码。
(1) 使用命令行工具 dotnet
。
通过命令行工具 dotnet
可以执行各种操作,其中包括编译 C# 代码。dotnet
命令具有非常丰富的参数选项,可以实现多种编译方式,如编译整个项目或指定目标框架、编译到不同的输出目录等。
(2) 使用集成开发环境(IDE)。
针对 .NET Core 的集成开发环境有很多种,包括 Visual Studio、Visual Studio Code、JetBrains Rider 等。这些集成开发环境支持直接打开 .NET Core 项目,并提供了各种编译和调试工具,可以更加方便地编译 C# 代码。例如,使用 Visual Studio 中的“生成”菜单或快捷键(默认为 F6)可以编译当前解决方案中的所有 C# 项目。
无论使用哪种方式,编译后的代码将生成一个或多个托管程序集(.dll 文件),可以直接运行或打包发布。两种方式实际上都是依赖.NET core,本文只讲利用dotnet工具编译,其属于 .NET Core SDK的一部分,因此先从 https://dotnet.microsoft.com/download下载适用于自己操作系统的 .NET Core SDK 并安装。
这边用的是dotnet-sdk-7.0.203-win-x64版本,安装直接下一步没难度,环境就算是搭建好了,进入实战。
2 新建项目
新建文件夹,命名为自己的项目,打开命令提示符或终端,使用 dotnet new
命令创建一个新的 C# 项目。例如,以下命令将创建一个Windows 窗体应用:
dotnet new winforms
常用模板包括:
模板名 短名称 语言 标记
--------------------- ------------ ---------- -------------------
ASP.NET Core Web 应用 webapp,razor [C#] Web/MVC/Razor Pages
Blazor Server 应用 blazorserver [C#] Web/Blazor
Windows 窗体应用 winforms [C#],VB Common/WinForms
WPF 应用程序 wpf [C#],VB Common/WPF
控制台应用 console [C#],F#,VB Common/Console
类库 classlib [C#],F#,VB Common/Library
例如:
dotnet new console
通过以下方式显示模板选项:
dotnet new console -h
通过以下方式显示已安装的所有模板:
dotnet new list
通过以下方式显示 NuGet.org 上可用模板:
dotnet new search web
此时目录下自动生成以下文件:
call-notepad.csproj Form1.cs obj/
call-notepad.csproj.user Form1.Designer.cs Program.cs
这边的Program.cs就是我们要编辑的代码文件,打开并编辑:
// 基于csharp做的小程序实现鼠标选择文件调用notepad打开,这边用notepad只是个引子,可以更换为其他软件
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace call_notepad
{
public partial class MainForm : Form
{
private OpenFileDialog openFileDialog = new OpenFileDialog();
private ListBox lstFiles = new ListBox();
private Button btnSelect = new Button();
private Button btnOpen = new Button();
public MainForm()
{
InitializeComponent();
}
private void btnSelect_Click(object? sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// 显示选择的文件
foreach (string file in openFileDialog.FileNames)
{
lstFiles.Items.Add(file);
}
}
}
private void btnOpen_Click(object? sender, EventArgs e)
{
// 打开文件
foreach (string file in lstFiles.Items)
{
Process.Start("notepad.exe", file);
}
}
private void InitializeComponent()
{
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.lstFiles = new System.Windows.Forms.ListBox();
this.btnSelect = new System.Windows.Forms.Button();
this.btnOpen = new System.Windows.Forms.Button();
this.SuspendLayout();
// OpenFileDialog
this.openFileDialog.Multiselect = true;
// ListBox
this.lstFiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.lstFiles.FormattingEnabled = true;
this.lstFiles.ItemHeight = 16;
this.lstFiles.Location = new System.Drawing.Point(12, 12);
this.lstFiles.Name = "lstFiles";
this.lstFiles.Size = new System.Drawing.Size(515, 196);
this.lstFiles.TabIndex = 0;
// Button - Select
this.btnSelect.Location = new System.Drawing.Point(12, 226);
this.btnSelect.Name = "btnSelect";
this.btnSelect.Size = new System.Drawing.Size(105, 33);
this.btnSelect.TabIndex = 1;
this.btnSelect.Text = "选择文件";
this.btnSelect.UseVisualStyleBackColor = true;
this.btnSelect.Click += new System.EventHandler(this.btnSelect_Click);
// Button - Open
this.btnOpen.Location = new System.Drawing.Point(150, 226);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(105, 33);
this.btnOpen.TabIndex = 2;
this.btnOpen.Text = "打开文件";
this.btnOpen.UseVisualStyleBackColor = true;
this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
// MainForm
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(539, 274);
this.Controls.Add(this.btnOpen);
this.Controls.Add(this.btnSelect);
this.Controls.Add(this.lstFiles);
this.Name = "MainForm";
this.Text = "Open Multiple Files";
this.ResumeLayout(false);
}
// `STAThread` 是一种 COM/Automation 线程模型的标记,用于指定应用程序的主线程应该在单线程单元 (STA) 中执行。通常情况下,只有使用 COM 组件或调用支持 STA 的第三方库时,才需要使用 `STAThread`。
// 在 .NET Framework 中,使用 `STAThread` 的应用程序主要用于图形用户界面 (GUI) 编程。
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
3 编译
命令执行 dotnet build
命令,编译项目。如果编译成功,将会生成可执行文件,在 bin\Debug\netcoreappX.X
文件夹下。其中 X.X 是 .NET Core 的版本号。
dotnet build
MSBuild version 17.5.1+f6fdcf537 for .NET
正在确定要还原的项目…
所有项目均是最新的,无法还原。
call-notepad -> E:\Gitee\csharp\call-notepad\bin\Debug\net7.0-windows\call-notepad.dll
已成功生成。
0 个警告
0 个错误
已用时间 00:00:03.97
生成的文件如下:
call-notepad.deps.json call-notepad.exe* call-notepad.runtimeconfig.json
call-notepad.dll* call-notepad.pdb
dotnet build
命令将项目及其依赖项生成为一组二进制文件。 二进制文件包括扩展名为 .dll 的中间语言 (IL) 文件中的项目代码。 根据项目类型和设置,可能会包含其他文件,例如:
- 可用于运行应用程序的可执行文件(如果项目类型是面向 .NET Core 3.0 或更高版本的可执行文件)。
- 用于调试的扩展名为 .pdb 的符号文件。
- 列出了应用程序或库的依赖项的 .deps.json 文件。
- 用于指定应用程序的共享运行时及其版本的 .runtimeconfig.json 文件。
- 项目通过项目引用或 NuGet 包引用所依赖的其他库。
对于目标版本低于 .NET Core 3.0 的可执行项目,通常不会将 NuGet 中的库依赖项复制到输出文件夹。 而是在运行时从 NuGet 全局包文件夹中对其进行解析。
考虑到这一点,dotnet build
的产品还未准备好转移到另一台计算机进行运行。 要创建可部署的应用程序版本,需要发布该应用程序(例如,使用 dotnet publish 命令)。 有关详细信息,请参阅 .NET 应用程序部署。
4 打包发布
运行 dotnet publish
命令,将项目打包成发布版。该命令会编译项目、还原项目依赖项,然后将发布版文件复制到指定的输出目录。
# 该命令使用 `Release` 配置编译项目,并将发布版文件复制到指定的输出目录release_app,且指定了windows 64依赖,目标计算机上必须安装兼容的 .NET 运行时才能运行该应用程序。
dotnet publish -c Release -o release_app -r win-x64 --no-self-contained
# 或下面这种单文件发布方式,更为简单
dotnet publish -c Release -o release_app -r win-x64 --self-contained=false /p:PublishSingleFile=true
publish具体用法
dotnet publish [<PROJECT>|<SOLUTION>] [-a|--arch <ARCHITECTURE>]
[-c|--configuration <CONFIGURATION>]
[-f|--framework <FRAMEWORK>] [--force] [--interactive]
[--manifest <PATH_TO_MANIFEST_FILE>] [--no-build] [--no-dependencies]
[--no-restore] [--nologo] [-o|--output <OUTPUT_DIRECTORY>]
[--os <OS>] [-r|--runtime <RUNTIME_IDENTIFIER>]
[--sc|--self-contained [true|false]] [--no-self-contained]
[-s|--source <SOURCE>] [--use-current-runtime, --ucr [true|false]]
[-v|--verbosity <LEVEL>] [--version-suffix <VERSION_SUFFIX>]
dotnet publish -h|--help
Usage:
dotnet publish [<PROJECT | SOLUTION>...] [options]
Arguments:
<PROJECT | SOLUTION> 要操作的项目或解决方案文件。如果没有指定文件,则命令将在当前目录里搜索一个文件。
Options:
--ucr, --use-current-runtime 将当前运行时用作目标运行时。
-o, --output <OUTPUT_DIR> 要放置已发布项目的输出目录。
--manifest <MANIFEST> 指向目标清单文件的路径,该文件包含要通过发布步骤执行的包的列表。
--no-build 发布之前不要生成项目。Implies --no-restore.
--sc, --self-contained 随应用程序一起发布 .NET 运行时,这样就不需要在目标计算机上安装运行时。
如果指定了运行时标识符,则默认值为 "true"。
--no-self-contained 将应用程序发布为依赖框架的应用程序。目标计算机上必须安装兼容的 .NET 运行时才能运行该应用程序。
--nologo 不显示启动版权标志或版权消息。
-f, --framework <FRAMEWORK> 要发布的目标框架。必须在项目文件中指定目标框架。
-r, --runtime <RUNTIME_IDENTIFIER> 要发布的目标运行时。在创建自包含部署时使用。
默认情况下发布依赖于框架的应用程序。
-c, --configuration <CONFIGURATION> 要发布的配置。默认值为 “Debug”。使用 `PublishRelease` 属性将 “Release” 作为此命令的默认值。
--version-suffix <VERSION_SUFFIX> 设置生成项目时使用的 $(VersionSuffix) 属性的值。
--interactive 允许命令停止和等待用户输入或操作(例如,用以完成身份验证)。
--no-restore 生成前请勿还原项目。
-v, --verbosity <LEVEL> 设置 MSBuild 详细程度。允许值为 q[uiet]、m[inimal]、n[ormal]、d[etailed] 和 diag[nostic]。
-a, --arch <arch> 目标体系结构。
--os <os> 目标操作系统。
--disable-build-servers 强制命令忽略任何永久性生成服务器。
-?, -h, --help 显示命令行帮助。
release_app目录输出包括以下几类文件:
call-notepad.deps.json 包含项目所有依赖项的 .deps.json 文件。
call-notepad.dll 扩展名为 dll 的程序集中的中间语言 (IL) 代码。
call-notepad.exe 可执行程序
call-notepad.pdb 用于调试的扩展名为 .pdb 的符号文件。
call-notepad.runtimeconfig.json .runtimeconfig.json 文件,其中指定了应用程序所需的共享运行时,以及运行时的其他配置选项(例如垃圾回收类型)。
... 应用程序的依赖项,将这些依赖项从 NuGet 缓存复制到输出文件夹等。
在输出目录中找到发布版文件,可以将该文件拷贝到目标机器上运行。
在 dotnet publish
命令中,还可以使用其他选项来自定义发布版文件的内容和格式。
例如,可以使用 --self-contained
选项指定发布版文件包含 .NET Core Runtime,这使得可以将应用程序拷贝到不同的操作系统、处理器体系结构和 .NET Core 版本上运行,而无需在目标机器上安装 .NET Core Runtime。
由于包含了Runtime,所以生成的文件通常比较大。