1

ディレクトリループで cs スクリプトを実行しようとしています。スクリプトが変更されるたびに (または新しい場合)、スクリプトが読み込まれて実行されます。しかし、スクリプトをもう一度ロードしようとするとエラーが発生します。

Access to the path 'C:\Users\Admin\AppData\Local\Temp\CSSCRIPT\Cache\647885655\hello.cs.compiled' is denied.

私がやろうとしたことは次のとおりです。

static Dictionary<string, string> mFilePathFileHashes = new Dictionary<string, string>();
public static void LoadFromDir(string dir)
{
    foreach (string filepath in Directory.GetFiles(dir))
    {
        string hash = GetMD5HashFromFile(filepath); //Generate file hash
        if (mFilePathFileHashes.Contains(new KeyValuePair<string, string>(filepath, hash))) continue; //Skip if it hasn't changed

        if (mFilePathFileHashes.ContainsKey(filepath))
        { //Hash changed
            mFilePathFileHashes[filepath] = hash;
        }
        else //This is the first time this file entered the loop
            mFilePathFileHashes.Add(filepath, hash);

        //Load the script
        IScript script = CSScript.Load(filepath)
                            .CreateInstance("Script")
                            .AlignToInterface<IScript>();

        //Do stuff
        script.AddUserControl();
    }

protected static string GetMD5HashFromFile(string fileName)
{
    FileStream file = new FileStream(fileName, FileMode.Open);
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] retVal = md5.ComputeHash(file);
    file.Close();

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < retVal.Length; i++)
    {
        sb.Append(retVal[i].ToString("x2"));
    }
    return sb.ToString();
}

「スクリプトをロードする」部分でエラーがスローされます。だから私はそれを少し読んで、これを試しました:

//Load the script
string asmFile = CSScript.Compile(filepath, null, false);
using (AsmHelper helper = new AsmHelper(asmFile, "temp_dom_" + Path.GetFileName(filepath), true))
{
    IScript script = helper.CreateAndAlignToInterface<IScript>("Script");
    script.AddUserControl();

    //helper.Invoke("Script.AddUserControl");
}

そのページが言ったのでScript is loaded in the temporary AppDomain and unloaded after the execution. To set up the AsmHelper to work in this mode instantiate it with the constructor that takes the assembly file name as a parameter

しかし、それはインターフェイスに合わせません:Type 'Script' in Assembly 'hello.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.それはどういう意味ですか?なぜシリアライズ可能にする必要があるのでしょうか?

代わりに行に切り替えるとhelper.Invoke、NullReferenceException が発生します。

スクリプト:

using System;
using System.Windows.Forms;
using CSScriptTest;

class Script : CSScriptTest.IScript
{ 
    public void AddUserControl()
    {
        Form1.frm.AddUserControl1(this, "test_uc_1");
    }
} 

したがって、最後のエラーは、実際にインターフェイスにアラインしたことがないか、メインの AppDomain の外部から静的メソッドを呼び出しているためである可能性があります (実際にはわかりません)。

これを機能させる方法はありますか?

4

1 に答える 1

0

さて、それは私が操作したいオブジェクトを次のようにインターフェースのメソッドに渡すことによって機能します:

using (var helper = new AsmHelper(CSScript.Compile(filepath), null, false))
{
    IScript script = helper.CreateAndAlignToInterface<IScript>("Script");
    script.AddUserControl(Form1.frm);
}

MarshalByRefObjectスクリプトは次のように継承します。

using System;
using System.Windows.Forms;
using CSScriptTest;

class Script : MarshalByRefObject, CSScriptTest.IScript
{ 
    public void AddUserControl(CSScriptTest.Form1 host)
    {
        host.AddUserControl1(this, "lol2");
    }
}

MSDN saisMarshalByRefObject Enables access to objects across application domain boundaries in applications that support remoting.ですから、それは理にかなっていると思いますが、メインアプリケーションのメソッドをスクリプトに公開する方法はありますか?

MarshalByRefObject次のように、メインプログラムから継承することはできないようです。

public class CTestIt : MarshalByRefObject
{
    public static CTestIt Singleton;
    internal static void SetSingleton()
    { //This method is successfully executed before we start loading scripts
        Singleton = new CTestIt();
        Console.WriteLine("CTestIt Singleton set"); 
    }

    public static void test()
    {
       //Null reference when a script calls CSScriptTest.CTestIt.test();
        Singleton.test_member(); 
    }

    public void test_member()
    {
        Console.WriteLine("test");
    }
}
于 2012-10-17T19:33:56.447 に答える