news 2026/6/6 3:18:55

C#调用Bartender打印标签后,如何一键导出为图片或PDF存档?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#调用Bartender打印标签后,如何一键导出为图片或PDF存档?

C#集成Bartender实现标签打印与电子化归档全流程指南

在制造业、医药仓储和物流管理中,标签打印系统与电子化存档的衔接直接影响着质量追溯效率。传统纸质标签面临易损毁、难检索的痛点,而单纯依赖打印记录又无法还原标签实际内容。本文将深入讲解如何通过C#调用Bartender的API,在完成标签打印的同时自动生成带时间戳和业务数据的PDF/图片文件,构建完整的"物理标签-电子存档"双向追溯体系。

1. 环境准备与基础配置

1.1 Bartender模板设计规范

在开始编码前,Bartender模板(.btw文件)需要遵循特定设计原则:

  • 动态字段命名:所有需要填充的变量应使用NamedSubString定义,例如:

    ${BatchNumber} - 产品批次号 ${ProductionDate} - 生产日期 ${QRCodeData} - 二维码内容
  • 打印区域设置:通过File > Page Setup确保:

    • 纸张尺寸与实际标签纸匹配
    • 边距不超过打印机的最小要求
    • 开启"Shrink to Fit"防止内容溢出
  • 导出兼容性:在模板属性中勾选:

    Allow Export: True Export Resolution: 300dpi (建议值)

1.2 C#项目依赖配置

创建.NET Framework 4.7.2+或.NET Core 3.1+项目,通过NuGet添加:

Install-Package Interop.BarTender -Version 11.1

app.config中添加COM引用配置:

<configuration> <system.runtime.interopServices> <comImport> <interopAssemblyName>BarTender, Version=11.1.0.0</interopAssemblyName> </comImport> </system.runtime.interopServices> </configuration>

2. 核心代码实现

2.1 打印与导出同步执行

创建LabelService.cs实现双模式操作:

