You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在WPF中从DLL读取PDF并在Adobe PDF Reader控件显示?

解决WPF中加载DLL嵌入PDF的问题

你遇到的核心问题是:Adobe的AxAcroPDF控件不支持WPF的pack URI格式——它是基于WinForms的ActiveX控件,只能识别标准的本地文件系统路径,或者通过间接方式加载(比如先把嵌入的资源转成临时文件)。下面给你两种可行的解决方案,按需选择:

方法一:将嵌入PDF提取到临时文件加载

这是适配现有AxAcroPDF控件的快速方案,步骤如下:

  1. 确认资源配置:首先确保DLL中的PDF文件在Visual Studio里的生成操作设置为「嵌入的资源」,否则程序无法读取到资源。
  2. 读取嵌入资源流:通过程序集获取资源的流,注意资源名称的格式是「命名空间.文件夹路径.文件名.pdf」(比如你的项目命名空间是SampleClass,PDF放在PDFs文件夹下,那资源名就是SampleClass.PDFs.xxx.pdf)。
  3. 写入临时文件并加载:把流复制到系统临时文件夹的临时文件,再用AxAcroPDF加载这个路径,最后记得在窗口关闭时清理临时文件。

示例代码:

using System.Reflection;
using System.IO;
using System.Windows;

// 获取包含PDF资源的程序集(如果PDF在当前运行的程序集里就用GetExecutingAssembly,否则替换为对应的Assembly)
var assembly = Assembly.GetExecutingAssembly();
// 替换成你的实际资源名称,注意大小写和路径
var resourceName = "SampleClass.PDFs.YourTargetPDF.pdf";

using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
    if (resourceStream == null)
    {
        MessageBox.Show("未找到指定的PDF嵌入资源,请检查资源名称是否正确");
        return;
    }

    // 创建唯一的临时PDF文件,避免冲突
    string tempPdfPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.pdf");
    
    // 将资源流写入临时文件
    using (FileStream tempFileStream = new FileStream(tempPdfPath, FileMode.Create))
    {
        resourceStream.CopyTo(tempFileStream);
    }

    // 加载PDF到Acrobat控件
    axAcroPDF1.LoadFile(tempPdfPath);

    // 窗口关闭时清理临时文件(忽略删除失败的情况,比如文件被占用)
    this.Closed += (sender, e) =>
    {
        if (File.Exists(tempPdfPath))
        {
            try { File.Delete(tempPdfPath); }
            catch { }
        }
    };
}

小提示

如果不确定资源名称,可以用assembly.GetManifestResourceNames()列出所有嵌入资源,找到你要的PDF对应的名称。

方法二:换用支持流加载的PDF控件(更安全高效)

如果不想依赖临时文件(避免磁盘残留敏感内容),推荐使用支持直接从流加载PDF的WPF/WinForms控件,比如:

  • PdfiumViewer:开源免费,支持WPF(通过WindowsFormsHost嵌入),可以直接加载流。
  • Syncfusion PdfViewer:商业控件,功能更丰富,原生支持WPF和流加载。

以PdfiumViewer为例,示例代码(需要先安装NuGet包PdfiumViewer):

using System.Reflection;
using System.IO;
using PdfiumViewer;

var assembly = Assembly.GetExecutingAssembly();
var resourceName = "SampleClass.PDFs.YourTargetPDF.pdf";

using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
    if (resourceStream != null)
    {
        // 创建PdfViewer控件并加载流
        var pdfViewer = new PdfViewer();
        pdfViewer.Load(resourceStream);
        
        // 嵌入到WPF的WindowsFormsHost中(需要在XAML里先添加WindowsFormsHost控件)
        windowsFormsHost.Child = pdfViewer;
    }
}

这种方式不需要生成临时文件,更符合你“避免外部访问”的需求,也更整洁。

内容的提问来源于stack exchange,提问作者Dante123

火山引擎 最新活动