NET-Mapnik icon indicating copy to clipboard operation
NET-Mapnik copied to clipboard

DllMain changes environment variables

Open pcrockett opened this issue 8 years ago • 5 comments

NETMapnik only seems to work when the Mapnik data files are in the process's current working directory. I think this is because the GDAL_DATA, PROJ_LIB, and ICU_DATA environment variables are set to relative paths when the DLL is loaded.

BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle,
    IN DWORD     nReason,
    IN LPVOID    Reserved)
{
    switch (nReason)
    {
        case DLL_PROCESS_ATTACH:
            _putenv_s("PROJ_LIB", "share\\proj");
            _putenv_s("ICU_DATA", "share\\icu");
            _putenv_s("GDAL_DATA", "share\\gdal");
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

I have tried changing the environment variables back to what they were before the DLL was loaded, but even when I do that, Mapnik still behaves like it wants to use the relative paths.

Is there another way for me to tell Mapnik where the actual GDAL, PROJ, etc. data files reside?

pcrockett avatar Dec 30 '16 18:12 pcrockett

Ah, just found related issue #14. Still, I'd like to not force the user to put the data files in the working directory of the current process, mainly because I'm writing code in ASP.NET and the default working directory is C:\Windows\System32\inetsrv. I don't want to install Mapnik files in that directory on my client's servers.

pcrockett avatar Dec 30 '16 18:12 pcrockett

The reason for the hard coded environmental variables is to avoid conflicts with existing PROJ/GDAL/ICU installs and limit outside dependencies. That being said i am open to optionally allowing these variables to be overridden if it is done right (i.e. see discussion in #35).

Regarding the ASP.NET working directory, i am guessing that you are having issues referencing unmanaged dlls and data files at run time? This is a common problem in IIS because IIS shadow copies all your managed assemblies to a temp directory but leaves everything else behind. The best solution in my opinion is to turn shadow copy off (see issue #22). With shadow copy turned off IIS runs everything directly from your bin directory.

<system.web>
<hostingEnvironment shadowCopyBinAssemblies="false" />
</system.web>

jbrwn avatar Dec 30 '16 19:12 jbrwn

Yes, I have discovered problems with shadow copy and disabled it. However I'm finding that even with shadow copy off, the working directory of the process is not the bin directory. It's C:\Windows\System32\inetsrv, so it's looking for the proj folder at C:\Windows\System32\inetsrv\share\proj instead of [MyAppDir]\bin\share\proj.

I'm not a C++/CLI developer, but would something like this work?

void setEnvVarIfEmpty(const char* varName, const char* value)
{
    size_t valueSize;

    getenv_s( &valueSize, NULL, 0, varName);
    if (valueSize == 0)
    {
        _putenv_s(varName, value);
    }
}

setEnvVarIfEmpty("PROJ_LIB", "share\\proj");
setEnvVarIfEmpty("ICU_DATA", "share\\icu");
setEnvVarIfEmpty("GDAL_DATA", "share\\gdal");

pcrockett avatar Dec 30 '16 19:12 pcrockett

I believe everything should work as expected with shadowCopyBinAssemblies set to false so this is a bit surprising to me.

I hesitate to use a set-var-if-empty pattern like you suggest. The default should be to use the data files that are local to net-mapnik. This is how it is done in node-mapnik and i agree with this approach. I'd be more inclined to use a NET_MAPNIK_GDAL_DATA environmental var that overrides the default location when set.

jbrwn avatar Dec 30 '16 20:12 jbrwn

Well, perhaps some of the configuration I've done is making Environment.CurrentDirectory default to a weird place.

  • Windows 10 Pro
  • x64 application (using mapnik.x64 NuGet package)
  • Running under regular IIS (not IIS Express that comes with Visual Studio)
  • Using an app pool that's running under a restricted user account (not a member of the regular interactive "Users" group)

Regarding the NET_MAPNIK_GDAL_DATA environment variable, that makes sense. Maybe if I get some time I'll contribute another pull request.

pcrockett avatar Dec 31 '16 00:12 pcrockett