Visual Indicators

Visual Indicators adds custom columns and user commands

It currently includes five columns:

V1

  • πŸ”— Alias
  • πŸ’› Favorite
  • ✨ Smart Favorite
  • πŸ›£οΈ Folder is in effective PATH

V2

Mark of the web (MOTW)

Default-on combo markers:

  • πŸ§ͺ Internet/Restricted MOTW + macro-capable / legacy active Office file
  • ☣️ Internet/Restricted MOTW + directly executable or scriptable file
  • πŸͺ€ Internet/Restricted MOTW + indirect launcher (.lnk, .url)
  • 🧳 Internet/Restricted MOTW + archive/container

Optional standalone indicators:

  • 🌐 MOTW Internet (ZoneId=3)
  • β›” MOTW Restricted (ZoneId=4)
  • β“‚ Macro-capable / legacy active Office file

V3

`Checks Windows Authenticode trust status using a Python helper.

Default indicators:

  • βœ… Valid trusted signature
  • βšͺ Unsigned
  • βŒ› Signed but expired
  • 🚫 Revoked
  • ⚠️ Untrusted / chain-invalid
  • β›” Invalid / tampered / otherwise bad
  • ❓ Signature-check error
  • 🧩 Placeholder, if enabled

V3Publisher

V3Publisher is a text column that shows the extracted publisher name for signed files when available.

V4 Sandbox


image

If you use Sandboxie and have pointed to 'sandboxie.ini' in the script configuration menu, this column will predict with reasonable accuracy which sandbox the file/program will be launched in.


Current commands

Alias / Favorite / PATH

  • Alias.AddSelected β€” Add alias for selected items
  • Alias.RemoveSelected β€” Remove aliases pointing to selected items
  • Favorite.AddSelected β€” Add selected items as favorites
  • Favorite.RemoveSelected β€” Remove favorites pointing to selected items
  • Path.AddTo β€” Add selected folders to PATH
  • Path.Remove β€” Remove selected folders from PATH
  • Alias.Debug β€” Show alias and PATH debug info for the current selection

MOTW / V2

  • MOTW.RefreshVisible β€” Refresh MOTW state for visible files in the current tab
  • MOTW.ClearCache β€” Clear cached MOTW state
  • MOTW.AddSelected β€” Add MOTW to selected file(s) by writing Zone.Identifier
  • MOTW.RemoveSelected β€” Remove MOTW from selected file(s) by deleting Zone.Identifier

V3

  • V3.RefreshVisible β€” Refresh V3 signature status for visible files in the current tab
  • V3.ClearCache β€” Clear cached V3 signature state

Helpers

Prompts to create a single helper script in place. Code provided below for reference.

#!/usr/bin/env python3
"""Visual Indicators helper v1.1.0.
Usage: python visual_indicators_helper_v1.1.0.py --mode motw INPUT OUTPUT
       python visual_indicators_helper_v1.1.0.py --mode signature INPUT OUTPUT
One standalone file; uses Python's standard library. Signature mode requires Windows.
"""
from __future__ import annotations

import time
_SCRIPT_START = time.perf_counter()
import json
import os
import re
import stat
import sys

VERSION = "1.1.0"
LOG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "motw_check.log")
ZONE = re.compile(r"(?im)^\s*ZoneId\s*=\s*(\d+)\s*$")
CLOUD_FLAGS = (getattr(stat, "FILE_ATTRIBUTE_OFFLINE", 0x1000)
               | getattr(stat, "FILE_ATTRIBUTE_RECALL_ON_OPEN", 0x40000)
               | getattr(stat, "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS", 0x400000))


def decode_text(raw: bytes) -> str:
    if raw.startswith((b"\xff\xfe", b"\xfe\xff")):
        return raw.decode("utf-16")
    if b"\x00" in raw:
        encoding = "utf-16-be" if raw.startswith(b"\x00") else "utf-16-le"
        return raw.decode(encoding)
    try:
        return raw.decode("utf-8-sig")
    except UnicodeDecodeError:
        return raw.decode("cp1252", errors="replace")


def probe_motw(path: str) -> tuple[str, str]:
    try:
        info = os.stat(path)
        if stat.S_ISDIR(info.st_mode):
            return "0", ""
        if getattr(info, "st_file_attributes", 0) & CLOUD_FLAGS:
            return "?", ""  # Do not recall cloud-only files.
        try:
            with open(path + ":Zone.Identifier", "rb") as stream:
                raw = stream.read(65536)
        except FileNotFoundError:
            return "0", ""
        match = ZONE.search(decode_text(raw))
        return "1", match.group(1) if match else ""
    except (OSError, ValueError, UnicodeError):
        return "?", ""


def run_motw(args: list[str] | None = None) -> int:
    args = sys.argv[1:] if args is None else args
    metrics = {"version": VERSION, "initialisation_ms": round((time.perf_counter() - _SCRIPT_START) * 1000, 3)}
    phase = "arguments"
    try:
        if len(args) != 2:
            raise ValueError("Expected INPUT_LIST OUTPUT_FILE")
        input_path, output_path = args
        phase = "input"
        started = time.perf_counter()
        with open(input_path, "rb") as source:
            paths = [p for p in decode_text(source.read()).splitlines() if p.strip()]
        if any("|" in p or "\x00" in p for p in paths):
            raise ValueError("Input path contains an unsupported delimiter")
        metrics["input_ms"] = round((time.perf_counter() - started) * 1000, 3)
        phase = "probing"
        rows = []
        counts = {"present": 0, "absent": 0, "unknown": 0}
        longest = 0.0
        started = time.perf_counter()
        for path in paths:
            probe_started = time.perf_counter()
            state, zone = probe_motw(path)
            longest = max(longest, (time.perf_counter() - probe_started) * 1000)
            counts[{"1": "present", "0": "absent", "?": "unknown"}[state]] += 1
            rows.append("|".join((path, state, zone)))
        metrics.update(counts)
        metrics["files"] = len(paths)
        metrics["probe_ms"] = round((time.perf_counter() - started) * 1000, 3)
        metrics["slowest_probe_ms"] = round(longest, 3)
        phase = "output"
        started = time.perf_counter()
        with open(output_path, "w", encoding="utf-16", newline="\n") as target:
            target.write("".join(row + "\n" for row in rows))
        metrics["output_ms"] = round((time.perf_counter() - started) * 1000, 3)
        metrics["status"] = "ok"
        return 0
    except Exception as error:
        metrics.update(status="error", phase=phase, error=str(error))
        return 1
    finally:
        metrics["script_ms_before_log"] = round((time.perf_counter() - _SCRIPT_START) * 1000, 3)
        metrics["timestamp"] = time.strftime("%Y-%m-%d %H:%M:%S")
        # Excludes interpreter startup before this module and this final log write.
        try:
            with open(LOG_PATH, "a", encoding="utf-8") as target:
                target.write(json.dumps(metrics, ensure_ascii=True) + "\n")
        except OSError:
            pass




def run_signature(arguments: list[str]) -> int:
    # Initialise Windows signature libraries only for signature requests.
    import ctypes
    from ctypes import wintypes
    import datetime as dt
    import os
    import sys
    import traceback

    LOG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "signature_check.log")
    DIRECT_HUMAN_OUTPUT = os.path.join(os.path.dirname(LOG_PATH), "signature_test_output.txt")
    DIRECT_BATCHLIKE_OUTPUT = os.path.join(os.path.dirname(LOG_PATH), "signature_check_output.txt")
    VERBOSE_LOG = False

    _LOG_BUFFER: list[str] = []


    def _append_log(msg: str) -> None:
        ts = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
        _LOG_BUFFER.append(f"[{ts}] {msg}")


    def log(msg: str) -> None:
        _append_log(msg)


    def log_verbose(msg: str) -> None:
        if VERBOSE_LOG:
            _append_log(msg)


    def log_exception(prefix: str) -> None:
        try:
            _append_log(prefix)
            _append_log(traceback.format_exc().rstrip())
        except Exception:
            pass


    def flush_logs() -> None:
        if not _LOG_BUFFER:
            return
        try:
            parent = os.path.dirname(LOG_PATH)
            if parent:
                os.makedirs(parent, exist_ok=True)
            with open(LOG_PATH, "a", encoding="utf-8", newline="\n") as f:
                f.write("\n".join(_LOG_BUFFER))
                f.write("\n")
        except Exception:
            pass


    def ensure_parent_dir(path: str) -> None:
        parent = os.path.dirname(path)
        if parent:
            os.makedirs(parent, exist_ok=True)


    def sanitize_field(text: str) -> str:
        return (text or "").replace("\r", " ").replace("\n", " ").replace("|", "/").strip()


    def safe_get_full_path(path: str) -> str:
        try:
            return os.path.abspath(path)
        except Exception as ex:
            log(f"safe_get_full_path failed for {path!r}: {ex!r}")
            return path


    def decode_text_best_effort(raw: bytes) -> str:
        for encoding in ("utf-8-sig", "utf-16", "utf-16-le", "utf-16-be", "cp1252", "latin-1"):
            try:
                return raw.decode(encoding)
            except UnicodeDecodeError:
                continue
        return raw.decode("latin-1", errors="replace")


    def read_input_paths(input_file: str) -> list[str]:
        with open(input_file, "rb") as f:
            raw = f.read()

        text = decode_text_best_effort(raw)
        paths: list[str] = []
        seen: set[str] = set()

        for raw_line in text.splitlines():
            line = raw_line.rstrip("\r\n")
            if not line.strip():
                continue
            norm = os.path.normcase(safe_get_full_path(line))
            if norm in seen:
                log_verbose(f"Skipped duplicate path: {line}")
                continue
            seen.add(norm)
            paths.append(line)
            log_verbose(f"Queued path: {line}")

        return paths


    def write_text_file(path: str, lines: list[str], encoding: str = "utf-16") -> None:
        ensure_parent_dir(path)
        with open(path, "w", encoding=encoding, newline="\n") as f:
            for line in lines:
                f.write(line + "\n")


    def is_list_file(path: str) -> bool:
        ext = os.path.splitext(path)[1].lower()
        return ext in {".txt", ".lst", ".csv"}


    # ---- WinVerifyTrust via ctypes ----

    WTD_UI_NONE = 2
    WTD_REVOKE_NONE = 0
    WTD_CHOICE_FILE = 1
    WTD_STATEACTION_VERIFY = 1
    WTD_STATEACTION_CLOSE = 2
    WTD_REVOCATION_CHECK_NONE = 0x00000010
    WTD_CACHE_ONLY_URL_RETRIEVAL = 0x00000004

    # HRESULT / WinVerifyTrust values
    TRUST_E_NOSIGNATURE = ctypes.c_long(0x800B0100).value
    TRUST_E_SUBJECT_FORM_UNKNOWN = ctypes.c_long(0x800B0003).value
    TRUST_E_PROVIDER_UNKNOWN = ctypes.c_long(0x800B0001).value
    CERT_E_EXPIRED = ctypes.c_long(0x800B0101).value
    CERT_E_UNTRUSTEDROOT = ctypes.c_long(0x800B0109).value
    CERT_E_CHAINING = ctypes.c_long(0x800B010A).value
    CERT_E_REVOKED = ctypes.c_long(0x800B010C).value
    CERT_E_REVOCATION_FAILURE = ctypes.c_long(0x800B010E).value
    TRUST_E_EXPLICIT_DISTRUST = ctypes.c_long(0x800B0111).value
    TRUST_E_BAD_DIGEST = ctypes.c_long(0x80096010).value
    CRYPT_E_SECURITY_SETTINGS = ctypes.c_long(0x80092026).value

    _UNSIGNED = {
        TRUST_E_NOSIGNATURE,
        TRUST_E_SUBJECT_FORM_UNKNOWN,
        TRUST_E_PROVIDER_UNKNOWN,
    }
    _UNTRUSTED = {
        CERT_E_UNTRUSTEDROOT,
        CERT_E_CHAINING,
        CERT_E_REVOCATION_FAILURE,
        TRUST_E_EXPLICIT_DISTRUST,
        CRYPT_E_SECURITY_SETTINGS,
    }


    class GUID(ctypes.Structure):
        _fields_ = [
            ("Data1", wintypes.DWORD),
            ("Data2", wintypes.WORD),
            ("Data3", wintypes.WORD),
            ("Data4", ctypes.c_ubyte * 8),
        ]


    WINTRUST_ACTION_GENERIC_VERIFY_V2 = GUID(
        0x00AAC56B,
        0xCD44,
        0x11D0,
        (ctypes.c_ubyte * 8)(0x8C, 0xC2, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xEE),
    )


    class WINTRUST_FILE_INFO(ctypes.Structure):
        _fields_ = [
            ("cbStruct", wintypes.DWORD),
            ("pcwszFilePath", wintypes.LPCWSTR),
            ("hFile", wintypes.HANDLE),
            ("pgKnownSubject", ctypes.c_void_p),
        ]


    class WINTRUST_DATA(ctypes.Structure):
        _fields_ = [
            ("cbStruct", wintypes.DWORD),
            ("pPolicyCallbackData", ctypes.c_void_p),
            ("pSIPClientData", ctypes.c_void_p),
            ("dwUIChoice", wintypes.DWORD),
            ("fdwRevocationChecks", wintypes.DWORD),
            ("dwUnionChoice", wintypes.DWORD),
            ("pFile", ctypes.POINTER(WINTRUST_FILE_INFO)),
            ("dwStateAction", wintypes.DWORD),
            ("hWVTStateData", wintypes.HANDLE),
            ("pwszURLReference", wintypes.LPCWSTR),
            ("dwProvFlags", wintypes.DWORD),
            ("dwUIContext", wintypes.DWORD),
            ("pSignatureSettings", ctypes.c_void_p),
        ]


    # ---- Certificate publisher extraction via CryptQueryObject ----

    CERT_QUERY_OBJECT_FILE = 1
    CERT_QUERY_CONTENT_FLAG_ALL = 0x00003FFE
    CERT_QUERY_FORMAT_FLAG_ALL = 0x0000000E
    CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
    CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001

    crypt32 = ctypes.WinDLL("crypt32")
    wintrust = ctypes.WinDLL("wintrust")

    WinVerifyTrust = wintrust.WinVerifyTrust
    WinVerifyTrust.argtypes = [wintypes.HWND, ctypes.POINTER(GUID), ctypes.POINTER(WINTRUST_DATA)]
    WinVerifyTrust.restype = wintypes.LONG

    CryptQueryObject = crypt32.CryptQueryObject
    CryptQueryObject.argtypes = [
        wintypes.DWORD,
        ctypes.c_void_p,
        wintypes.DWORD,
        wintypes.DWORD,
        wintypes.DWORD,
        ctypes.POINTER(wintypes.DWORD),
        ctypes.POINTER(wintypes.DWORD),
        ctypes.POINTER(wintypes.DWORD),
        ctypes.POINTER(ctypes.c_void_p),
        ctypes.POINTER(ctypes.c_void_p),
        ctypes.POINTER(ctypes.c_void_p),
    ]
    CryptQueryObject.restype = wintypes.BOOL

    CertEnumCertificatesInStore = crypt32.CertEnumCertificatesInStore
    CertEnumCertificatesInStore.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    CertEnumCertificatesInStore.restype = ctypes.c_void_p

    CertGetNameStringW = crypt32.CertGetNameStringW
    CertGetNameStringW.argtypes = [ctypes.c_void_p, wintypes.DWORD, wintypes.DWORD, ctypes.c_void_p, wintypes.LPWSTR, wintypes.DWORD]
    CertGetNameStringW.restype = wintypes.DWORD

    CertFreeCertificateContext = crypt32.CertFreeCertificateContext
    CertFreeCertificateContext.argtypes = [ctypes.c_void_p]
    CertFreeCertificateContext.restype = wintypes.BOOL

    CertCloseStore = crypt32.CertCloseStore
    CertCloseStore.argtypes = [ctypes.c_void_p, wintypes.DWORD]
    CertCloseStore.restype = wintypes.BOOL

    CryptMsgClose = crypt32.CryptMsgClose
    CryptMsgClose.argtypes = [ctypes.c_void_p]
    CryptMsgClose.restype = wintypes.BOOL


    def hresult_hex(value: int) -> str:
        return f"0x{ctypes.c_uint32(value).value:08X}"


    def classify_signature_status(code: int) -> str:
        if code == 0:
            return "valid"
        if code in _UNSIGNED:
            return "unsigned"
        if code == CERT_E_EXPIRED:
            return "expired"
        if code == CERT_E_REVOKED:
            return "revoked"
        if code in _UNTRUSTED:
            return "untrusted"
        if code == TRUST_E_BAD_DIGEST:
            return "bad"
        return "bad"


    def extract_publisher_from_signed_file(full_path: str) -> str:
        encoding = wintypes.DWORD()
        content_type = wintypes.DWORD()
        format_type = wintypes.DWORD()
        cert_store = ctypes.c_void_p()
        crypt_msg = ctypes.c_void_p()
        context = ctypes.c_void_p()

        try:
            ok = CryptQueryObject(
                CERT_QUERY_OBJECT_FILE,
                ctypes.c_wchar_p(full_path),
                CERT_QUERY_CONTENT_FLAG_ALL,
                CERT_QUERY_FORMAT_FLAG_ALL,
                0,
                ctypes.byref(encoding),
                ctypes.byref(content_type),
                ctypes.byref(format_type),
                ctypes.byref(cert_store),
                ctypes.byref(crypt_msg),
                ctypes.byref(context),
            )
            if not ok:
                return ""

            cert_ctx = CertEnumCertificatesInStore(cert_store, None)
            while cert_ctx:
                needed = CertGetNameStringW(cert_ctx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, None, None, 0)
                if needed and needed > 1:
                    buf = ctypes.create_unicode_buffer(needed)
                    CertGetNameStringW(cert_ctx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, None, buf, needed)
                    name = buf.value.strip()
                    if name:
                        return name
                cert_ctx = CertEnumCertificatesInStore(cert_store, cert_ctx)
            return ""
        except Exception:
            log_exception(f"extract_publisher_from_signed_file exception for {full_path!r}")
            return ""
        finally:
            try:
                if context:
                    CertFreeCertificateContext(context)
            except Exception:
                pass
            try:
                if crypt_msg:
                    CryptMsgClose(crypt_msg)
            except Exception:
                pass
            try:
                if cert_store:
                    CertCloseStore(cert_store, CERT_CLOSE_STORE_FORCE_FLAG)
            except Exception:
                pass


    def verify_signature_wintrust(full_path: str) -> tuple[str, str]:
        file_info = WINTRUST_FILE_INFO()
        file_info.cbStruct = ctypes.sizeof(WINTRUST_FILE_INFO)
        file_info.pcwszFilePath = full_path
        file_info.hFile = None
        file_info.pgKnownSubject = None

        data = WINTRUST_DATA()
        data.cbStruct = ctypes.sizeof(WINTRUST_DATA)
        data.pPolicyCallbackData = None
        data.pSIPClientData = None
        data.dwUIChoice = WTD_UI_NONE
        data.fdwRevocationChecks = WTD_REVOKE_NONE
        data.dwUnionChoice = WTD_CHOICE_FILE
        data.pFile = ctypes.pointer(file_info)
        data.dwStateAction = WTD_STATEACTION_VERIFY
        data.hWVTStateData = None
        data.pwszURLReference = None
        data.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL
        data.dwUIContext = 0
        data.pSignatureSettings = None

        try:
            status = WinVerifyTrust(None, ctypes.byref(WINTRUST_ACTION_GENERIC_VERIFY_V2), ctypes.byref(data))
            log_verbose(f"WinVerifyTrust result for {full_path!r}: {hresult_hex(status)}")
            return classify_signature_status(status), hresult_hex(status)
        except Exception:
            log_exception(f"verify_signature_wintrust exception for {full_path!r}")
            return "error", "exception"
        finally:
            try:
                data.dwStateAction = WTD_STATEACTION_CLOSE
                WinVerifyTrust(None, ctypes.byref(WINTRUST_ACTION_GENERIC_VERIFY_V2), ctypes.byref(data))
            except Exception:
                pass


    def signature_row_for_path(original_path: str) -> tuple[str, str, str, str]:
        full_path = safe_get_full_path(original_path)
        if not full_path or not os.path.exists(full_path):
            log(f"Path does not exist: {original_path!r}")
            return (original_path, "error", "", "missing")
        if os.path.isdir(full_path):
            log_verbose(f"Skipping directory: {full_path!r}")
            return (original_path, "error", "", "directory")

        status, detail = verify_signature_wintrust(full_path)
        publisher = ""
        if status != "unsigned" and status != "error":
            publisher = extract_publisher_from_signed_file(full_path)
        log_verbose(f"Signature result: path={full_path} | status={status} | publisher={publisher} | detail={detail}")
        return (full_path, status, publisher, detail)


    def write_direct_reports(target_path: str, status: str, publisher: str, detail: str) -> None:
        human = [
            f"File: {target_path}",
            f"Status: {status}",
            f"Detail: {detail}",
            f"Publisher: {publisher}",
        ]
        write_text_file(DIRECT_HUMAN_OUTPUT, human, encoding="utf-8")
        log(f"Wrote human-readable direct report: {DIRECT_HUMAN_OUTPUT}")
        batchlike = [f"{sanitize_field(target_path)}|{sanitize_field(status)}|{sanitize_field(publisher)}|{sanitize_field(detail)}"]
        write_text_file(DIRECT_BATCHLIKE_OUTPUT, batchlike, encoding="utf-16")
        log(f"Wrote batch-style direct report: {DIRECT_BATCHLIKE_OUTPUT}")


    def main() -> int:
        args = arguments
        try:
            log("----- signature_check.py start -----")
            log(f"argv={sys.argv!r}")
            log(f"python={sys.executable!r}")
            log(f"cwd={os.getcwd()!r}")

            if not args:
                log("No arguments supplied.")
                return 1

            input_path = args[0]
            output_path = args[1] if len(args) > 1 else ""
            input_full = safe_get_full_path(input_path)
            direct_mode = not is_list_file(input_full)

            if direct_mode:
                log("Mode=direct")
                original, status, publisher, detail = signature_row_for_path(input_path)
                write_direct_reports(original, status, publisher, detail)
                if not output_path:
                    output_path = DIRECT_BATCHLIKE_OUTPUT
                rows = [f"{sanitize_field(original)}|{sanitize_field(status)}|{sanitize_field(publisher)}|{sanitize_field(detail)}"]
                write_text_file(output_path, rows, encoding="utf-16")
                log(f"Wrote output file: {output_path}")
                log("----- signature_check.py success -----")
                return 0

            log("Mode=batch")
            if not output_path:
                output_path = os.path.join(os.path.dirname(LOG_PATH), "signature_check_batch_output.txt")

            if not os.path.exists(input_full):
                log(f"Input list file does not exist: {input_full}")
                write_text_file(output_path, [], encoding="utf-16")
                return 0

            paths = read_input_paths(input_full)
            log(f"Unique queued path count: {len(paths)}")
            rows: list[str] = []
            for path in paths:
                original, status, publisher, detail = signature_row_for_path(path)
                rows.append(f"{sanitize_field(original)}|{sanitize_field(status)}|{sanitize_field(publisher)}|{sanitize_field(detail)}")

            write_text_file(output_path, rows, encoding="utf-16")
            log(f"Wrote output file: {output_path}")
            log(f"Output row count: {len(rows)}")
            log("----- signature_check.py success -----")
            return 0
        except Exception:
            log_exception("Top-level failure")
            try:
                out = args[1] if len(args) > 1 else os.path.join(os.path.dirname(LOG_PATH), "signature_check_batch_output.txt")
                write_text_file(out, [], encoding="utf-16")
                log(f"Wrote empty fallback output file: {out}")
            except Exception:
                log_exception("Failed to write fallback output file")
            return 0
        finally:
            flush_logs()



    return main()


def main(args: list[str] | None = None) -> int:
    args = sys.argv[1:] if args is None else args
    if len(args) != 4 or args[0] != "--mode" or args[1] not in ("motw", "signature"):
        print("Usage: helper.py --mode motw|signature INPUT OUTPUT", file=sys.stderr)
        return 2
    if args[1] == "motw":
        return run_motw(args[2:])
    if os.name != "nt":
        print("Signature mode requires Windows.", file=sys.stderr)
        return 2
    return run_signature(args[2:])


if __name__ == "__main__":
    sys.exit(main())

You must have python installed as the helper uses the Python runtime:

  • PythonExe

Default:

  • python.exe

In most circumstances, you will need to point the script to "python.exe" on your system. This can be done in the script configuration menu.


Button to Toggle Columns

Set COLUMNSTOGGLE="scp:VisualIndicators/V1(8)"
Set COLUMNSTOGGLE="scp:VisualIndicators/V2(9)"
Set COLUMNSTOGGLE="scp:VisualIndicators/V3(10)"
Set COLUMNSTOGGLE="scp:VisualIndicators/V3Publisher(11)"
Set COLUMNSTOGGLE="scp:VisualIndicators/V4(12)"

Visual_Indicators.opusscriptinstall (29.5 KB)

6 Likes

Interesting and good work! It works well for a given directory. Wonder if it could be tied in with Everything search and/or flat view to get a list of all applicable folders... Maybe next iteration. :wink:

1 Like

Thanks :).

If you press F5 to refresh after switching to flat view, it should show you aliased files within all folders within the display.

Upgraded to version 1.3

be great if it somehow worked in thumbnail mode. thumbnail overlays perhaps?

I just did a quick review of the Dopus Docs and there doesn't seem to be a straightforward way of doing this, but happy to be corrected :slight_smile:

Updated to Beta version 2.4.2:

Experimental

  • Added indicators for path variables, symlinks, and files locked by a program
  • Added new commands:
    • Path.Addto
    • Path.Remove
  • Added a new 'locked by' column which lists the locking program(s). This feature requires you to download the attached python helper and to point to it in the script configuration menu. This is my attempt at implementing a version of an idea conceived by @polargoose
  • Added delay timers for favorite and path removal commands (these can be adjusted in the script configuration. I run 1.5 secs.
1 Like

Updated to version 2.13.3.

  • general performance improvements.
  • added MOTW and signature checks.
  • removed locked-by.
  • added new helpers.
  • added Sandboxie column
1 Like

Version 2.17.1

  • Significant speed and QOL improvements.
  • Prompts to create the python helper in place.
1 Like