diff --git a/deploy/README.md b/deploy/README.md index 9894b96..e66078c 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -129,6 +129,13 @@ scp "$B"/公共库/设备控制类库/设备控制/DeviceCtrlLibrary.dll "$B"/ "$B"/项目7/任务二/寝室情景模式/寝室情景模式/bin/Debug/*Interop.WMPLib.dll 服务器:IOT_SIM/textbook-libs/ ``` +容器里的平台用普通用户运行,目录和文件要让其他用户能读(用 root 拷的文件常常是 `-rw-------`,导出时会提示"权限不够"): + +```bash +chmod 755 ~/IOT_SIM/textbook-libs +chmod 644 ~/IOT_SIM/textbook-libs/*.dll +``` + 拷好后不用重启,下一次导出就能用。本机开发时同样放在仓库根目录的 `textbook-libs/`(已在 .gitignore 里),也可以用环境变量 `SIM_TEXTBOOK_LIBS` 指到别处。 ## 备份与恢复 diff --git a/runtime/Sim.Runner/ExeExporter.cs b/runtime/Sim.Runner/ExeExporter.cs index 97fd722..9f1a69d 100644 --- a/runtime/Sim.Runner/ExeExporter.cs +++ b/runtime/Sim.Runner/ExeExporter.cs @@ -69,7 +69,7 @@ internal static class ExeExporter /// libsDir:教材 dll 所在目录;galleryDir:平台素材库 public static Result Export(string projectDir, string libsDir, string galleryDir, string assemblyName) { - var libs = Directory.Exists(libsDir) ? Directory.GetFiles(libsDir, "*.dll").OrderBy(p => p, StringComparer.Ordinal).ToArray() : Array.Empty(); + var libs = TextbookLibs(libsDir); if (!libs.Any(p => Path.GetFileName(p) == "DeviceCtrlLibrary.dll")) throw new InvalidOperationException("服务器上没有放教材的设备类库(真机版 DeviceCtrlLibrary.dll 等),不能导出 EXE,请联系老师"); @@ -135,6 +135,32 @@ internal static class ExeExporter return new Result(emit.Success, pe.ToArray(), diagnostics); } + /// + /// 教材 dll 的路径。目录或文件读不了时(服务器上拷进去的文件权限是 600,容器里的平台用户读不到)说明原因, + /// 不把英文的系统报错直接给学生看。 + /// + private static string[] TextbookLibs(string libsDir) + { + if (!Directory.Exists(libsDir)) return Array.Empty(); + string? current = null; + try + { + var libs = Directory.GetFiles(libsDir, "*.dll").OrderBy(p => p, StringComparer.Ordinal).ToArray(); + foreach (var lib in libs) + { + current = lib; + using var _ = File.OpenRead(lib); + } + return libs; + } + catch (UnauthorizedAccessException) + { + var what = current == null ? "目录" : Path.GetFileName(current); + throw new InvalidOperationException( + $"服务器上的教材设备类库读不了({what} 的权限不够),不能导出 EXE,请联系老师(服务器上执行 chmod 755 textbook-libs 和 chmod 644 textbook-libs/*.dll)"); + } + } + /// /// 每个窗体、控件类的 .resources:VS 生成的 Designer.cs 用 ComponentResourceManager 读窗体的 .resx, /// 平台没有 .resx。媒体播放器的 OcxState 放默认状态,其他取到 null(和运行时一样)。