Пример #1
0
 /// <summary>
 /// Finds accessible object (AO) in the specified control of window w.
 /// Returns true if found. The <see cref="Result"/> property will be the found AO.
 /// </summary>
 /// <param name="w">Window that contains the control.</param>
 /// <param name="controls">Control properties. This functions searches in all matching controls.</param>
 /// <exception cref="Exception">Exceptions of <see cref="Find(AWnd)"/>.</exception>
 /// <remarks>
 /// Alternatively you can specify control class name or id in role. How this function is different: 1. Allows to specify more control properties. 2. Works better/faster when the control is of a different process or thread than the parent window; else slightly slower.
 /// </remarks>
 public bool Find(AWnd w, AWnd.ChildFinder controls)
 {
     w.ThrowIfInvalid();
     foreach (var c in controls.FindAll(w))
     {
         try {
             if (_FindOrWait(c, 0, false))
             {
                 controls.Result = c;
                 return(true);
             }
         }
         catch (AuException ex) when(!c.IsAlive)
         {
             ADebug.Print(ex.Message);
         }                                                                                        //don't throw AuWndException/AuException if the window or a control is destroyed while searching, but throw AuException if eg access denied
     }
     return(false);
 }
Пример #2
0
        Bitmap _GetImage(string file, IconGetFlags giFlags, Func <Bitmap> callback, Action <Bitmap, object> autoUpdate, object auParam, bool auDispose)
        {
            bool cached = true;

            lock (this) {
                Bitmap R = null;

                //is in memory cache?
                if (_table == null)
                {
                    _table = new Hashtable(StringComparer.OrdinalIgnoreCase);
                }
                else
                {
                    R = _table[file] as Bitmap;
                }

                if (R == null)
                {
                    //is in file cache?
                    try {
                        if (_x == null && AFile.ExistsAsFile(_cacheFile))
                        {
                            _x = AExtXml.LoadElem(_cacheFile);
                            if (_iconSize != _x.Attr("size", 0) || ADpi.BaseDPI != _x.Attr("dpi", 0))
                            {
                                _x = null;
                                ADebug.Print("info: cleared icon cache");
                            }

                            //FUTURE: Delete unused entries. Maybe try to auto-update changed icons.
                            //	Not very important, because there is ClearCache.
                        }
                        if (_x != null)
                        {
                            var x = _x.Elem("i", "name", file, true);
                            if (x != null)
                            {
                                using var ms = new MemoryStream(Convert.FromBase64String(x.Value), false);
                                R            = new Bitmap(ms);
                            }
                        }
                    }
                    catch (Exception ex) {
                        ADebug.Print(ex.Message);
                    }

                    if (R != null)
                    {
                        _table[file] = R;                                //add to memory cache
                    }
                    else if (_LoadImage(out R, file, giFlags, callback)) //get file icon
                    {
                        _AddImage(file, R, false);                       //add to file cache and memory cache
                        cached = false;
                    }
                }

                //auto-update
                if (cached && autoUpdate != null)
                {
                    var d = new _AUData()
                    {
                        cache       = this, oldImage = R, file = file, callback = callback,
                        autoUpdated = autoUpdate, auParam = auParam, giFlags = giFlags, canDispose = auDispose,
                    };
                    _AutoUpdateAdd(d);
                }

                return(R);
            }
        }
