本页说明如何在 .NET Framework 4.8 窗体(或控制台)项目中引用 DLL:同一解决方案内的项目引用、磁盘上的托管程序集,以及手写 DllImport / Declare 调用 C++ 非托管导出。操作文案以 LCode 中文界面为准;凡有代码均同时给出 C# 5.0 与 VB.NET。类库的新建与编译见 DLL 动态链接库开发入门

添加项目引用

同一解决方案内既有「Windows 应用程序」又有「类库」时,优先用项目引用:改完类库再编译解决方案,窗体侧会用到最新输出,不必每次手动挑 bin\Debug 里的文件。

  1. 在项目浏览器中选中要添加引用的项目(通常是窗体应用),或展开其下的引用节点。
  2. 右键项目(或「引用」节点)→ 添加引用;也可菜单 项目 → 添加引用。打开标题为「添加引用」的对话框。
  3. 切换到 项目 页签。列表列标题为项目名称项目目录
  4. 选中目标类库项目,点 选择(E),确认右侧「选择引用」列表中出现该项,再点确定。
  5. 菜单 编译 → 编译解决方案F8)。先保证类库无错误,再运行窗体项目。
界面文案 含义
添加引用 对话框标题;项目/引用节点右键与「项目」菜单中的命令名
项目 页签:列出当前解决方案内可互引的项目
选择(E) 把当前页选中项加入下方「选择引用」列表
引用 项目树中的引用文件夹节点名
提示:项目引用默认会把被引用程序集本地复制到输出目录(属性面板中文名为「本地复制」,对应 MSBuild 的 Copy Local)。同一解决方案内一般保持为 True。多项目与启动项说明见 解决方案与项目

浏览引用托管 DLL

类库不在当前解决方案内、或只拿到第三方 .dll 时,用文件浏览添加托管程序集引用(不要用于纯 C++ 非托管 DLL——那一类走下文的 DllImport / Declare)。

  1. 同样打开「添加引用」对话框。
  2. 切换到 .NET集合浏览器 页签(文案来自界面资源;作用是浏览磁盘上的程序集文件)。
  3. 浏览(B)...,在打开文件对话框中筛选「程序集文件」(*.dll;*.exe),选中目标文件后确定。
  4. 确认下方「选择引用」列表出现该项(类型一般为 Assembly),再点对话框确定。
  5. 也可在 GAC 页签中从全局程序集缓存按引用名称 / 版本选择;需要精确版本时可「选择特定程序集的版本」。
页签 / 控件 用途
.NET集合浏览器 浏览并添加磁盘上的托管 .dll / .exe
浏览(B)... 打开文件选择框;支持多选
GAC 从全局程序集缓存添加(如部分框架程序集)
COM 添加 COM 组件引用(本页不展开)
本地复制 选中引用节点后在属性面板中查看/修改;True 时把 DLL 复制到输出目录
特定版本 是否绑定某一精确程序集版本;版本对不上时易导致加载失败
建议:浏览添加后,引用会写入相对路径(HintPath)。把 DLL 放在解决方案内固定目录(例如 lib\)再引用,比指向另一台机器的绝对路径更稳妥。若只改了外部 DLL 却未重新复制到输出目录,运行时仍可能用旧文件——检查「本地复制」与输出目录内容。

C# / VB.NET 调用示例

假设已按 DLL 入门 在类库 DemoLib 中实现 Greeter.SayHello,并在窗体项目中完成项目引用(或浏览到对应托管 DLL)。在按钮单击中调用:

C#
using System;
using System.Windows.Forms;
using DemoLib;

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    private void btnHello_Click(object sender, EventArgs e)
    {
        Greeter.SayHello("LCode");
    }
}
VB.NET
Imports System
Imports System.Windows.Forms
Imports DemoLib

Public Class MainForm
    Inherits Form

    Private Sub btnHello_Click(sender As Object, e As EventArgs) Handles btnHello.Click
        Greeter.SayHello("LCode")
    End Sub
End Class

命名空间以类库中实际声明为准。若编译提示找不到类型或命名空间:确认引用节点下已有 DemoLib(或程序集名),目标框架均为 v4.8,且类库已成功编译。

调用 C++ 非托管 DLL

纯本机(C/C++)DLL 没有 .NET 元数据,不能靠「添加引用」当托管程序集使用。应在代码中用平台调用声明导出函数:C# 用 [DllImport],VB.NET 用 Declare(或同样的 DllImport)。

下面以系统 user32.dllMessageBeep 为例(无需自备 C++ 工程即可验证声明写法):

C#
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MainForm : Form
{
    [DllImport("user32.dll")]
    private static extern bool MessageBeep(uint uType);

    private void btnBeep_Click(object sender, EventArgs e)
    {
        // 0x00000040 = MB_ICONINFORMATION
        MessageBeep(0x00000040);
    }
}
VB.NET
Imports System
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Public Class MainForm
    Inherits Form

    <DllImport("user32.dll")>
    Private Shared Function MessageBeep(uType As UInteger) As Boolean
    End Function

    ' 等价写法:Declare Function MessageBeep Lib "user32.dll" (ByVal uType As UInteger) As Boolean

    Private Sub btnBeep_Click(sender As Object, e As EventArgs) Handles btnBeep.Click
        ' &H40 = MB_ICONINFORMATION
        MessageBeep(&H40UI)
    End Sub
End Class
注意点 说明
平台位数 进程与本机 DLL 须同为 x86 或同为 x64。AnyCPU 在 64 位系统上常以 64 位运行,无法加载纯 32 位 DLL。请在项目选项中对齐平台目标,并把 DLL 放到可被加载的路径(输出目录或系统搜索路径)。
调用约定 / 字符集 按导出方约定设置 CallingConventionCharSetEntryPoint;名称或约定错误会在运行时抛出 EntryPointNotFoundException / DllNotFoundException
LCode 辅助 主产品界面暂不支持,待更新完善可视化「声明非托管导出」向导;请按文档手写 DllImport / Declare。仓库中的 PInvoke 示例插件不在默认交付路径,本手册不以之为前提。

常见错误

现象 常见原因 处理方向
找不到类型 / 命名空间 未添加引用,或引用的程序集未编译成功 打开「添加引用」确认项目或浏览项存在;先编译类库再编译窗体
找不到程序集(运行时) 输出目录缺少 DLL;「本地复制」为 False;HintPath 失效 检查引用属性「本地复制」;确认 DLL 与 EXE 同目录或路径有效
版本 / 强名称冲突 「特定版本」过严,或绑定重定向与实际文件不一致 核对引用版本;浏览引用时优先使用与编译时一致的文件
BadImageFormatException 位数不匹配(32/64),或把非托管 DLL 当托管引用添加 对齐平台目标;非托管改用 DllImport / Declare
Copy Local / 本地复制未生效 属性被关掉,或手动删了输出目录中的依赖 选中引用 → 属性 →「本地复制」= True,重新编译

相关阅读