【问题标题】:Why is "Environment.CurrentDirectory" set to "C:\\Program Files\\IIS Express"?为什么“Environment.CurrentDirectory”设置为“C:\\Program Files\\IIS Express”?
【发布时间】:2019-01-11 23:33:29
【问题描述】:

我在 https://www.c-sharpcorner.com/article/building-api-gateway-using-ocelot-in-asp-net-core/ 关注 API 网关示例

我创建了一个空的 asp.net web api 应用程序并按照上面链接中提到的步骤进行操作。

我在 Program.cs 文件中的 Main() 函数是:

    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();
    }

另外,我的 Startup.cs 文件有以下代码:

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();
    }
}

当我运行代码时,我收到文件 configuration.json NOT FOUND 的错误。 当我在上述函数中检查当前目录的源代码时,我看到 Directory.GetCurrentDirectory() 返回 PATH 为 C:\\Program Files\\IIS Express 而不是当前项目目录。

我的问题是为什么路径设置为 IIS 目录?我该如何解决这个问题?

【问题讨论】:

  • 尝试使用AppDomain.CurrentDomain.BaseDirectorySystem.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location。您不能依赖当前工作目录来加载资源,因为它可以随时更改。
  • 您使用的是 ASP.NET Core 2.2 InPrpcess 托管模型吗?
  • @TanvirArjel 是的
  • 检查我的答案!

标签: c# asp.net asp.net-web-api


【解决方案1】:

这是 ASP.NET Core 2.2 中的一个错误,已在Github 中报告,Microsoft ASP.NET Core 团队提供了如下解决方案,他们将在功能中添加此解决方案ASP.NET Core 版本。

编写一个辅助类如下:

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
        }
    }
}

然后在Main方法中调用SetCurrentDirectory()方法如下:

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();
}

现在一切都应该正常了!

【讨论】:

    【解决方案2】:

    在 .net core 3.0 中提供永久修复之前,您也可以在进程外运行它。 要更改此设置,您可以更改 csproj 文件中的设置

    <AspNetCoreHostingModel>inprocess</AspNetCoreHostingModel>
    

    <AspNetCoreHostingModel>outofprocess</AspNetCoreHostingModel>
    

    或者,如果您在 IISExpress 下运行,您可以在 launchsettings.json 文件中设置托管模型。右键单击 Visual Studion 中的项目文件和属性 -> 调试 -> Web 服务器设置 -> 托管模型。 将其设置为 Out of Process 将添加

    "ancmHostingModel": "OutOfProcess" 
    

    到 launchsettings.json 中的 IIS Express 配置文件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 2014-05-10
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      • 2015-12-12
      相关资源
      最近更新 更多