/// <summary> /// Install the script package at the specified path. The script package should be a valid /// ZIP file that contains an install.ini file with a "CIXReader Script" section. /// </summary> /// <param name="installerPath">Path to the installation package</param> public void InstallScriptPackage(string installerPath) { bool success = false; ScriptManifest manifest = ReadPackageManifest(installerPath); if (manifest == null) { LogFile.WriteLine("Bad script package: missing install.ini in {0}", installerPath); } else { // Can accept blanks for everything apart from Script if (string.IsNullOrWhiteSpace(manifest.ScriptFile)) { LogFile.WriteLine("Bad script package: missing Script entry in install.ini in {0}", installerPath); } else { success = true; ScriptPackage isp = new ScriptPackage(manifest); if (isp.ShowDialog() == DialogResult.OK) { // All OK, so unpack the lot and install string packageName = Path.GetFileNameWithoutExtension(installerPath); if (packageName != null) { string scriptFolder = Path.Combine(CIX.HomeFolder, "scripts", packageName); if (!Directory.Exists(scriptFolder)) { Directory.CreateDirectory(scriptFolder); } if (UnzipPackage(installerPath, scriptFolder)) { manifest = new ScriptManifest(Path.Combine(scriptFolder, ManifestFileName)); LoadSingleScript(scriptFolder, manifest); } } } } } if (!success) { MessageBox.Show(Resources.ScriptInstallError, Resources.AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); } }
/// <summary> /// Read the script package manifest /// </summary> /// <param name="installerPath">Path to the script package</param> private static ScriptManifest ReadPackageManifest(string installerPath) { try { using (ZipInputStream s = new ZipInputStream(File.OpenRead(installerPath))) { ZipEntry theEntry; while ((theEntry = s.GetNextEntry()) != null) { string fileName = Path.GetFileName(theEntry.Name); if (fileName == ManifestFileName) { string temporaryManifestFile = Path.GetTempFileName(); using (FileStream streamWriter = File.Create(temporaryManifestFile)) { byte[] data = new byte[2048]; while (true) { int size = s.Read(data, 0, data.Length); if (size > 0) { streamWriter.Write(data, 0, size); } else { break; } } } ScriptManifest manifest = new ScriptManifest(temporaryManifestFile); File.Delete(temporaryManifestFile); return(manifest); } } } } catch (Exception e) { LogFile.WriteLine("Cannot read zip file {0} : {1}", installerPath, e.Message); } return(null); }
/// <summary> /// Load a single script from the specified manifest. /// </summary> private void LoadSingleScript(string path, ScriptManifest manifest) { string scriptFile = Path.Combine(path, manifest.ScriptFile); NLua.Lua lua = new NLua.Lua(); lua.LoadCLRPackage(); _luaAPI.RegisterFunctions(lua); bool success = true; try { lua.DoFile(scriptFile); LuaFunction fnc = lua.GetFunction("on_load"); if (fnc != null) { object[] res = fnc.Call(); if (res != null && res.Length == 1) { success = Convert.ToBoolean(res[0]); } } // Cache this script object for event callbacks if the // init function returns success. if (success) { if (_scriptObjects.ContainsKey(scriptFile)) { // BUGBUG: What if we have scripts that register events? We need to tell // them to unregister first. Add an interface for this. NLua.Lua oldScript = _scriptObjects[scriptFile]; oldScript.Dispose(); _scriptObjects.Remove(scriptFile); } _scriptObjects.Add(scriptFile, lua); } if (manifest.InstallToToolbar) { ToolbarDataItem item = new ToolbarDataItem { type = "button", name = "Script", label = manifest.Name, tooltip = manifest.Description, data = scriptFile, image = manifest.IconFile }; CRToolbarItemCollection.DefaultCollection.Add(item); } } catch (Exception e) { LogFile.WriteLine("Error loading script {0} : {1}", scriptFile, e.Message); success = false; } if (success) { LogFile.WriteLine("Loaded and initialised script {0}", scriptFile); } else { lua.Dispose(); } }
/// <summary> /// Initialises a new instance of the <see cref="ScriptPackage"/> class. /// </summary> public ScriptPackage(ScriptManifest manifest) { InitializeComponent(); _manifest = manifest; }
/// <summary> /// Read the script package manifest /// </summary> /// <param name="installerPath">Path to the script package</param> private static ScriptManifest ReadPackageManifest(string installerPath) { try { using (ZipInputStream s = new ZipInputStream(File.OpenRead(installerPath))) { ZipEntry theEntry; while ((theEntry = s.GetNextEntry()) != null) { string fileName = Path.GetFileName(theEntry.Name); if (fileName == ManifestFileName) { string temporaryManifestFile = Path.GetTempFileName(); using (FileStream streamWriter = File.Create(temporaryManifestFile)) { byte[] data = new byte[2048]; while (true) { int size = s.Read(data, 0, data.Length); if (size > 0) { streamWriter.Write(data, 0, size); } else { break; } } } ScriptManifest manifest = new ScriptManifest(temporaryManifestFile); File.Delete(temporaryManifestFile); return manifest; } } } } catch (Exception e) { LogFile.WriteLine("Cannot read zip file {0} : {1}", installerPath, e.Message); } return null; }