using IronPython.Hosting;
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Runtime;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace cforge
{
///
/// Misc helper classes for all kinds of stuff
///
class Helper
{
#region Registry
///
/// Function to check if URL Handler for cforge tool is installed
///
/// true, if yes. false, if not
public static bool CheckRegistryProtocol()
{
RegistryKey cforge = Registry.ClassesRoot.OpenSubKey("cforge");
if (cforge == null)
{
return false;
}
return true;
}
public static void RegisterProtocol(bool bVerbose)
{
try
{
String fullpath = GetCFORGEAssemblyPath();
RegistryKey cforgekey = Registry.ClassesRoot.OpenSubKey("cforge");
cforgekey = Registry.ClassesRoot.CreateSubKey("cforge", true);
cforgekey.SetValue("", "URL:cforge Protocol");
cforgekey.SetValue("URL Protocol", "");
RegistryKey cforgeshell = cforgekey.CreateSubKey("shell");
RegistryKey shellopen = cforgeshell.CreateSubKey("open");
RegistryKey opencommand = shellopen.CreateSubKey("command");
opencommand.SetValue("", "\"" + fullpath + "\" \"%1\"");
Console.WriteLine("[INFO] Installed URL Handler for cforge tool. \r\n\tPath is: " + fullpath);
}
catch (Exception ex)
{
Console.WriteLine("Exception while adding the registry key. Perhaps you are not admin?");
Console.WriteLine(ex.ToString());
}
}
internal static void ShowLicenseInfo()
{
Console.WriteLine("License information ");
Console.WriteLine("");
Console.Write(Resources.license);
Console.WriteLine("");
}
#endregion
#region SystemPath
public static void AddToSystemPath(bool bVerbose)
{
string strPath = System.Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
string[] split = strPath.Split(new Char[] { ';' });
string path = Path.GetDirectoryName(GetCFORGEAssemblyPath());
string strNewSystemPath = strPath + ";" + path;
if (!split.Contains(path))
{
System.Environment.SetEnvironmentVariable("Path", strNewSystemPath, EnvironmentVariableTarget.Machine);
}
}
public static void bootstrap(bool bVerbose)
{
/// bootstrapper
/// warning for svn.exe if not present
string exepath = Helper.FindExePath("svn.exe");
if (exepath == String.Empty)
{
Console.WriteLine("[WARNING] Please install Turtoise SVN with command line client option!");
}
else
{
Console.WriteLine("[INFO] Turtoise SVN detected. \r\n\tPath is: " + exepath);
exepath = String.Empty;
}
/// add libdoc.exe to path to enable CODESYS libdocscripting (TODO expand this section)
exepath = Helper.FindExePath("libdoc.exe");
string strPath = System.Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
string path = String.Empty;
string strNewSystemPath = String.Empty;
if (exepath == String.Empty)
{
/// add path to: "C:\Program Files\CODESYS 3.5.14.0\CODESYS\DocScripting\3.5.14.0"
/// for now quick and dirty => should become dynamic
path = "C:\\Program Files\\CODESYS 3.5.14.0\\CODESYS\\DocScripting\\3.5.14.0";
strNewSystemPath = strPath + ";" + path;
System.Environment.SetEnvironmentVariable("Path", strNewSystemPath, EnvironmentVariableTarget.Machine);
Console.WriteLine("[INFO] Environmentvariable for DocScripting added: \r\n\tPath is: " + path);
}
else
{
Console.WriteLine("[INFO] DocScripting detected. \r\n\tPath is: " + exepath);
exepath = String.Empty;
}
}
///
/// Expands environment variables and, if unqualified, locates the exe in the working directory
/// or the evironment's path.
///
/// The name of the executable file
/// The fully-qualified path to the file
/// Raised when the exe was not found
public static string FindExePath(string exe)
{
exe = Environment.ExpandEnvironmentVariables(exe);
if (!File.Exists(exe))
{
if (Path.GetDirectoryName(exe) == String.Empty)
{
foreach (string test in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(';'))
{
string path = test.Trim();
if (!String.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exe)))
return Path.GetFullPath(path);
}
}
return String.Empty;
/// throw new FileNotFoundException(new FileNotFoundException().Message, exe);
}
return Path.GetFullPath(exe);
}
#endregion
public static bool EasyAttachEnabled()
{
try
{
String path = GetCFORGEAssemblyPath();
String Debugfile = Path.Combine(Path.GetDirectoryName(path), "debug");
if (File.Exists(Debugfile))
return true;
}
catch
{
}
return false;
}
///
/// Function to retrieve the location of the currenty assembly (cforge.exe).
/// This should be located in the CODESYS installation subfolder "CFORGE"
///
/// full path to cforge.exe
private static String GetCFORGEAssemblyPath()
{
String path = System.Reflection.Assembly.GetExecutingAssembly().Location;
return path;
}
private static bool IsCODESYSPathInstallation()
{
String path = GetCFORGEAssemblyPath();
if (path.Contains("bin") && (path.Contains("Debug") || path.Contains("Release")))
return false;
return true;
}
///
/// Function to retrieve the CODESYS AP_ROOT (this is where "Common" etc. folders are)
///
/// full path to AP ROOT
private static String GetCODESYSRoot()
{
if (IsCODESYSPathInstallation())
{
// twice up from cforge.exe (if installed in CODESYS)
String path = GetCFORGEAssemblyPath();
path = Directory.GetParent(path).FullName;
return Directory.GetParent(path).FullName;
}
// for now return a normal installation path for CODESYS
return @"C:\Program Files (x86)\3S CODESYS\CODESYS\";
}
///
/// Function to retrieve the "ScriptLib" Path inside CODESYS. We just take the last one, probably this is the newest one
///
/// full path to ScriptLib version folder
private static String GetCODESYSScriptingLibPath()
{
String path = Path.Combine(GetCODESYSRoot(), "ScriptLib");
String version = Directory.EnumerateDirectories(path).Last();
path = Path.Combine(path, version);
return path;
}
///
/// Function to retrieve the CFORGE Script path (this is where the IronPython scripts should reside)
///
/// full path to CFORGE Scripts
private static String GetCFORGEScriptPath()
{
if (IsCODESYSPathInstallation())
{
// \CFORGE\Scripts
String path = GetCODESYSRoot();
return Path.Combine(path, "CFORGE", "Scripts");
}
String localscriptpath = System.AppDomain.CurrentDomain.BaseDirectory;
localscriptpath = Directory.GetParent(localscriptpath).FullName;
localscriptpath = Directory.GetParent(localscriptpath).FullName;
localscriptpath = Directory.GetParent(localscriptpath).FullName;
return Path.Combine(localscriptpath,"Package", "CFORGE", "Scripts");
}
///
/// Function to enumerate all IronPython scripts to exend cforge.exe inside Scripts folder
///
/// List of IPY scripts
public static List GetAllScripts()
{
List liScripts = new List();
try
{
String path = GetCFORGEScriptPath();
foreach (String file in Directory.EnumerateFiles(path))
{
if (Path.GetExtension(file).ToLowerInvariant() == ".py")
{
String shortfilename = Path.GetFileNameWithoutExtension(file);
liScripts.Add(shortfilename);
}
}
}
catch(Exception e)
{
Console.WriteLine("[EXCEPTION] GetAllScripts: " + e.Message);
}
return liScripts;
}
public static bool IsUserElevated()
{
using (var curIdent = WindowsIdentity.GetCurrent())
{
var principal = new WindowsPrincipal(curIdent);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
public static void RunElevated(String args)
{
String strAssemblyPath = GetCFORGEAssemblyPath();
try
{
Process p = new Process();
p.StartInfo.FileName = strAssemblyPath;
p.StartInfo.Arguments = args;
p.StartInfo.Verb = "runas";
p.Start();
p.WaitForExit();
}
catch(Exception ex)
{
Console.WriteLine("[EXCEPTION] RunElevated: " + ex.Message);
}
}
#region Scripting
public static void ExecuteIPyScript(String command, String[] args, bool bVerbose)
{
String scriptfile = Path.Combine(GetCFORGEScriptPath(), command + ".py");
Console.WriteLine();
Console.WriteLine("[INFO] Executing: " + scriptfile);
Console.WriteLine();
if (!File.Exists(scriptfile))
{
Console.WriteLine();
Console.WriteLine("[ERROR] Cannot execute command: no such file or directory: " + scriptfile);
Console.WriteLine();
return;
}
//ScriptEngine engine = Python.CreateEngine();
ScriptEngine engine = IronPython.Hosting.Python.CreateEngine(new Dictionary { { "Debug", ScriptingRuntimeHelpers.True } });
Debug.Assert(engine.Runtime.Setup.DebugMode);
String strScriptingPath = GetCODESYSScriptingLibPath();
try
{
dynamic sys = Python.GetSysModule(engine);
sys.argv[0] = scriptfile;
foreach (string arg in args)
{
sys.argv.Add(arg);
}
sys.path.Add(GetCFORGEScriptPath());
sys.path.Add(strScriptingPath);
var source = engine.CreateScriptSourceFromFile(scriptfile);
source.Execute();
//Console.WriteLine("Script finished");
}
catch (IronPython.Runtime.Exceptions.SystemExitException ex)
{
Console.WriteLine();
Console.WriteLine("[INFO] command " + command + ".py exited: ");
ExceptionOperations eo = engine.GetService();
string error = "[INFO] " + eo.FormatException(ex);
Console.WriteLine(error);
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("[Exception] command " + command + ".py caused an exception: " );
ExceptionOperations eo = engine.GetService();
string error = eo.FormatException(ex);
Console.WriteLine(error);
}
}
public static void ShowUsageIPyScript(string command, bool v)
{
String scriptfile = Path.Combine(GetCFORGEScriptPath(), command + ".py");
if (!File.Exists(scriptfile))
{
Console.WriteLine("[ERROR] Cannot execute command: no such file or directory: " + scriptfile);
return;
}
ScriptRuntime runtime;
runtime = Python.CreateRuntime();
Python.GetEngine(runtime);
try
{
dynamic script = runtime.UseFile(scriptfile);
var help = script.cforge_usage();
foreach (var item in help)
{
String cmd = "--" + command + " " + item[0].ToString();
cmd = cmd.PadRight(32) + item[1];
Console.WriteLine(cmd);
}
}
catch
{
// we silently ignore errors in this script, as we only want to show the usage!
//Console.WriteLine(("--" + command).PadRight(32) + "");
}
}
#endregion
}
}