Exemple #1
0
        /// <summary>
        /// Gets file icon as <b>Bitmap</b>.
        /// Returns null if the icon is not cached and failed to get it, eg file does not exist.
        /// </summary>
        /// <param name="file">Any file or folder.</param>
        /// <param name="useExt">
        /// Get file type icon, depending on filename extension. Use this to avoid getting separate image object for each file of same type.
        /// This is ignored if filename extension is ".ico" or ".exe" or starts with ".exe," or ".dll,".
        /// </param>
        /// <param name="giFlags">Flags for <see cref="AIcon.GetFileIconImage"/>.</param>
        /// <param name="autoUpdate">
        /// If not null, the cached image will be auto-updated when changed. Then will be called this function. It can update the image in UI.
        /// How it works: If this function finds cached image, it sets timer that after ~50 ms loads that icon/image from file again and compares with the cached image. If different, updates the cache. Does it once, not periodically.
        /// Use only in UI threads. Does not work if this thread does not retrieve/dispatch posted messages.
        /// </param>
        /// <param name="auParam">Something to pass to the <i>autoUpdate</i> callback function.</param>
        /// <remarks>
        /// If the icon is in the memory cache, gets it from there.
        /// Else if it is in the file cache, gets it from there and adds to the memory cache.
        /// Else gets from file (uses <see cref="AIcon.GetFileIconImage"/> and adds to the file cache and to the memory cache.
        /// </remarks>
        public Bitmap GetImage(string file, bool useExt, IconGetFlags giFlags = 0, Action <Bitmap, object> autoUpdate = null, object auParam = null)
        {
            if (useExt)
            {
                var ext = APath.GetExtension(file);
                if (ext.Length == 0)
                {
                    if (AFile.ExistsAsDirectory(file))
                    {
                        ext = file;
                    }
                    else
                    {
                        ext = ".no-ext";
                    }
                }
                else
                {
                    //ext = ext.Lower();
                    if (ext.Eqi(".ico") || ext.Eqi(".exe") || ext.Starts(".exe,", true) || ext.Starts(".dll,", true))
                    {
                        ext = file;
                    }
                }
                file = ext;
            }
            else if (APath.IsFullPathExpandEnvVar(ref file))
            {
                file = APath.Normalize_(file, noExpandEV: true);
            }

            return(_GetImage(file, giFlags, null, autoUpdate, auParam, true));
        }
Exemple #2
0
 /// <summary>
 /// Clears the memory cache and deletes the cache file.
 /// </summary>
 public void ClearCache()
 {
     lock (this) {
         _dirty = false;
         _x     = null;
         _table = null;
         AFile.Delete(_cacheFile);
     }
 }
Exemple #3
0
        /// <summary>
        /// Saves the Shortcut variable properties to the shortcut file.
        /// </summary>
        /// <exception cref="AuException">Failed to save .lnk file.</exception>
        /// <remarks>
        /// Creates parent folder if need.
        /// </remarks>
        public void Save()
        {
            if (_changedHotkey && !_isOpen && AFile.ExistsAsFile(_lnkPath))
            {
                _UnregisterHotkey(_lnkPath);
            }

            AFile.CreateDirectoryFor(_lnkPath);
            AuException.ThrowIfHresultNot0(_ipf.Save(_lnkPath, true), "*save");
        }
Exemple #4
0
        //This could be public, but then need to make IShellLink public. It is defined in a non-standard way. Never mind, it is not important.

        AShortcutFile(string lnkPath, uint mode)
        {
            _isl     = new Api.ShellLink() as Api.IShellLink;
            _ipf     = _isl as Api.IPersistFile;
            _lnkPath = lnkPath;
            if (mode != Api.STGM_WRITE && (mode == Api.STGM_READ || AFile.ExistsAsFile(_lnkPath)))
            {
                AuException.ThrowIfHresultNot0(_ipf.Load(_lnkPath, mode), "*open");
                _isOpen = true;
            }
        }
Exemple #5
0
 /// <summary>
 /// Saves to the cache file now, if need.
 /// Automatically called on process exit.
 /// </summary>
 public void SaveCacheFileNow()
 {
     if (_dirty)
     {
         lock (this) {
             if (_dirty)
             {
                 _dirty = false;
                 AFile.WaitIfLocked(() => _x.Save(_cacheFile));
             }
         }
     }
 }
Exemple #6
0
 /// <summary>
 /// Saves XML to a file in a safer way.
 /// Uses <see cref="XDocument.Save(string)"/> and <see cref="AFile.Save"/>
 /// </summary>
 /// <exception cref="Exception">Exceptions of <see cref="XDocument.Save"/> and <see cref="AFile.Save"/>.</exception>
 public static void SaveDoc(this XDocument t, string file, bool backup = false, SaveOptions?options = default)
 {
     AFile.Save(file, temp => {
         if (options.HasValue)
         {
             t.Save(temp, options.GetValueOrDefault());
         }
         else
         {
             t.Save(temp);
         }
     }, backup);
 }
Exemple #7
0
 static void _SetOnce(ref string propVar, string value, bool create, [CallerMemberName] string propName = null)
 {
     lock (_lock) {
         if (propVar != null)
         {
             throw new InvalidOperationException("AFolders." + propName + " is already set.");
         }
         propVar = value;
         if (create)
         {
             AFile.CreateDirectory(value);
         }
     }
 }
Exemple #8
0
        //note: don't use Application.ProductName etc. It loads Forms, throws if dynamic assembly, etc.

        #region set auto/once

        static string _SetAuto(ref string propVar, string value, bool create)
        {
            lock (_lock) {
                if (propVar == null)
                {
                    propVar = value;
                    if (create)
                    {
                        AFile.CreateDirectory(value);
                    }
                }
            }
            return(propVar);
        }