public class LabelService : IDisposable { private BarTender.Application _btApp; private BarTender.Format _btFormat; public void PrintAndExport(string templatePath, string printerName, Dictionary<string, string> fieldValues, string outputPath) { try { _btApp = new BarTender.Application(); _btFormat = _btApp.Formats.Open(templatePath); // 动态填充字段 foreach (var kv in fieldValues) { _btFormat.SetNamedSubStringValue(kv.Key, kv.Value); } // 打印配置 _btFormat.PrintSetup.Printer = printerName; _btFormat.PrintSetup.IdenticalCopiesOfLabel = 1; // 同步执行打印和导出 _btFormat.PrintOut(false, false); // 异步打印 ExportToFile(outputPath); } finally { Cleanup(); } } private void ExportToFile(string outputPath) { string ext = Path.GetExtension(outputPath).ToLower(); string format = ext switch { ".jpg" => "JPG", ".png" => "PNG", ".pdf" => "PDF", _ => throw new ArgumentException("Unsupported format") }; _btFormat.ExportToFile(outputPath, format, BarTender.BtColors.btColors24Bit, BarTender.BtResolution.btResolutionPrinter, BarTender.BtSaveOptions.btDoNotSaveChanges); } public void Dispose() => Cleanup(); private void Cleanup() { _btFormat?.Close(BarTender.BtSaveOptions.btDoNotSaveChanges); _btApp?.Quit(BarTender.BtSaveOptions.btDoNotSaveChanges); } }

2.2 智能文件命名策略

FileNamingService.cs中实现动态路径生成:

public static class FileNamingService { public static string GenerateFilePath(string baseDir, string prefix, Dictionary<string, string> metadata) { var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmssfff"); var paramsStr = string.Join("_", metadata.Select(kv => $"{kv.Key}-{kv.Value}")); // 清理非法字符 var validName = Regex.Replace($"{prefix}_{timestamp}_{paramsStr}", "[\\\\/:*?\"<>|]", "_"); return Path.Combine(baseDir, $"{validName}.pdf"); } }

调用示例:

var fields = new Dictionary<string, string> { {"BatchNumber", "B2023-001"}, {"ExpiryDate", "2025-12-31"} }; string outputPath = FileNamingService.GenerateFilePath( @"D:\LabelArchive", "ProductLabel", fields);

3. 高级功能实现

3.1 批量导出与压缩

创建批量处理器处理多个标签:

public void BatchExport(IEnumerable<LabelRequest> requests, string zipOutputPath) { using var zip = ZipFile.Open(zipOutputPath, ZipArchiveMode.Create); foreach (var req in requests) { string tempPath = Path.GetTempFileName(); using var service = new LabelService(); service.PrintAndExport(req.TemplatePath, req.PrinterName, req.FieldValues, tempPath); zip.CreateEntryFromFile(tempPath, Path.GetFileName(req.OutputFileName)); File.Delete(tempPath); } }

3.2 数据库集成方案

实现EF Core存储方案:

public class LabelArchiveService { private readonly AppDbContext _db; public async Task ArchiveToDatabase(string filePath, Dictionary<string, string> metadata) { var fileBytes = await File.ReadAllBytesAsync(filePath); var record = new LabelArchive { Id = Guid.NewGuid(), FileContent = fileBytes, FileType = Path.GetExtension(filePath), MetadataJson = JsonSerializer.Serialize(metadata), CreatedAt = DateTime.UtcNow }; _db.LabelArchives.Add(record); await _db.SaveChangesAsync(); } }

4. 企业级部署方案

4.1 打印任务监控服务

创建Windows服务监控打印队列:

public class PrintMonitorService : ServiceBase { private FileSystemWatcher _watcher; protected override void OnStart(string[] args) { _watcher = new FileSystemWatcher(@"C:\PrintJobs"); _watcher.Created += OnNewPrintJob; _watcher.EnableRaisingEvents = true; } private void OnNewPrintJob(object sender, FileSystemEventArgs e) { var jobInfo = JsonSerializer.Deserialize<PrintJob>(File.ReadAllText(e.FullPath)); using var service = new LabelService(); service.PrintAndExport(jobInfo.TemplatePath, jobInfo.PrinterName, jobInfo.FieldValues, jobInfo.OutputPath); } }

4.2 与MES系统集成

通过REST API对接生产执行系统:

[ApiController] [Route("api/labels")] public class LabelController : ControllerBase { [HttpPost] public async Task<IActionResult> GenerateLabel([FromBody] LabelRequest request) { string outputPath = FileNamingService.GenerateFilePath( Config.ArchivePath, request.LabelType, request.Metadata); using var service = new LabelService(); service.PrintAndExport( GetTemplatePath(request.LabelType), request.PrinterName, request.Metadata, outputPath); var dbRecord = await _archiveService.ArchiveToDatabase(outputPath, request.Metadata); return Ok(new { dbRecord.Id, FilePath = outputPath }); } }

5. 性能优化与异常处理

5.1 Bartender实例管理

实现对象池管理Bartender实例:

public class BtEnginePool : IDisposable { private ConcurrentQueue<BarTender.Application> _pool = new(); private int _maxInstances = 5; public BarTender.Application GetInstance() { if (_pool.TryDequeue(out var instance)) return instance; if (_pool.Count < _maxInstances) return new BarTender.Application(); throw new InvalidOperationException("Reached maximum instances"); } public void ReturnInstance(BarTender.Application instance) { _pool.Enqueue(instance); } public void Dispose() { while (_pool.TryDequeue(out var instance)) { instance.Quit(BarTender.BtSaveOptions.btDoNotSaveChanges); } } }

5.2 常见错误处理方案

错误类型检测方法解决方案
打印机离线检查btFormat.PrintSetup.PrinterOnline自动切换到备用打印机
模板缺失捕获COMException (0x800A03EC)从版本控制系统恢复模板
磁盘空间不足检查DriveInfo.AvailableFreeSpace触发清理旧文件流程
字段不匹配遍历btFormat.NamedSubStrings验证记录错误并跳过该标签

实现弹性策略:

public class ResilientLabelProcessor { public async Task ProcessWithRetry(LabelRequest request, int maxRetries = 3) { int attempt = 0; while (attempt < maxRetries) { try { using var service = new LabelService(); service.PrintAndExport(...); return; } catch (COMException ex) when (IsTransientError(ex)) { await Task.Delay(1000 * (attempt + 1)); attempt++; } } throw new LabelGenerationException("Max retries exceeded"); } private bool IsTransientError(COMException ex) { return ex.ErrorCode switch { -2146828288 => true, // 打印机忙 -2146828214 => true, // 临时文件错误 _ => false }; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 3:17:13

2026 年,探秘高性价比电子记分牌领先源头厂家

在体育赛事日益增多的今天&#xff0c;电子记分牌的重要性愈发凸显。它不仅能够准确记录比赛分数和时间&#xff0c;还能提升比赛的科技感和观赏性。那么&#xff0c;在众多厂家中&#xff0c;哪家电子记分牌厂家能够提供高性价比的产品呢&#xff1f;让我们一起探秘。一、电子…

作者头像 李华
网站建设 2026/6/6 3:13:07

如何快速掌握Flameshot:开源截图工具完整教程

如何快速掌握Flameshot&#xff1a;开源截图工具完整教程 【免费下载链接】flameshot Powerful yet simple to use screenshot software :desktop_computer: :camera_flash: 项目地址: https://gitcode.com/gh_mirrors/fl/flameshot Flameshot是一款功能强大且完全免费的…

作者头像 李华
网站建设 2026/6/6 3:13:06

以为用平台签就高枕无忧?电子合同平台自验功能的盲区

许多企业误以为在知名第三方电子合同平台签署文件后&#xff0c;依赖平台自身的“验签功能”就足够安全。实际上&#xff0c;这种“既当裁判又当运动员”的自验模式存在严重盲区&#xff1a;它无法跨平台核验多种 CA 证书的有效性&#xff0c;且在面临司法纠纷时缺乏客观中立的…

作者头像 李华
网站建设 2026/6/6 3:12:55

牙齿矫正的收费标准参考

有牙齿矫正需求的市民&#xff0c;最先关注的往往是收费标准&#xff0c;矫正方式、牙齿畸形复杂程度、医疗机构资质的差异&#xff0c;都会直接拉开最终费用的差距。常规金属托槽矫正定价亲民&#xff0c;适配预算有限的青少年群体&#xff0c;陶瓷半隐形矫正美观度更高&#…

作者头像 李华