简体   繁体   中英

Why is “Environment.CurrentDirectory” set to “C:\\Program Files\\IIS Express”?

I am following API Gateway example at https://www.c-sharpcorner.com/article/building-api-gateway-using-ocelot-in-asp-net-core/

And I create an empty asp.net web api application and followed the steps as mentioned in above link.

My Main() function in Program.cs file is:

    public static void Main(string[] args)
    {
        IWebHostBuilder builder = new WebHostBuilder();
        builder.ConfigureServices(s =>
        {
            s.AddSingleton(builder);
        });
        builder.UseKestrel()
               .UseContentRoot(Directory.GetCurrentDirectory())
               .UseStartup<Startup>()
               .UseUrls("http://localhost:9000");

        var host = builder.Build();
        host.Run();
    }

Also, my Startup.cs file has following code:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder();
        builder.SetBasePath(Environment.CurrentDirectory)
               .AddJsonFile("configuration.json", optional: false, reloadOnChange: true)
               .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; private set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        Action<ConfigurationBuilderCachePart> settings = (x) =>
        {
            x.WithMicrosoftLogging(log =>
            {
                log.AddConsole(LogLevel.Debug);

            }).WithDictionaryHandle();
        };
        services.AddOcelot();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        await app.UseOcelot();
    }
}

When I run the code, I get error for file configuration.json NOT FOUND . And when I check the source code for current directory in above functions I see that the Directory.GetCurrentDirectory() returns PATH as C:\\\\Program Files\\\\IIS Express and not the current project directory.

My question is why is the path set to IIS directory ? How can I fix this ?

This is a bug in ASP.NET Core 2.2 which has been reported in Github and Microsoft ASP.NET Core team has provided an solution as follows and they will add this solution in the feature version of ASP.NET Core.

Write a helper class as follows:

public class CurrentDirectoryHelpers
{
    internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    [System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
    private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    private struct IISConfigurationData
    {
        public IntPtr pNativeApplication;
        [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
        public string pwzFullApplicationPath;
        [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
        public string pwzVirtualApplicationPath;
        public bool fWindowsAuthEnabled;
        public bool fBasicAuthEnabled;
        public bool fAnonymousAuthEnable;
    }

    public static void SetCurrentDirectory()
    {
        try
        {
            // Check if physical path was provided by ANCM
            var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
            if (string.IsNullOrEmpty(sitePhysicalPath))
            {
                // Skip if not running ANCM InProcess
                if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
                {
                    return;
                }

                IISConfigurationData configurationData = default(IISConfigurationData);
                if (http_get_application_properties(ref configurationData) != 0)
                {
                    return;
                }

                sitePhysicalPath = configurationData.pwzFullApplicationPath;
            }

            Environment.CurrentDirectory = sitePhysicalPath;
        }
        catch
        {
            // ignore
        }
    }
}

Then call the SetCurrentDirectory() method in the Main method as follows:

public static void Main(string[] args)
{

     CurrentDirectoryHelpers.SetCurrentDirectory(); // call it here


    IWebHostBuilder builder = new WebHostBuilder();
    builder.ConfigureServices(s =>
    {
        s.AddSingleton(builder);
    });
    builder.UseKestrel()
           .UseContentRoot(Directory.GetCurrentDirectory())
           .UseStartup<Startup>()
           .UseUrls("http://localhost:9000");

    var host = builder.Build();
    host.Run();
}

Now everything should work fine!

You can also run this out of process until a permanent fix is provided in .net core 3.0. To change this you can change the setting in the csproj file from

<AspNetCoreHostingModel>inprocess</AspNetCoreHostingModel>

to

<AspNetCoreHostingModel>outofprocess</AspNetCoreHostingModel>

Or if you are running under IISExpress you can set the Hosting Model in the launchsettings.json file. Right click the project file in Visual Studion and Properties -> Debug -> Web Server Setting -> Hosting Model. Setting it to Out of Process will add

"ancmHostingModel": "OutOfProcess" 

to the IIS Express profile in launchsettings.json

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM