C# - 脚本 - 文件仍在使用中

时间:2014-03-04 17:03:04

标签: c#

我正在使用 CodeDomProvider 类来编译我正在开发的某个应用程序中的脚本。这些是我正在使用的3种方法。

public static void CompileNpcScripts(bool pLoadCompiledScripts)
    {
        Dictionary<string, DateTime> compiledScripts = new Dictionary<string, DateTime>();

        foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\Compiled\\", "*.compiled"))
        {
            compiledScripts.Add(System.IO.Path.GetFileNameWithoutExtension(script), System.IO.File.GetLastWriteTime(script));
        }

        List<string> needCompliation = new List<string>();
        foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\", "*.s"))
        {
            var shortname = System.IO.Path.GetFileNameWithoutExtension(script);
            if (!compiledScripts.ContainsKey(shortname) || compiledScripts[shortname] < System.IO.File.GetLastWriteTime(script))
            {
                needCompliation.Add(script);
            }
        }

        foreach (var script in needCompliation)
        {
            var shortname = System.IO.Path.GetFileNameWithoutExtension(script);

            _usableNpcScripts.Remove(shortname);

            CompilerResults results = CompileScript(ScriptType.Npc, script);
        }

        foreach (var script in System.IO.Directory.GetFiles("..\\DataSvr\\Script\\Compiled\\", "*.compiled"))
        {
            var shortname = System.IO.Path.GetFileNameWithoutExtension(script);

            if (!_usableNpcScripts.ContainsKey(shortname))
            {
                _usableNpcScripts.Add(shortname, Assembly.LoadFile(Environment.CurrentDirectory + "\\" + script));
            }
        }

        if (pLoadCompiledScripts)
        {
            foreach (KeyValuePair<string, Assembly> script in _usableNpcScripts)
            {
                GameServer.NpcScripts.Add(script.Key, (INpcScript)ScriptingTools.FindInterface(script.Value, "INpcScript"));
            }
        }
        else
        {
            foreach (var script in needCompliation)
            {
                var shortname = System.IO.Path.GetFileNameWithoutExtension(script);

                if (GameServer.NpcScripts.ContainsKey(shortname))
                {
                    GameServer.NpcScripts[shortname] = (INpcScript)ScriptingTools.FindInterface(_usableNpcScripts[shortname], "INpcScript");
                }
            }
        }
    }

    public static CompilerResults CompileScript(ScriptType pType, string pSource)
    {
        try
        {
            if (_compiler == null)
            {
                _compiler = CodeDomProvider.CreateProvider("CSharp");
                _compilerParams = new CompilerParameters();

                _compilerParams.GenerateExecutable = false;
                _compilerParams.CompilerOptions = "/optimize";
                // TODO: Should it be generated in memory?
                _compilerParams.GenerateInMemory = false;
                _compilerParams.IncludeDebugInformation = false;
                _compilerParams.ReferencedAssemblies.Add("System.dll");
                _compilerParams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
                { }
                int lol;
            }

            _compilerParams.OutputAssembly = "Scripts\\" + pType + "\\Compiled\\" + System.IO.Path.GetFileNameWithoutExtension(pSource) + ".compiled";
            var result = _compiler.CompileAssemblyFromFile(_compilerParams, pSource);

            if (System.IO.File.Exists(_compilerParams.OutputAssembly))
            {
                System.IO.File.SetLastWriteTime(_compilerParams.OutputAssembly, System.IO.File.GetLastWriteTime(pSource));
            }

            return result;
        }
        catch
        {
            // Stil being used by the user.
            return null;
        }
    }

    public static object FindInterface(Assembly pDLL, string pInterface)
    {
        foreach (Type type in pDLL.GetTypes())
        {
            if (type.GetInterface(pInterface, true) != null)
                return pDLL.CreateInstance(type.FullName);
        }

        return null;
    }

布尔“pLoadCompiledScripts”用于告诉程序脚本应该重新加载还是插入。 GameServer的NpcScripts dictionairy只是INpcScript接口的集合。

现在。在initla加载中,我调用以下内容:CompileNpcScripts(true),因此它将检查需要编译的文件,将重新编译它们,然后将所有这些文件加载​​到dictionairy中。我还有一个FileWatcher类,它监视Script文件夹中的更改。引发事件后,我调用CompileNpcScripts(false),因此它将重新加载现有脚本。但是,CompileScript方法返回null,因为另一个进程正在使用文件“[name] .compiled”。为什么我能这样解决它呢?感谢。

1 个答案:

答案 0 :(得分:0)

问题可能是两件事之一。

首先,检查你的FileWatcher课程并确保它没有抓住它正在观看的任何文件(比如访问上次修改日期属性或任何情况)。

其次,编译器在编译它们之后可能仍然保留脚本。我会尝试处理编译器并在每次重新编译脚本时重建它。