You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在macOS/Linux编译面向Windows的.NET Core 8 C#程序及打印机设置方案

解决方案汇总

1. 利用.NET交叉编译+Windows目标框架

直接在Linux/macOS上编译面向Windows的程序,核心是指定Windows专属的目标框架和运行时:

  • 修改项目文件(.csproj),指定目标框架为net8.0-windows,并确保包含Windows平台资产:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <WindowsSpecificAssets>all</WindowsSpecificAssets>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Drawing.Common" Version="8.0.0" />
  </ItemGroup>
</Project>
  • 使用WINDOWS条件编译符号包裹System.Drawing.Printing相关代码,确保编译时能识别Windows专属符号:
#if WINDOWS
using System.Drawing.Printing;

public class PrinterHelper
{
    public static (PaperSize, Margins) GetPrinterSettings(string printerName)
    {
        using var settings = new PrinterSettings { PrinterName = printerName };
        return (settings.DefaultPageSettings.PaperSize, settings.DefaultPageSettings.Margins);
    }

    public static void Print(PrintDocument doc) => doc.Print();
}
#endif
  • 在Linux/macOS终端执行交叉编译命令,指定Windows运行时:
dotnet publish -c Release -r win-x64 --self-contained false

(注:需先执行dotnet workload install windows安装Windows目标编译组件)

2. 抽象打印接口分离平台逻辑

通过接口隔离Windows打印实现,避免跨平台编译时的符号错误:

  • 核心项目定义打印接口:
public interface IPrintHandler
{
    (PaperSizeInfo, MarginInfo) GetPrinterConfig(string printerName);
    void ExecutePrint(PrintContent content);
}

// 用自定义类替代System.Drawing的类型,避免跨平台引用问题
public record PaperSizeInfo(string Name, float Width, float Height);
public record MarginInfo(int Left, int Top, int Right, int Bottom);
  • 创建Windows专属类库,实现接口并引用System.Drawing.Printing:
using System.Drawing.Printing;

public class WindowsPrintHandler : IPrintHandler
{
    public (PaperSizeInfo, MarginInfo) GetPrinterConfig(string printerName)
    {
        using var settings = new PrinterSettings { PrinterName = printerName };
        var pageSettings = settings.DefaultPageSettings;
        return (
            new PaperSizeInfo(pageSettings.PaperSize.Name, pageSettings.PaperSize.Width, pageSettings.PaperSize.Height),
            new MarginInfo(pageSettings.Margins.Left, pageSettings.Margins.Top, pageSettings.Margins.Right, pageSettings.Margins.Bottom)
        );
    }

    public void ExecutePrint(PrintContent content)
    {
        // 基于System.Drawing.Printing实现打印逻辑
        using var doc = new PrintDocument();
        doc.PrintPage += (s, e) => { /* 绘制打印内容 */ };
        doc.Print();
    }
}
  • 主项目根据目标平台注册实现:
#if WINDOWS
services.AddSingleton<IPrintHandler, WindowsPrintHandler>();
#else
// 非Windows环境注册空实现,仅用于编译通过
services.AddSingleton<IPrintHandler, NullPrintHandler>();
#endif

public class NullPrintHandler : IPrintHandler
{
    public (PaperSizeInfo, MarginInfo) GetPrinterConfig(string printerName) 
        => throw new NotSupportedException("仅支持Windows平台");

    public void ExecutePrint(PrintContent content) 
        => throw new NotSupportedException("仅支持Windows平台");
}
  • 交叉编译时指定Windows运行时即可,编译过程不会因符号缺失报错。

3. 直接调用Win32 API(进阶方案)

跳过System.Drawing.Printing,通过P/Invoke调用Windows原生API获取打印机设置并执行打印,无需依赖Windows专属库的编译时引用:

using System.Runtime.InteropServices;

public class Win32PrinterHelper
{
    // 示例:获取打印机默认纸张尺寸(简化版)
    [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool GetPrinter(IntPtr hPrinter, int level, IntPtr pPrinter, int cbBuf, out int pcbNeeded);

    public static PaperSizeInfo GetDefaultPaperSize(string printerName)
    {
        // 省略Win32 API调用细节,需自行实现打印机句柄获取、参数解析逻辑
        // 最终返回自定义的PaperSizeInfo对象
    }

    // 打印相关Win32 API调用同理,如StartDocPrinter、StartPagePrinter等
}

这种方式编译时不依赖System.Drawing.Common,仅在Windows运行时调用API,适合对依赖控制严格的场景。


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:15:35