public static void PushDepthInfo(EngineState s, int targetDepth) { while (s.PeekDepth < targetDepth) { EngineLocalState ls = s.PeekLocalState(); s.PushLocalState(ls.IsMacro, ls.RefScriptId); } }
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