Exemple #9
0
        /// <summary>
        /// Gets path with unique filename for a new file or directory.
        /// If the specified path is of an existing file or directory, returns path where the filename part is modified like "file 2.txt", "file 3.txt" etc. Else returns unchanged path.
        /// </summary>
        /// <param name="path">Suggested full path.</param>
        /// <param name="isDirectory">The path is for a directory. The number is always appended at the very end, not before .extension.</param>
        public static string MakeUnique(string path, bool isDirectory)
        {
            if (!AFile.ExistsAsAny(path))
            {
                return(path);
            }
            string ext = isDirectory ? null : GetExtension(path, out path);

            for (int i = 2; ; i++)
            {
                var s = path + " " + i + ext;
                if (!AFile.ExistsAsAny(s))
                {
                    return(s);
                }
            }
        }
Exemple #10
0
 public Assembly Find(string asmFile)
 {
     _d ??= new Dictionary <string, _Asm>(StringComparer.OrdinalIgnoreCase);
     if (!AFile.GetProperties(asmFile, out var p, FAFlags.UseRawPath))
     {
         return(null);
     }
     _fileTime = p.LastWriteTimeUtc;
     if (_d.TryGetValue(asmFile, out var x))
     {
         if (x.time == _fileTime)
         {
             return(x.asm);
         }
         _d.Remove(asmFile);
     }
     return(null);
 }
Exemple #11
0
        //Used by Run and RunConsole.
        static string _NormalizeFile(bool runConsole, string file, out bool isFullPath, out bool isShellPath)
        {
            isShellPath = isFullPath = false;
            file        = APath.ExpandEnvVar(file);
            if (file.NE())
            {
                throw new ArgumentException();
            }
            if (runConsole || !(isShellPath = APath.IsShellPath_(file)))
            {
                if (isFullPath = APath.IsFullPath(file))
                {
                    var fl = runConsole ? PNFlags.DontExpandDosPath : PNFlags.DontExpandDosPath | PNFlags.DontPrefixLongPath;
                    file = APath.Normalize_(file, fl, true);

                    //ShellExecuteEx supports long path prefix for exe but not for documents.
                    //Process.Run supports long path prefix, except when the exe is .NET.
                    if (!runConsole)
                    {
                        file = APath.UnprefixLongPath(file);
                    }

                    if (ADisableFsRedirection.IsSystem64PathIn32BitProcess(file) && !AFile.ExistsAsAny(file))
                    {
                        file = ADisableFsRedirection.GetNonRedirectedSystemPath(file);
                    }
                }
                else if (!APath.IsUrl(file))
                {
                    //ShellExecuteEx searches everywhere except in app folder.
                    //Process.Run prefers current directory.
                    var s2 = AFile.SearchPath(file);
                    if (s2 != null)
                    {
                        file       = s2;
                        isFullPath = true;
                    }
                }
            }
            return(file);
        }
Exemple #12
0
        /// <summary>
        /// Opens or creates a database file.
        /// </summary>
        /// <param name="file">
        /// Database file. Can be:
        /// - Full path. Supports environment variables etc, see <see cref="APath.ExpandEnvVar"/>
        /// - ":memory:" - create a private, temporary in-memory database.
        /// - "" - create a private, temporary on-disk database.
        /// - Starts with "file:" - see sqlite3_open_v2 documentation in SQLite website.
        /// </param>
        /// <param name="flags">sqlite3_open_v2 flags, documanted in SQLite website. Default: read-write, create file if does not exist (and parent directory).</param>
        /// <param name="sql">
        /// SQL to execute. For example, one or more ;-separated PRAGMA statements to configure the database connection. Or even "CREATE TABLE IF NOT EXISTS ...".
        /// This function also always executes "PRAGMA foreign_keys=ON;PRAGMA secure_delete=ON;".
        /// </param>
        /// <exception cref="ArgumentException">Not full path.</exception>
        /// <exception cref="SLException">Failed to open database or execute sql.</exception>
        /// <remarks>
        /// Calls sqlite3_open_v2.
        /// <note>If a variable of this class is used by multiple threads, use <c>lock(variable) {  }</c> where need.</note>
        /// </remarks>
        public ASqlite(string file, SLFlags flags = SLFlags.ReadWriteCreate, string sql = null)
        {
            bool isSpec = file != null && (file.Length == 0 || file == ":memory:" || file.Starts("file:"));

            if (!isSpec)
            {
                file = APath.Normalize(file);
                if (flags.Has(SLFlags.SQLITE_OPEN_CREATE) && !AFile.ExistsAsFile(file, true))
                {
                    AFile.CreateDirectoryFor(file);
                }
            }
            var r = SLApi.sqlite3_open_v2(AConvert.ToUtf8(file), ref _db, flags, null);

            if (r != 0)
            {
                Dispose();
                throw new SLException(r, "sqlite3_open " + file);
            }
            Execute("PRAGMA foreign_keys=ON;PRAGMA secure_delete=ON;" + sql);
        }
Exemple #13
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);
            }
        }
Exemple #14
0
 /// <summary>
 /// Deletes the settings file of the toolbar, if exists. It resets toolbar settings.
 /// The toolbar should not be open when calling this function.
 /// </summary>
 /// <param name="toolbarName">Toolbar name.</param>
 /// <exception cref="Exception">Exceptions of <see cref="AFile.Delete(string, bool)"/>.</exception>
 public static void DeleteSettings(string toolbarName)
 {
     AFile.Delete(GetSettingsFilePath(toolbarName));
 }
Exemple #15
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"/>.
        }