1

我有一个 .Net Framework 4.8 应用程序,我需要在其中将一些 html/css 转换为 pdf。

我已经采样了一个 DinkToPdf 的演示项目,它是“.NET Core P/Invoke wrapper for wkhtmltopdf library that uses Webkit engine to convert HTML pages to PDF”。这在 .NET 核心应用程序和 Xamarin Forms 应用程序中有效,但无法在 .Net Framewrk 应用程序中运行。

我已通过 NugetPackageManager 将 DinkToPDF v1.0.8 添加到我的项目的参考文件夹中。我查看了包依赖项并确保所有版本都达到所需版本。由于 DinkToPdf 使用它,我需要将一个本机库复制到我的项目根目录:libwkhtmltox.dll(我尝试过不同版本)我也尝试过 RndUsr0.DinkToPdf 包,它“升级到 .NET Standard 2.0, .NET Core 2.1,wkhtmltopdf v0.12.5。” 但没有更好的结果。

会发生什么:当我的应用调用 basicConverter.Converet(HtmlToPdfDocument doc) 时出现异常:"DinkToPdf.WkHtmlToXBindings::wkhtmltopdf_init' 使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查PInvoke 签名的调用约定和参数与目标非托管签名匹配。"

    public static void ConvertToPdf(/*string [] args*/)
    {
        //load native lib libwkhtmltox.dll
        var architectureFolder = (IntPtr.Size == 8) ? "64 bit" : "32 bit";
        var wkHtmlToPdfPath = Path.Combine(AppContext.BaseDirectory, $"wkhtmltox\\v0.12.4\\{architectureFolder}\\libwkhtmltox.dll");//here a libwkhtmltox.dll needs to be stored 
        IntPtr pDll = NativeMethods.LoadLibrary(wkHtmlToPdfPath);
        if (pDll == IntPtr.Zero)
        {
            throw new FileNotFoundException("-- Cannot load libwkhtmltox == a dll used for html to pdf convertion --");
        }
        var converter = new BasicConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            }
        };
        ObjectSettings objectSettings = new ObjectSettings()
        {
            PagesCount = true,
            HtmlContent = html,
            WebSettings = { DefaultEncoding = "utf-8"}
        };
        doc.Objects.Add(objectSettings);
        byte[] pdf = converter.Convert(doc);//!!! THIS IS THE POINT THAT THROWS UP
        string outputFile = Path.Combine(AppContext.BaseDirectory, "ImageFromHtmnl.pdf");
        using (FileStream stream = new FileStream(outputFile, FileMode.Create))
        {
            stream.Write(pdf, 0, pdf.Length);
        }
    }

总结一下:我希望带有 libwkhtmltox.dll 本机库的 DinkToPdf nuget 包在 .NET Framework 应用程序中的功能与在 .NET Core 应用程序中的功能一样。但事实并非如此。

我错过了什么?

编辑:忘记发布实现对本机库的调用的此类:

static class NativeMethods
{
    [DllImport("kernel32.dll"/*, CallingConvention = CallingConvention.Cdecl*/)]
    public static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);


    [DllImport("kernel32.dll")]
    public static extern bool FreeLibrary(IntPtr hModule);

    public static string GetLibraryPathname(string filename)
    {
        // If 64-bit process, load 64-bit DLL
        bool is64bit = System.Environment.Is64BitProcess;

        string prefix = "Win32";

        if (is64bit)
        {
            prefix = "x64";
        }

        var lib1 = prefix + @"\" + filename;

        return lib1;
    }
}
4

1 回答 1

2

我遇到了核心/标准/框架/xamarin

这很好地解释了:

问题是什么?示例:假设我们使用 .Net Framework 创建了一个应用程序,并将其库用于共享代码。一段时间后,我们觉得在 .Net Core 中创建应用程序并尝试重用在 .Net Framework 中创建的相同共享代码库。我们可以这样做吗?答案是不。由于兼容性问题,我们无法在 .Net Core 中使用 .Net Framework 基类库。基本上,面向.Net Framework 的库只能在基于.Net Framework 的应用程序中运行,而面向.Net Core 的库只能在.Net Core 兼容的应用程序中运行。解决办法是什么? 解决方案是 .Net 标准。.Net Standard 是一组 API 的规范,它与任何 .Net 平台兼容,无论是 .Net Framework 还是 .Net Core。如果我们使用 .Net 标准创建基类库,那么它将与任何 .Net 运行时一起运行。

于 2019-09-17T09:45:27.807 回答