ABP Zero 5.3.0 (ASP.Net Core 2.0.2) 发布问题
在发布 ABP Zero 5.3.0,ASP.Net Core 版本 2.0.2 到 Win 2012 R2 服务器时,遇到一个奇怪的问题,发布到 IIS 后,打开站点报 500 错误。

查看站点下 “App_Data\Logs\Log.txt”,显示的错误详情如下
1 ERROR 2018-04-21 12:02:23,413 [3 ] Microsoft.AspNetCore.Server.Kestrel - Connection id "0HLD77HRIRUNH", Request id "0HLD77HRIRUNH:00000001": An unhandled exception was thrown by the application. 2 System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.Hosting.resources, Version=2.0.2.0, Culture=zh-CN, PublicKeyToken=adb9793829ddae60'. 系统找不到指定的路径。 3 File name: 'Microsoft.AspNetCore.Hosting.resources, Version=2.0.2.0, Culture=zh-CN, PublicKeyToken=adb9793829ddae60' ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\inetpub\wwwroot\MyAPI\Plugins'. 4 at System.IO.Win32FileSystemEnumerableIterator`1.HandleError(Int32 errorCode, String path) 5 at System.IO.Win32FileSystemEnumerableIterator`1.CommonInit() 6 at System.IO.Win32FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler) 7 at System.IO.Win32FileSystemEnumerableFactory.CreateFileNameIterator(String path, String originalUserPath, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption) 8 at System.IO.Win32FileSystem.EnumeratePaths(String fullPath, String searchPattern, SearchOption searchOption, SearchTarget searchTarget) 9 at System.IO.Directory.EnumerateFileSystemNames(String path, String searchPattern, SearchOption searchOption, Boolean includeFiles, Boolean includeDirs) 10 at System.IO.Directory.EnumerateFiles(String path, String searchPattern, SearchOption searchOption) 11 at Abp.Reflection.AssemblyHelper.GetAllAssembliesInFolder(String folderPath, SearchOption searchOption) 12 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode) 13 --- End of stack trace from previous location where exception was thrown --- 14 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 15 at System.Lazy`1.CreateValue() 16 at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext() 17 at System.Linq.Set`1.UnionWith(IEnumerable`1 other) 18 at System.Linq.Enumerable.DistinctIterator`1.FillSet() 19 at System.Linq.Enumerable.DistinctIterator`1.ToList() 20 at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 21 at Abp.PlugIns.AbpPlugInManager.<>c__DisplayClass6_0.<RegisterToAssemblyResolve>b__0(Object sender, ResolveEventArgs args) 22 at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName) 23 at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks, IntPtr ptrLoadContextBinder) 24 at System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(String name, CultureInfo culture, Version version, Boolean throwOnFileNotFound, StackCrawlMark& stackMark) 25 at System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(CultureInfo lookForCulture, StackCrawlMark& stackMark) 26 at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark) 27 at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark) 28 at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents) 29 at System.Resources.ResourceManager.GetString(String name, CultureInfo culture) 30 at Microsoft.AspNetCore.Hosting.Resources.GetString(String name, String[] formatterNames) 31 at Microsoft.AspNetCore.Hosting.Views.ErrorPage.<ExecuteAsync>d__6.MoveNext() 32 --- End of stack trace from previous location where exception was thrown --- 33 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 34 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 35 at Microsoft.Extensions.RazorViews.BaseView.<ExecuteAsync>d__29.MoveNext() 36 --- End of stack trace from previous location where exception was thrown --- 37 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 38 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 39 at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.<ProcessRequestsAsync>d__2.MoveNext()
先看到有一个路径信息,说站点下缺少“Plugins” 文件夹,于是手动增加了该文件夹,重新启动站点,还是报一样的错,就认为不是这个原因,还原现场我就把 “Plugins”

另外根据报错信息 “Could not load file or assembly 'Microsoft.AspNetCore.Hosting.resources, Version=2.0.2.0, Culture=zh-CN, PublicKeyToken=adb9793829ddae60'. 系统找不到指定的路径。”,怀疑是 AspNetCore.Hosting 版本差异引起的问题,因为之前服务器安装的是 DotNetCore.2.0.0-WindowsHosting.exe,所以我又下载了最新的 Asp.Net Runtime( "AspNetCore.2.0.7.RuntimePackageStore_x64.exe"),但是安装完后再次运行站点还是同样的错误。
之后通过搜索了很多网站,也尝试了很多不同的解决方案都无效,为了得到更多的信息,修改了 web.config 中 stdoutLogEnabled="true",但是日志文件夹 "logs"没有自动生成,在手动创建了 logs 文件夹后,刷新网站也没有日志写入该文件夹下,而 “App_Data\Logs\Log.txt” 日志里记录的还是同样的异常信息。

网络上已经找不到解决方案了,已经穷途末路。根据以上的情况综合分析后,我有一个假设,会不会是某些特别的权限问题导致的呢,于是我将站点文件夹拷贝到了另外一个用户自己创建的目录下,不再放 “C:\inetpub\wwwroot” 里。重启 iis 后,打开站点,还是500错误,但是 stdoutLog 日志文件生成,这印证了我的假设,日志的错误显示明确了很多,缺少 “Plugins” 文件夹。

在新的站点目录下添加了 “Plugins” 文件夹后,重新打开站点,看到了熟悉的画面,内心是无比的欣悦啊,耗时大半天总算解决了这个奇葩的问题。

总结,在 “C:\inetpub\wwwroot” 下部署的站点,很容易出现莫名其妙的权限问题,即使是用 iis 运行账户的用户去创建的文件夹也会出现权限问题,所以为了避免这些奇怪的问题出现,建议将站点部署到 “C:\inetpub\wwwroot” 外的用户文件夹下。

浙公网安备 33010602011771号