I am trying to execute cs scripts in a directory a loop. Every time the script changed (or if it's new) it gets loaded and executed. But I receive an error on trying to load the script a second time:
Access to the path 'C:\Users\Admin\AppData\Local\Temp\CSSCRIPT\Cache\647885655\hello.cs.compiled' is denied.
What I tried to do was:
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();
}
At the "Load the script" part it would throw the error. So I read up on it a bit and tried this:
//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");
}
Because that page said 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
But that won't Align to the interface : Type 'Script' in Assembly 'hello.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
What does that even mean, and why would it need to be serializable?
If I switch to the helper.Invoke
line instead I get a NullReferenceException.
The script:
using System;
using System.Windows.Forms;
using CSScriptTest;
class Script : CSScriptTest.IScript
{
public void AddUserControl()
{
Form1.frm.AddUserControl1(this, "test_uc_1");
}
}
So that last error may be because I never actually Aligned to an interface, or because I am calling a static method from outside of the main AppDomain (I really wouldn't know).
Is there any way to get this working?