Ejemplo n.º 1
0
 public static void PushDepthInfo(EngineState s, int targetDepth)
 {
     while (s.PeekDepth < targetDepth)
     {
         EngineLocalState ls = s.PeekLocalState();
         s.PushLocalState(ls.IsMacro, ls.RefScriptId);
     }
 }
Ejemplo n.º 2
0
        public static List <LogInfo> SystemCmd(EngineState s, CodeCommand cmd)
        {
            List <LogInfo>  logs = new List <LogInfo>(1);
            CodeInfo_System info = cmd.Info.Cast <CodeInfo_System>();

            SystemType type = info.Type;

            switch (type)
            {
            case SystemType.Cursor:
            {
                SystemInfo_Cursor subInfo = info.SubInfo.Cast <SystemInfo_Cursor>();

                string iconStr = StringEscaper.Preprocess(s, subInfo.State);

                if (iconStr.Equals("WAIT", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher?.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
                        });
                    s.CursorWait = true;
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Wait]"));
                }
                else if (iconStr.Equals("NORMAL", StringComparison.OrdinalIgnoreCase))
                {
                    Application.Current?.Dispatcher?.Invoke(() =>
                        {
                            System.Windows.Input.Mouse.OverrideCursor = null;
                        });
                    s.CursorWait = false;
                    logs.Add(new LogInfo(LogState.Success, "Mouse cursor icon set to [Normal]"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Error, $"[{iconStr}] is not a valid mouse cursor icon"));
                }
            }
            break;

            case SystemType.ErrorOff:
            {
                SystemInfo_ErrorOff subInfo = info.SubInfo.Cast <SystemInfo_ErrorOff>();

                string linesStr = StringEscaper.Preprocess(s, subInfo.Lines);
                if (!NumberHelper.ParseInt32(linesStr, out int lines))
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{linesStr}] is not a positive integer"));
                }
                if (lines <= 0)
                {
                    return(LogInfo.LogErrorMessage(logs, $"[{linesStr}] is not a positive integer"));
                }

                if (s.ErrorOff == null)
                {
                    // Enable s.ErrorOff
                    // Write to s.ErrorOffWaitingRegister instead of s.ErrorOff, to prevent muting error of [System,ErrorOff] itself.
                    EngineLocalState ls = s.PeekLocalState();
                    if (s.ErrorOffDepthMinusOne)
                    {
                        ls = ls.UpdateDepth(ls.Depth - 1);
                    }

                    ErrorOffState newState = new ErrorOffState
                    {
                        LocalState   = ls,
                        StartLineIdx = cmd.LineIdx,
                        LineCount    = lines,
                    };

                    s.ErrorOffWaitingRegister = newState;
                    s.ErrorOffDepthMinusOne   = false;
                    logs.Add(new LogInfo(LogState.Success, $"Error and warning logs will be muted for [{lines}] lines"));
                }
                else
                {         // If s.ErrorOff is already enabled, do nothing. Ex) Nested ErrorOff
                    logs.Add(new LogInfo(LogState.Ignore, "ErrorOff is already enabled"));
                }
            }
            break;

            case SystemType.GetEnv:
            {
                SystemInfo_GetEnv subInfo = info.SubInfo.Cast <SystemInfo_GetEnv>();

                string envVarName  = StringEscaper.Preprocess(s, subInfo.EnvVar);
                string envVarValue = Environment.GetEnvironmentVariable(envVarName);
                if (envVarValue == null)         // Failure
                {
                    logs.Add(new LogInfo(LogState.Ignore, $"Cannot get environment variable [%{envVarName}%]'s value"));
                    envVarValue = string.Empty;
                }

                logs.Add(new LogInfo(LogState.Success, $"Environment variable [{envVarName}]'s value is [{envVarValue}]"));
                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, envVarValue);
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.GetFreeDrive:
            {
                SystemInfo_GetFreeDrive subInfo = info.SubInfo.Cast <SystemInfo_GetFreeDrive>();

                DriveInfo[] drives = DriveInfo.GetDrives();
                // ReSharper disable once StringLiteralTypo
                const string letters        = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                char         lastFreeLetter = letters.Except(drives.Select(d => d.Name[0])).LastOrDefault();

                if (lastFreeLetter != '\0')         // Success
                {
                    logs.Add(new LogInfo(LogState.Success, $"Last free drive letter is [{lastFreeLetter}]"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, lastFreeLetter.ToString(CultureInfo.InvariantCulture));
                    logs.AddRange(varLogs);
                }
                else         // No Free Drives
                {
                    // TODO: Is it correct WB082 behavior?
                    logs.Add(new LogInfo(LogState.Ignore, "No free drive letter"));
                    List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, string.Empty);
                    logs.AddRange(varLogs);
                }
            }
            break;

            case SystemType.GetFreeSpace:
            {
                SystemInfo_GetFreeSpace subInfo = info.SubInfo.Cast <SystemInfo_GetFreeSpace>();

                string path = StringEscaper.Preprocess(s, subInfo.Path);

                FileInfo f = new FileInfo(path);
                if (f.Directory == null)
                {
                    return(LogInfo.LogErrorMessage(logs, $"Unable to get drive information for [{path}]"));
                }
                DriveInfo drive             = new DriveInfo(f.Directory.Root.FullName);
                long      freeSpaceMegaByte = drive.TotalFreeSpace / (1024 * 1024);    // B to MB

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, freeSpaceMegaByte.ToString(CultureInfo.InvariantCulture));
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.IsAdmin:
            {
                SystemInfo_IsAdmin subInfo = info.SubInfo.Cast <SystemInfo_IsAdmin>();

                bool isAdmin;
                using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
                {
                    WindowsPrincipal principal = new WindowsPrincipal(identity);
                    isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
                }

                if (isAdmin)
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is running as Administrator"));
                }
                else
                {
                    logs.Add(new LogInfo(LogState.Success, "PEBakery is not running as Administrator"));
                }

                List <LogInfo> varLogs = Variables.SetVariable(s, subInfo.DestVar, isAdmin.ToString(CultureInfo.InvariantCulture));
                logs.AddRange(varLogs);
            }
            break;

            case SystemType.OnBuildExit:
            {
                SystemInfo_OnBuildExit subInfo = info.SubInfo.Cast <SystemInfo_OnBuildExit>();

                s.OnBuildExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnBuildExit callback registered"));
            }
            break;

            case SystemType.OnScriptExit:
            {
                SystemInfo_OnScriptExit subInfo = info.SubInfo.Cast <SystemInfo_OnScriptExit>();

                s.OnScriptExit = subInfo.Cmd;

                logs.Add(new LogInfo(LogState.Success, "OnScriptExit callback registered"));
            }
            break;

            case SystemType.RefreshInterface:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo), "Invalid CodeInfo");

                s.MainViewModel.StartRefreshScript().Wait();

                logs.Add(new LogInfo(LogState.Success, $"Re-rendered script [{cmd.Section.Script.Title}]"));
            }
            break;

            case SystemType.RescanScripts:
            case SystemType.RefreshAllScripts:
            {
                Debug.Assert(info.SubInfo.GetType() == typeof(SystemInfo), "Invalid CodeInfo");

                // Refresh Project
                s.MainViewModel.StartLoadingProjects(true, true).Wait();

                logs.Add(new LogInfo(LogState.Success, $"Reload project [{cmd.Section.Script.Project.ProjectName}]"));
            }
            break;

            case SystemType.LoadNewScript:
            {
                SystemInfo_LoadNewScript subInfo = info.SubInfo.Cast <SystemInfo_LoadNewScript>();

                string       srcFilePath  = StringEscaper.Preprocess(s, subInfo.SrcFilePath);
                string       destTreeDir  = StringEscaper.Preprocess(s, subInfo.DestTreeDir);
                SearchOption searchOption = SearchOption.AllDirectories;
                if (subInfo.NoRecFlag)
                {
                    searchOption = SearchOption.TopDirectoryOnly;
                }

                Debug.Assert(srcFilePath != null, "Internal Logic Error at CommandSystem.LoadNewScript");

                // Check wildcard
                string wildcard         = Path.GetFileName(srcFilePath);
                bool   containsWildcard = wildcard.IndexOfAny(new[] { '*', '?' }) != -1;

                string[] files;
                if (containsWildcard)
                {         // With wildcard
                    files = FileHelper.GetFilesEx(FileHelper.GetDirNameEx(srcFilePath), wildcard, searchOption);
                    if (files.Length == 0)
                    {
                        return(LogInfo.LogErrorMessage(logs, $"Script [{srcFilePath}] does not exist"));
                    }
                }
                else
                {         // No wildcard
                    if (!File.Exists(srcFilePath))
                    {
                        return(LogInfo.LogErrorMessage(logs, $"Script [{srcFilePath}] does not exist"));
                    }

                    files = new string[] { srcFilePath };
                }
                List <Script> newScripts = new List <Script>(files.Length);

                string srcDirPath = Path.GetDirectoryName(srcFilePath);
                Debug.Assert(srcDirPath != null, $"{nameof(srcDirPath)} is null (CommandSystem.LoadNewScript)");

                (string realPath, string treePath)[] fileTuples = files