/// <summary> /// Returns true if the string is full path, like <c>@"C:\a\b.txt"</c> or <c>@"C:"</c> or <c>@"\\server\share\..."</c>: /// </summary> /// <param name="path">Any string. Can be null.</param> /// <remarks> /// Returns true if <i>path</i> matches one of these wildcard patterns: /// - <c>@"?:\*"</c> - local path, like <c>@"C:\a\b.txt"</c>. Here ? is A-Z, a-z. /// - <c>@"?:"</c> - drive name, like <c>@"C:"</c>. Here ? is A-Z, a-z. /// - <c>@"\\*"</c> - network path, like <c>@"\\server\share\..."</c>. Or has prefix <c>@"\\?\"</c>. /// /// Supports <c>'/'</c> characters too. /// /// Supports only file-system paths. Returns false if path is URL (<see cref="IsUrl"/>) or starts with <c>"::"</c>. /// /// If path starts with <c>"%environmentVariable%"</c>, shows warning and returns false. You should at first expand environment variables with <see cref="ExpandEnvVar"/> or instead use <see cref="IsFullPathExpandEnvVar"/>. /// </remarks> public static bool IsFullPath(string path) { var s = path; int len = s.Lenn(); if (len >= 2) { if (s[1] == ':' && AChar.IsAsciiAlpha(s[0])) { return(len == 2 || IsSepChar_(s[2])); //info: returns false if eg "c:abc" which means "abc" in current directory of drive "c:" } switch (s[0]) { case '\\': case '/': return(IsSepChar_(s[1])); case '%': #if true if (!ExpandEnvVar(s).Starts('%')) { AWarning.Write("Path starts with %environmentVariable%. Use APath.IsFullPathExpandEnvVar instead."); } #else s = ExpandEnvVar(s); //quite fast. 70% slower than just EnvVarExists_, but reliable. return(!s.Starts('%') && IsFullPath(s)); #endif break; } } return(false); }
[MethodImpl(MethodImplOptions.NoInlining)] //uses stack public static RResult TryRun(string s, string args = null, RFlags flags = 0, ROptions curDirEtc = null) { try { return(Run(s, args, flags, curDirEtc)); } catch (AuException e) { AWarning.Write(e.Message, 1); return(null); } }
/// <summary> /// Unregisters the hotkey. /// </summary> /// <remarks> /// Called implicitly when disposing this variable. /// Must be called from the same thread as when registering, and the window must be still alive. /// If fails, calls <see cref="AWarning.Write"/>. /// </remarks> public void Unregister() { if (_id != 0) { if (!Api.UnregisterHotKey(_w, _id)) { var es = ALastError.Message; AWarning.Write($"Failed to unregister hotkey, id={_id.ToString()}. {es}"); return; } _id = 0; _w = default; //Hotkey = default; } }
/// protected virtual void Dispose(bool disposing) { if (_hproc.Is0) { return; } if (Mem != default) { var mem = Mem; Mem = default; if (!_dontFree) { if (!Api.VirtualFreeEx(_HprocHR, mem)) { AWarning.Write("Failed to free process memory. " + ALastError.Message); } } } _hproc.Dispose(); }
/// <summary> /// Calls <see cref="GetFileId"/> for two paths and returns true if both calls succeed and the ids are equal. /// Paths should be normalized. They are passed to API unmodified. /// </summary> /// <param name="path1"></param> /// <param name="path2"></param> internal static bool IsSameFile_(string path1, string path2) { //try to optimize. No, unreliable. //int i1 = path1.FindLastAny("\\/~"), i2 = path2.FindLastAny("\\/~"); //if(i1 >= 0 && i2 >= 0 && path1[i1] != '~' && path2[i2] != '~') { // i1++; i2++; // if() //} var ok1 = GetFileId(path1, out var fid1); var ok2 = GetFileId(path2, out var fid2); if (ok1 && ok2) { return(fid1 == fid2); } AWarning.Write("GetFileId failed"); //CONSIDER: throw return(false); }
/// <param name="name"> /// Toolbar name. Must be valid filename. /// Used for the toolbar's settings file name. Also it is the initial <b>Name</b> and <b>Text</b> of <see cref="Control"/>, and used with <see cref="Find"/>. /// </param> /// <param name="f"><see cref="CallerFilePathAttribute"/></param> /// <param name="l"><see cref="CallerLineNumberAttribute"/></param> /// <exception cref="ArgumentException">Empty or invalid name.</exception> /// <remarks> /// Reads the settings file if exists, ie if settings changed in the past. See <see cref="GetSettingsFilePath"/>. If fails, writes warning to the output and uses default settings. /// /// Creates <see cref="Control"/> object. Does not create its window handle; will do it in <see cref="Show"/>. /// /// Sets properties: /// - <see cref="MTBase.ItemThread"/> = <see cref="MTThread.StaThread"/>. /// - <see cref="MTBase.ExtractIconPathFromCode"/> = true. /// - <see cref="MTBase.DefaultIcon"/> = <see cref="MTBase.CommonIcon"/>. /// - <see cref="MTBase.DefaultSubmenuIcon"/> = <see cref="MTBase.CommonSubmenuIcon"/>. /// </remarks> public AToolbar(string name, [CallerFilePath] string f = null, [CallerLineNumber] int l = 0) : base(f, l) { int tid = Thread.CurrentThread.ManagedThreadId; if (s_treadId == 0) { s_treadId = tid; } else if (tid != s_treadId) { AWarning.Write("All toolbars should be in single thread. Multiple threads use more CPU. If using triggers, insert this code before adding toolbar triggers: <code>Triggers.Options.RunActionInMainThread();</code>"); } //rejected: [CallerMemberName] string name = null. Problem: if local func or lambda, it is parent method's name. And can be eg ".ctor" if directly in script. _name = name; _sett = _Settings.Load(GetSettingsFilePath(name)); _c = new _ToolStrip(this) { Name = _name, Text = _name, Size = _sett.size, }; _anchor = _sett.anchor; _xy = _sett.location; Border = _sett.border; //default Sizable2 ExtractIconPathFromCode = true; DefaultIcon = CommonIcon; DefaultSubmenuIcon = CommonSubmenuIcon; ItemThread = MTThread.StaThread; _constructed = true; }
/// <summary> /// Returns index of matching element or -1. /// Returns -1 if using getAll. /// </summary> /// <param name="wParent">Parent window. Can be default(AWnd) if inList is true and no DirectChild flag and not using winforms name.</param> /// <param name="a">List of AWnd. Does not dispose it.</param> /// <param name="getAll">If not null, calls it for all matching and returns -1.</param> int _FindInList(AWnd wParent, _WndList a, Action <AWnd> getAll = null) { Result = default; if (a.Type == _WndList.ListType.None) { return(-1); } bool inList = a.Type != _WndList.ListType.ArrayBuilder; int skipCount = _skipCount; try { //will need to dispose something for (int index = 0; a.Next(out AWnd w); index++) { if (w.Is0) { continue; } if (inList) //else the enum function did this { if (!_flags.Has(WCFlags.HiddenToo)) { if (!w.IsVisibleIn_(wParent)) { continue; } } if (_flags.Has(WCFlags.DirectChild) && !wParent.Is0) { if (w.ParentGWL_ != wParent) { continue; } } } if (_nameIs == _NameIs.id) { if (w.ControlId != _id) { continue; } } if (_className != null) { if (!_className.Match(w.ClassName)) { continue; } } if (_name != null) { string s; switch (_nameIs) { case _NameIs.text: s = w.ControlText; break; //case _NameIs.label: // s = w.NameLabel; // break; case _NameIs.accName: s = w.NameAcc; break; case _NameIs.wfName: if (_wfControls == null) { try { _wfControls = new AWinFormsControlNames(wParent.Is0 ? w : wParent); } catch (AuWndException) { //invalid parent window return(-1); } catch (AuException e) { //probably process of higher UAC integrity level AWarning.Write($"Failed to get .NET control names. {e.Message}"); return(-1); } } s = _wfControls.GetControlName(w); break; default: Debug.Assert(_nameIs == _NameIs.name); s = w.Name; break; } if (!_name.Match(s)) { continue; } } if (_also != null && !_also(w)) { continue; } if (getAll != null) { getAll(w); continue; } if (skipCount-- > 0) { continue; } Result = w; return(index); } } finally { if (_wfControls != null) { _wfControls.Dispose(); _wfControls = null; } } return(-1); }