Пример #3
0
        /// <summary>
        /// Executes assembly in this thread.
        /// Handles exceptions.
        /// </summary>
        /// <param name="asmFile">Full path of assembly file.</param>
        /// <param name="args">To pass to Main.</param>
        /// <param name="pdbOffset">0 or offset of portable PDB in assembly file.</param>
        /// <param name="flags"></param>
        /// <param name="fullPathRefs">Paths of assemblies specified using full path.</param>
        public static void Run(string asmFile, string[] args, int pdbOffset, RAFlags flags = 0, string fullPathRefs = null)
        {
            ADebug.PrintIf(pdbOffset == 0, "pdbOffset 0");

            bool inEditorThread       = 0 != (flags & RAFlags.InEditorThread);
            bool findLoaded           = inEditorThread;
            _LoadedScriptAssembly lsa = default;
            Assembly asm = findLoaded ? lsa.Find(asmFile) : null;

            if (asm == null)
            {
#if true
                //var p1 = APerf.Create();
                var alc = System.Runtime.Loader.AssemblyLoadContext.Default;
                //SHOULDDO: try to unload. It seems AssemblyLoadContext supports it. Not tested. I guess it would create more problems than is useful.
                //p1.Next();
                using (var stream = AFile.WaitIfLocked(() => File.OpenRead(asmFile))) {
                    //p1.Next();
                    if (pdbOffset > 0)
                    {
                        var b = new byte[pdbOffset];
                        stream.Read(b, 0, b.Length);
                        using var msAsm = new MemoryStream(b);
                        b = new byte[stream.Length - pdbOffset];
                        stream.Read(b, 0, b.Length);
                        using var msDeb = new MemoryStream(b);
                        //p1.Next('f');
                        asm = alc.LoadFromStream(msAsm, msDeb);
                        //p1.Next();
                    }
                    else
                    {
                        asm = alc.LoadFromStream(stream);
                    }
                }
                //p1.NW();
                //APerf.Next('a');

                if (fullPathRefs != null)
                {
                    var fpr = fullPathRefs.SegSplit("|");
                    alc.Resolving += (System.Runtime.Loader.AssemblyLoadContext alc, AssemblyName an) => {
                        //AOutput.Write(an, an.Name, an.FullName);
                        foreach (var v in fpr)
                        {
                            var s1    = an.Name;
                            int iName = v.Length - s1.Length - 4;
                            if (iName <= 0 || v[iName - 1] != '\\' || !v.Eq(iName, s1, true))
                            {
                                continue;
                            }
                            if (!AFile.ExistsAsFile(v))
                            {
                                continue;
                            }
                            //try {
                            return(alc.LoadFromAssemblyPath(v));
                            //} catch(Exception ex) { ADebug.Print(ex.ToStringWithoutStack()); break; }
                        }
                        return(null);
                    };
                }

                //ADebug.PrintLoadedAssemblies(true, true);

                //AOutput.Write(asm);
#else
                byte[] bAsm, bPdb = null;
                using (var stream = AFile.WaitIfLocked(() => File.OpenRead(asmFile))) {
                    bAsm = new byte[pdbOffset > 0 ? pdbOffset : stream.Length];
                    stream.Read(bAsm, 0, bAsm.Length);
                    try {
                        if (pdbOffset > 0)
                        {
                            bPdb = new byte[stream.Length - pdbOffset];
                            stream.Read(bPdb, 0, bPdb.Length);
                        }
                        else
                        {
                            var s1 = Path.ChangeExtension(asmFile, "pdb");
                            if (AFile.ExistsAsFile(s1))
                            {
                                bPdb = File.ReadAllBytes(s1);
                            }
                        }
                    }
                    catch (Exception ex) { bPdb = null; ADebug.Print(ex); }                    //not very important
                }
                //APerf.Next('f');
                //APerf.First();
                asm = Assembly.Load(bAsm, bPdb);
#endif
                //APerf.Next('A');
                //APerf.NW(); //without AV 7 ms. With Windows Defender 10 ms, but first time 20-900 ms.
                if (findLoaded)
                {
                    lsa.Add(asmFile, asm);
                }

                //never mind: it's possible that we load a newer compiled assembly version of script than intended.
            }

            try {
                var entryPoint = asm.EntryPoint ?? throw new InvalidOperationException("assembly without entry point (function Main)");

                bool useArgs = entryPoint.GetParameters().Length != 0;
                if (useArgs)
                {
                    if (args == null)
                    {
                        args = Array.Empty <string>();
                    }
                }

                //APerf.Next('1');
                if (!inEditorThread)
                {
                    Util.Log_.Run.Write("Task started.");
                }

                //APerf.Next('2');
                if (useArgs)
                {
                    entryPoint.Invoke(null, new object[] { args });
                }
                else
                {
                    entryPoint.Invoke(null, null);
                }

                if (!inEditorThread)
                {
                    Util.Log_.Run.Write("Task ended.");
                }
            }
            catch (TargetInvocationException te) {
                var e = te.InnerException;

                if (!inEditorThread)
                {
                    Util.Log_.Run.Write($"Unhandled exception: {e.ToStringWithoutStack()}");
                }

                if (0 != (flags & RAFlags.DontHandleExceptions))
                {
                    throw e;
                }
                //AOutput.Write(e);
                AScript.OnHostHandledException(new UnhandledExceptionEventArgs(e, false));
            }

            //see also: TaskScheduler.UnobservedTaskException event.
            //	tested: the event works.
            //	tested: somehow does not terminate process even with <ThrowUnobservedTaskExceptions enabled="true"/>.
            //		Only when ADialog.Show called, the GC.Collect makes it to disappear but the process does not exit.
            //	note: the terminating behavior also can be set in registry or env var. It overrides <ThrowUnobservedTaskExceptions enabled="false"/>.
        }