问题描述
最近第一次在操作系统为 Windows Server 的(云)服务器上使用 oommf 的过程中,发现 oommf 的子程序 mmArchive 不能将(OVF格式)场文件保存到 .mif 文件所在的目录中。在(云)服务器上的用户类型为“Administrator”,即管理员用户。
这里使用新版本的oommf(OOMMF 2.0 beta 0 (30-Sep-2022)),它能更加详细的提示 oommf 保存文件失败的原因,如下:
< XX> mmArchive 2.0b0 warning:
Error replying to socket message
‘datafile {C:/Users/ADMINI~1/AppData/Local/Temp/XXX C:/Users/Administrator/XXX}’:
Can’t move file C:/Users/ADMINI~1/AppData/Local/Temp/XXX to C:/Users/Administrator/XXX:
File “C:/Users/ADMINI~1/AppData/Local/Temp/XXX” not owned by current user (BUILTIN/Administrators vs.XXX/Administrator)
(Net_Protocol)
从提示框中可以看出,oommf 提示需要保存的场文件不属于当前用户。但是,我们可以在 oommf 的默认缓存目录中(C:/Users/ADMINI~1/AppData/Local/Temp/XXX)找到该场文件,只不过它的文件名并不规范。
原因分析:
oommf 的各个子程序之间是模块化设计的,专门用于加载 .mif 文件并计算的子程序 Oxsii / Boxsi 会将需要保存的每一个场文件都存放在缓存目录 “C:/Users/ADMINI~1/AppData/Local/Temp/XXX” 中,专门用于保存文件的子程序 mmArchive 会将缓存目录中的场文件移动到用户指定的输出目录(默认情况下就是 .mif 文件所在的目录),接着对它以约定好的命名风格进行重命名。
在 mmArchive 移动缓存目录中的场文件到输出目录之前,它会先对缓存目录中的场文件进行一系列的文件属性识别,详情参考 oommf\app\mmarchive\mmarchive.tcl中的 proc CheckFileMove { f1 f2 errmsg_var }
函数,其中关于对场文件的“所有者”属性的识别语句如下:
if {![file owned $f1]} {
set errmsg "File \"$f1\" not owned by current user"
set sidfile [Oc_WinGetFileSID $f1]
set siduser [Oc_WinGetCurrentProcessSID]
set fileowner [Oc_WinGetSIDAccountName $sidfile]
set user [Oc_WinGetSIDAccountName $siduser]
if {[string compare $fileowner $user]!=0} {
append errmsg " ($fileowner vs. $user)"
} elseif {[string compare $sidfile $siduser]!=0} {
append errmsg " ($sidfile vs. $siduser)"
}
if {[Oc_AmRoot]>0} {
global tcl_platform
if {[string compare windows $tcl_platform(platform)]==0} {
append errmsg \
"\nOOMMF applications should not be run as administrator"
} else {
append errmsg \
"\nOOMMF applications should not be run as root"
}
}
return 0 ;# Require ownership
}
通过判断场文件的“所有者”属性,从而 mmArchive 知道了该文件的“所有者”不属于当前用户,于是就报错了。而且根据源码中 if {[Oc_AmRoot]>0}
的提示可知:oommf 不应该被“管理员”用户(即Windows操作系统中的Administrator用户,Linux操作系统中的Root用户)运行。
解决方案:
暂时找到两个解决方法:
1.在mmarchive.tcl源码中注释掉检查场文件“所有者”属性的语句
这是最简单的方法!首先,完全关闭 oommf 。接着在 oommf\app\mmarchive\mmarchive.tcl 中的 proc CheckFileMove { f1 f2 errmsg_var }
函数里面直接注释掉关于检查场文件“所有者”这一属性的语句,即注释掉上文出现的代码片段。最后,无需重新编译,直接打开 oommf,就可以正常保存场文件了。
不过,由于本人并没有了解过 oommf 的源码,对它的设计思想也不了解,所以并不清楚在源码中注释掉这一代码片段会有什么潜在的影响,或者说场文件的“所有者”属性对 oommf 到底有什么作用。 但目前来看,确实没看出有什么影响。
2.新建一个非管理员用户来运行 oommf
这个方法稍微麻烦一点!在不修改 oommf 源码的情况下,根据上文代码片段中的错误提示信息,我们不用管理员的用户身份去运行 oommf,而是新建一个普通用户来运行。
关于如何在Windows Server(Windows 10 类似)上新建用户的操作请参考:
windows server 2012r2 如何新建一个用户并且可以远程登录
关于在远程登录新建用户的账号时可能遇到的问题,请参考:
连接被拒绝 因为没有授权此用户账户进行远程登录
windows server 2016 开启多用户登陆