ArtifexSoftware / Ghostscript.NET

Ghostscript.NET - managed wrapper around the Ghostscript library (32-bit & 64-bit)
https://ghostscript.com
GNU Affero General Public License v3.0
391 stars 152 forks source link

Exception at IIS: Module could not be loaded. at Microsoft.WinAny.Interop.DynamicNativeLibrary #121

Closed pawelcodenest closed 5 months ago

pawelcodenest commented 5 months ago

I am trying to use Ghostscript.NET v.1.2.3 with a ghostscript native library installed in a system (version 9.56.1). Running code locally works. But after deploying on a IIS remote server causes an exception:

System.Exception: Module could not be loaded. at Microsoft.WinAny.Interop.DynamicNativeLibrary..ctor(Byte[] buffer) at Ghostscript.NET.GhostscriptLibrary..ctor(GhostscriptVersionInfo version, Boolean fromMemory) at Ghostscript.NET.Processor.GhostscriptProcessor..ctor(GhostscriptVersionInfo version, Boolean fromMemory)

Here is my code snippet:

string executablePath = Assembly.GetExecutingAssembly().Location;
string appDataFolder = System.IO.Path.GetDirectoryName(executablePath);
string binPath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
string inputFilePath = "", outputFilePath = "";

try
{
    inputFilePath = System.IO.Path.Combine(appDataFolder, $"input_{DateTime.Now:yyyy_MM_dd_HH_mm_ss}.pdf");
    File.WriteAllBytes(inputFilePath, bytes);

    outputFilePath = System.IO.Path.Combine(appDataFolder, $"output_{DateTime.Now:yyyy_MM_dd_HH_mm_ss}.pdf");

    List<string> switches = new List<string>
    {
        "-empty",
        "-dSAFER",
        "-dBATCH",
        "-dNOPAUSE",
        "-dNOPROMPT",
        "-sDEVICE=pdfwrite",
        @"-sOutputFile=" + outputFilePath,
        @"-f",
        inputFilePath
    };

    using (GhostscriptProcessor ghostscript = new GhostscriptProcessor())
    {
        ghostscript.Process(switches.ToArray());
    }

    return File.ReadAllBytes(outputFilePath);
}
catch
{
    throw;
}
finally
{
    if (File.Exists(inputFilePath))
        File.Delete(inputFilePath);

    if (File.Exists(outputFilePath))
        File.Delete(outputFilePath);
}

Any ideas?

pawelcodenest commented 5 months ago

Similar exception I got when I use a different constructor with loaded ghostscript lib into buffer:

if (Environment.Is64BitProcess)
{
    pathToGs = System.IO.Path.Combine(binPath, "gsdll64.dll");
}
else
{
    pathToGs = System.IO.Path.Combine(binPath, "gsdll32.dll");
}

List<string> switches = new List<string>
{
    "-empty",
    "-dSAFER",
    "-dBATCH",
    "-dNOPAUSE",
    "-dNOPROMPT",
    "-sDEVICE=pdfwrite",
    @"-sOutputFile=" + outputFilePath,
    @"-f",
    inputFilePath
};

using (GhostscriptProcessor ghostscript = new GhostscriptProcessor(File.ReadAllBytes(pathToGs)))
{
    ghostscript.Process(switches.ToArray());
}
PrimeJoker commented 5 months ago

I think the gsdll cannot be found, thats the main error message. If you replace the path to the actual folder location of the gsdll, does it cause the same error message? Running IIS in production can be very fiddly. I would recommend placing the actual hard coded path to the gsdll. You might be surprised IIS is looking into the c:\windows folder instead of where your Web app is running from.

pawelcodenest commented 5 months ago

Yes, I copy dll's (both x64 and x32) to the bin application folder. Of course the same with GhostsctiptNet.dll And of course I've installed native GhostsScript library in a server (both x64 and x32). The same effect. I've tried to initialize GhostScriptProcessor in a different way, as I mentioned above, but its the same message.

But one thing: I use native gswin64.exe locally - no errors. On a server it throws an exception message: dll cannot be loaded... So maybe that is the reason, but why?

EDITED: Can't load Ghostscript DLL Can't load DLL, LoadLibrary error code 126

Seems, its a missing dependency error.

PrimeJoker commented 5 months ago

Try and retrace your steps. Reinstall ghostscript.net via nuget. You don't need to manually copy it to your webapp bin folder when you build it should do that automatically. You don't need gswin64.exe only the gsdll64.dll/gsdll32.dll and gsdll64.lib/gsdll32.lib. Another question, is a 64/32 bit version installed? Check in IIS in application pools > Advanved settings. Under general section check if the enable 32-bit applications is enabled and disable it for your webapp. Remember to restart your webapp and app pool.

pawelcodenest commented 5 months ago

Resolved. I installed GhostScript version 9.18 (64 bit). And no errors with running it locally, on a remote server and using GhostScript.NET. I use a default constructor in code with default behavior.

List<string> switches = new List<string>
{
    "-empty",
    "-dSAFER",
    "-dBATCH",
    "-dNOPAUSE",
    "-dNOPROMPT",
    "-sDEVICE=pdfwrite",
    @"-sOutputFile=" + outputFilePath,
    @"-f",
    inputFilePath
};

using (GhostscriptProcessor ghostscript = new GhostscriptProcessor())
{
    ghostscript.Process(switches.ToArray());
}
pawelcodenest commented 5 months ago

Issue closed.