Releases: michal-ruzicka/TCOfficeView
Release list
Release v2.4.0
[v2.4.0] – 2026-07-09
Added
-
Full mode (and the mode-switch button) now covers OpenDocument files, Office templates and PowerPoint slideshows. Previously only the classic Office extensions were recognised as Word / Excel / PowerPoint documents; everything else — including formats those applications open natively — was treated as a generic preview-handler file, so the → Full button never appeared and the quick→full auto-fallback never fired. The recognised set now additionally includes:
- Word — ODT (OpenDocument Text), DOT, DOTX (templates)
- Excel — ODS (OpenDocument Spreadsheet), XLT, XLTX (templates)
- PowerPoint — ODP (OpenDocument Presentation), PPS, PPSX (slideshows), POT, POTX (templates)
OpenDocument templates (OTT, OTS, OTP) are not included because Microsoft Office does not open them.
Security
-
Full mode no longer executes document macros. Office applications driven via OLE Automation default to
msoAutomationSecurityLow, so a full-mode preview of a document with VBA macros used to run its AutoOpen/Document_Open code without any prompt: automation opens bypass both Protected View and the "Enable Content" notification bar. In practice this affected XLSB and the legacy DOC / XLS / PPT formats (the explicitly macro-enabled DOCM / XLSM / PPTM never reach the plugin at all — see the note below). The host now setsApplication.AutomationSecurity = msoAutomationSecurityForceDisableon every Word / Excel / PowerPoint instance it creates, so previews never execute macros in either mode (quick previews could never run them). The setting is per-instance and runtime-only — it does not change the user's Office configuration. To run a document's macros, open the file in the Office application itself.Note that Office deliberately registers no preview handler for any of its macro-enabled formats (DOCM, DOTM, XLSM, XLTM, PPTM, PPSM, POTM) — those files preview neither in Windows Explorer's Alt+P pane nor in this plugin, which steps aside so Total Commander's next viewer takes over. XLSB is the exception: it can carry macros yet has a preview handler registered, which is one more reason the defence is the automation setting rather than an extension list. This is now documented in
README.md.
Fixed
- The full-mode overlay window can no longer be moved or resized by the user. The borderless Office window floated over the Lister pane could be dragged away by the free space of its title bar, or resized by grabbing its edges (typically by accident, when aiming for the Lister's edge), and stayed displaced until the pane itself changed. The overlay tracker now cancels such a drag the moment it starts — the window never leaves its place — and additionally snaps the window back over the pane whenever its position or size drifts for any other reason.
- GitHub CI build restored. The workflow now uses the CMake (and Ninja) bundled with the Visual Studio Build Tools via the
VC.CMake.Projectcomponent instead of installing CMake separately through winget. This also keeps the local and CI toolchains identical for reproducible builds. The pinned compiler version was bumped to19.51.36248to match the current Build Tools release, andsetup-build-environment-example.cmdnow accepts the installer's reboot-requested exit code (3010) as success.
Release v2.3.1
[v2.3.1] – 2026-06-05
No user-visible feature changes. This release adds reproducible builds —
locks the build toolchain so that the same source commit always produces
byte-identical binaries, giving users an independent way to verify a release
binary against the published source code.
See Verifying Releases in README.md and
Reproducible Builds in CONTRIBUTING.md
for the verification workflow and the full technical details.
Added
setup-build-environment-example.cmd— a one-shot script that sets up a
complete build environment on a fresh Windows installation (VM,
Windows Sandbox,
or similar), downloads the source tree from GitHub, installs Visual
Studio Build Tools and CMake, and runsbuild.cmdto produce the
distributable ZIP. Every step is visible and documented inside the script.
Changed
- Build toolchain pinned for reproducible builds. The exact MSVC compiler
version (19.51.36246), toolset (14.51) and Windows SDK (10.0.26100.0)
are locked inbuild.cmdand the CI workflow. The build uses the NMake
Makefiles generator with the compiler environment activated per architecture
viaVsDevCmd.bat -vcvars_ver=14.51— no VS generator flag is needed and
cmake's VS instance detection is bypassed entirely.
The MSVC compiler flags/Brepro,/experimental:deterministicand linker
flag/BREPROeliminate per-build noise from object files and the PE
timestamp. Source-file paths in debug info are normalised via/pathmap.
File timestamps in the ZIP are set torelease-date=frompluginst.inf. sha256sums.sha256added to every release ZIP. The file lists the SHA-256
of every other file in the archive. The CI build log andbuild.cmdboth
print the SHA-256 of the produced ZIP itself, providing an independent
reference for cross-build comparison.- Line endings in ZIP text files normalised to CRLF. Markdown, INI and
INF files in the release ZIP are now guaranteed to use Windows line endings
regardless of the platform or git configuration the build was run under.
Release v2.3.0
[v2.3.0] – 2026-05-28
Full-mode preview for all Office apps is now fully interactive and much
more reliable. Rapid Ctrl+Q/F3 browsing among Office files no longer
triggers a wave of cold-starts if full mode is used.
Upgrading from an earlier version? Total Commander keeps an
already-configured detect string when a plugin is replaced, so
users coming from v2.1.0 or earlier won't automatically pick up
the new universal file-type support — see
Upgrading from an Earlier Version inREADME.md.
Added
- Word, Excel and PowerPoint full mode are now fully interactive and much
more reliable.
Full-mode previews used to render almost correctly but especially in Excel
clicking, scrolling and ribbon buttons did not work always correctly.
All three apps now behave like normal read-only Office windows. Achieving
this required re-architecting all three from window embedding to a
top-level overlay — see Changed below. The → Quick button still
works as before. - Configurable dwell-time before starting an Office application
([Mode] FullLoadDelayMs, default 1000 ms). The delay prevents
rapid arrow-key browsing from triggering a wave of expensive Office
cold-starts. It works differently by mode:full/full-switchable— the Office launch is deferred from
initial navigation; if the user moves on within the dwell window
the launch is cancelled entirely and Office is never touched.quick-switchable(the default) — quick mode runs immediately
(no delay) and succeeds for ordinary Office files. The delay
kicks in only when the quick handler fails and auto-fallback to
full mode would fire — which in practice means SharePoint
documents synced from a non-primary Microsoft 365 tenant. For
those files "Preview is loading…" is shown during the dwell
window; the mode-switch button is hidden. Moving to another file
within that window cancels the Office launch. Files that load
fine in quick mode are completely unaffected.
Set to0to disable and load immediately (restores pre-dwell-time
behaviour). The delay never applies to the→ Fullmode-switch
button — that always loads immediately.
Changed
-
All three Office apps re-architected from window embedding to a
top-level overlay. Word, Excel and PowerPoint full mode all used to
embed the real Office window — reparent it as a child of the Lister
pane. All three are now kept as a borderless top-level window floated
over the pane. This is the only way to make them foreground-capable,
and therefore interactive (especially very important for Excel windows);
a reparented child of another process can never take the foreground, which
is why the embedded versions were limited in some functionality.Behavioural consequences worth knowing:
- The preview is live only while Total Commander is the front window.
Switch to another application and the pane shows a frozen snapshot
of the last Office state (still readable) until you switch back. - Modern Office apps draw their own title bar, so the Close button is
present even on a frameless window; closing the preview that way tears
it down and shows a "Full preview was closed." message instead of a
blank pane. - The grey close-guard strip that used to cover the top of
Word/Excel/PowerPoint full previews is gone — it was needed only to
intercept the close button on embedded windows (resulting in closing
lister [whenF3was used] or even whole Total Commander window [when
Ctrl+Qwas used]), and is not needed in the overlay model. - A "Preview is loading…" indicator appears for full preview mode.
- The preview is live only while Total Commander is the front window.
-
Mark-of-the-Web blocking enforced in full mode.
Files opened via OLE Automation do not trigger Office's Protected View
pipeline — the application trusts its COM caller and opens the file
without the "Enable Editing" quarantine banner, bypassing the
security control MOTW is meant to enforce. TCOfficeView now applies
its own MOTW check before launching any Office full-mode load: if
the file is MOTW-blocked (Internet or Restricted zone), the Unblock
fallback panel is shown instead of starting Office. After clicking
Unblock this file the preview reloads in full mode as normal.
Quick and auto-fallback paths are unchanged. -
Unblock button made simpler on the MOTW info page.
Fixed
- Rapid switching between Office files no longer triggers a load for
every file flicked past. Two complementary debounce mechanisms now
work together: a dwell-time timer (seeFullLoadDelayMsabove) prevents
the Office cold-start from starting at all for files you navigate through
quickly, and a message-queue trailing-edge filter skips queued LOAD
requests when a newer one is already waiting — so only the file you
actually land on gets rendered. This also applies to the auto-fallback
path for SharePoint cross-tenant documents (which previously could trigger
Office cold-starts even on files the user had already left).
Release v2.2.2
[v2.2.2] – 2026-05-26
Upgrading from an earlier version? Total Commander keeps an
already-configured detect string when a plugin is replaced, so
users coming from v2.1.0 or earlier won't automatically pick up
the new universal file-type support — see
Upgrading from an Earlier Version inREADME.md.
Added
- Auto-fallback from quick to full mode for Office documents the
preview handler refuses to render. Files synced from a SharePoint
site in a non-primary Microsoft 365 tenant typically fail in quick
mode with HRESULT0x80004005(E_FAIL) or0x80004001(E_NOTIMPL) —
the preview handler's sandboxed surrogate process can't authenticate
cross-tenant. This is an Office-side limitation that affects
Windows Explorer's Alt+P / Preview Pane the same way; it isn't
specific to TCOfficeView. When this happens TCOfficeView now
silently retries the preview by launching the real Office
application in the background (which runs as the user with full
auth tokens and usually succeeds). Controlled per application from
a new[AutoFallback]INI section —Word=true/Excel=true/
PowerPoint=true(default for all three). Auto-fallback only
kicks in when the application is in thequick-switchablemode
(the default); explicitquickmode opts the application out.
Mark-of-the-Web-blocked files keep their dedicated Unblock
fallback panel — they are intentionally excluded from auto-
fallback because opening them in the real Office app would
bypass Protected View. SeeREADME.md→ Configuration →
Auto-Fallback for Multi-Tenant SharePoint Documents. - User-initiated mode switch suppresses auto-fallback. When
the user clicks the→ Quickoverlay button on a document that
auto-fell-back to full at load time, the click is now treated as
an explicit "I want quick mode here" instruction — auto-fallback
is skipped so the click does not silently bounce the document
back to full mode. Instead the quick fallback panel is shown
(with an Office-specific explanation of why the preview handler
refuses the file) and the overlay button flips to→ Fullso
the user can return to full mode deliberately. - Office-aware text in the generic fallback panel. For Word,
Excel and PowerPoint files the "preview handler failed" message
now lists the common causes (SharePoint cross-tenant sync,
corrupted document, broken Office install) and notes the
Explorer-Alt+P-parity behaviour. When the file's application
is in a switchable mode, a→ Fullbutton hint is included.
Release v2.2.1
[v2.2.1] – 2026-05-26
Upgrading from an earlier version? Total Commander keeps an
already-configured detect string when a plugin is replaced, so
users coming from v2.1.0 or earlier won't automatically pick up
the new universal file-type support — see
Upgrading from an Earlier Version inREADME.md.
Added
- Mark-of-the-Web detection and one-click unblock in the fallback panel.
When the preview handler refuses to render a file, the fallback panel
now reads the file'sZone.Identifieralternate data stream and, if
the file is marked as having come from the internet (ZoneId>=3,
i.e. Internet or Restricted zone), replaces the generic "handler
failed" text with a tailored explanation: the security zone, the
originating URL if present, and a plain-language description of what
Office's Protected View does and why. An Unblock this file and
retry the preview button is shown at the bottom of the pane; one
click strips theZone.IdentifierADS (equivalent to PowerShell's
Unblock-Fileor right-click → Properties → Unblock) and re-runs
the LOAD in the same mode the user was in, so the document opens
without leaving the Lister pane. The button is only shown for
MOTW-blocked files; for all other failure causes the fallback panel
is unchanged.
Fixed
-
Cross-process window reparenting in Full mode no longer causes
Total Commander UI stutter. Office application windows (Word,
Excel, PowerPoint) are now hidden withShowWindow(SW_HIDE)before
SetParentstrips their top-level frame and reparents them into the
Lister pane. Previously the reparent happened while the window was
still visible — PowerPoint in particular cannot be started invisibly
(Application.Visible = Falseis rejected) — which forced Windows
to synchronously reconcile window state across three processes
(TC → host → Office) and made Total Commander's own modal dialogs
(copy, overwrite confirmation, …) feel sluggish and jerky while a
Full-mode preview was active.On detach (
UnloadWordFullSta,UnloadExcelFullSta,
UnloadPptFullSta) each app's window now receives
SetWindowPos(..., SWP_FRAMECHANGED | SWP_HIDEWINDOW)after its
style is restored toWS_OVERLAPPEDWINDOW. Without this the window
manager could leave the frame in an inconsistent state (a top-level
window without caption or borders) until the next paint, producing
"ghost" windows that continued to interfere with focus and Z-order.
Release v2.2.0
[v2.2.0] – 2026-05-25
Universal Preview Handler support is tha main enhancement of this
release — PDF, HTML, ... Anything that Explorer's Alt+P pane can show
is now supported by TCOfficeView Total Commander plugin.
Upgrading from an earlier version? Total Commander keeps an
already-configured detect string when a plugin is replaced, so
users coming from v2.1 or earlier won't automatically pick up
the new universal file-type support — see
Upgrading from an Earlier Version inREADME.md.
Added
-
Universal Preview Handler support (PDF, HTML, anything Explorer's
Alt+P pane can show). The plugin advertises support for all file
type (EXT="*") so fresh installs work out of the box for the common
formats; users who want truly universal support can switch the detect
string in TC toEXT="*"(documented in README) and the plugin will
be asked about every file. A new registry probe in the plugin DLL
(HasPreviewHandlerForExt, mirroring the host's
FindPreviewHandlerClsidlookup chain — direct shellex → default
ProgID →OpenWithProgids→SystemFileAssociations\<ext>→
SystemFileAssociations\<PerceivedType>) decides at LOAD time
whether a Windows Preview Handler is actually registered for the
file's extension; if not, the plugin returns the "decline" value
so TC moves on to the next configured Lister plugin or its
built-in viewer. Cost: one zero-allocation registry walk per
F3 / Ctrl+Q; no host process spawn for files we can't render.In practice this gives the user automatic support for PDF (via
Edge's built-in handler on Windows 10+, or Adobe Acrobat Reader if
installed), MSG (via Windows' built-in MAPI Mail Previewer),
and — withEXT="*"— Photoshop PSD, AutoCAD DWG/DXF,
Sketchup SKP, and anything else that ships a Preview Handler. -
[PreviewHandlers]INI section for per-extension CLSID overrides.
When several preview handlers are installed for the same file type
(e.g. both Microsoft Edge and Adobe Reader register one for.pdf,
whichever was installed last wins system-wide), the user can now
pin a specific handler for this plugin only by writing
<.ext>=<CLSID>in the INI:[PreviewHandlers] .pdf={3A84F9C2-6164-485C-A7D9-4B27F8AC009E}
Override entries are consulted before the standard registry lookup
chain; the system-wide registration is the fallback when no override
matches. Bad CLSIDs are silently ignored at load time. Explorer's
preview pane and other applications keep using whatever Windows
picked as the system default — the override is scoped to
TCOfficeView only. The shipped sample INI documents the format and
points at the
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\PreviewHandlers
registry key where every installed handler is enumerated with its
CLSID and friendly name. -
Optional discovery report — set
[PreviewHandlers] ReportPath=<path>
in the INI to enable. When the option is set, the host writes
(on a low-priority background thread, every time it starts) a
human-readable text file at the chosen location containing:- Section 1 — every installed preview handler on the machine,
sorted by friendly name, with its CLSID alongside (the master
pick-list). Source:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\PreviewHandlers. - Section 2 — the current per-extension assignment for every
file type that has a registered handler (walked fromHKCR\.*),
preformatted as commented-out INI lines
(;.pdf={CLSID} ; Friendly name) sorted by extension and ready
to copy into the[PreviewHandlers]section of
TCOfficeView.ini— uncomment a row, swap the CLSID for one of
the alternatives from section 1 above.
Written atomically via a
.tmpfile +MoveFileExW, so the
report is never observed half-written. Off by default — the
registry walk is cheap but it's still wasted work on every Lister
session when the user isn't actively configuring overrides. Turn
it on while setting up overrides, then comment the line out again.
Failure (path unwritable, destination locked by an editor, …) is
logged and silently skipped — the report is a convenience, not a
requirement for the plugin to function. - Section 1 — every installed preview handler on the machine,
-
Per-extension deny in
[PreviewHandlers]— write.ext=(empty
value) to skip an extension entirely. TCOfficeView then behaves
as if no preview handler existed for that file type: the plugin
DLL returnsnullptrfromListLoadW/LISTPLUGIN_ERRORfrom
ListLoadNextW, Total Commander routes the file to the next
configured Lister plugin or its built-in viewer, and the host
process is never even spawned. Useful when another Lister plugin
does a better job for a specific file type (e.g. a dedicated PDF
previewer) and the user wants to keep TCOfficeView for everything
else.The plugin DLL re-reads the
[PreviewHandlers]section from the
INI on everyListLoadW/ListLoadNextWcall, so deny-list edits
take effect immediately without restarting Total Commander. The
host re-reads the section on every spawn and honours the deny list
insideFindPreviewHandlerClsidas a defence-in-depth backstop in
case the DLL ever forwards a file for a denied extension.
Changed
- README's “Supported Formats” section is now an indicative list of
common handlers rather than the authoritative whitelist (which is
whatever the user's machine has registered). The “When MS Office
Is Not Installed” section was renamed and rewritten to reflect the
new behaviour: silent decline + TC fall-through for files with no
handler, and the fallback panel reserved for cases where a handler
IS registered but fails at run time.
Fixed
-
[PreviewHandlers]parser rejected entries that ended with an
inline;comment. The sample INI documented the format
.pdf={CLSID} ; Friendly name, exactly the same shape the
discovery report produces for copy-paste — but the parser passed
the value, comment and all, straight toCLSIDFromString, which
is strict about trailing characters and silently dropped the
entry. The override therefore had no effect even though the user
had written it correctly per the docs. Values are now stripped
of any inline;…tail and surrounding whitespace before being
parsed. Each successfully-loaded override is also logged
(PreviewHandlers override: .pdf -> {…}), and each rejected
entry is logged asREJECTED (bad CLSID)so typos are easier
to spot. -
ListGetDetectStringnow returnsEXT="*"instead of a
hard-coded list of Office extensions. Total Commander calls this
exported function the first time it needs to query the plugin's
detect string and stores the returned value inwincmd.ini,
overriding whateverdefaultextension=inpluginst.infset
initially. The stale hard-coded list was the real reason new
file types (PDF, HTML, …) were not picked up automatically on
fresh installs — they simply weren't in the string TC saw. With
the new value, fresh installs route every file through the plugin
DLL'sHasPreviewHandlerForExtregistry probe, exactly the way
the new universal-handler architecture was meant to work.Existing users coming from v2.1 or earlier need a one-off
configuration refresh to pick this up — see Notes below. -
ListLoadNextWno longer leaves a stale preview on screen when
navigating (n/pkeys in the Lister) to a file the plugin
can't handle. The previous code returned the wrong constant on
the failure path —0instead of1— so Total Commander
interpreted "no handler for this file" as success, kept the
Lister window open, and left the prior file's rendering visible
in it. The plugin now uses the documentedLISTPLUGIN_OK(0) /
LISTPLUGIN_ERROR(1) constants (added tolistplug.hfor
clarity) and returnsLISTPLUGIN_ERRORwhenever it can't load
the requested file — at which point TC closes the Lister and
routes the file to the next configured plugin or its built-in
viewer. The success path was also corrected from1to0;
this had been silently wrong since the plugin's first release but
TC's tolerance for either value masked it. -
pluginst.infno longer ships eitherdetect=or
defaultextension=. The former is recognised by Total Commander
only for archive (WCX) plugins; the latter would, if TC reads it at
install time, write a finite EXT="…" list towincmd.inithat
would then conflict with theEXT="*"value the plugin's
ListGetDetectStringreturns on first use.ListGetDetectString
is now the single source of truth — the plugin DLL itself decides
which files TC should ask it about, and the answer is "all of
them; my registry probe will decline the ones I can't render".
Notes
-
Upgrading from v2.1.0 or earlier requires a one-off configuration
refresh to enable the new universal file-type support. Total
Commander does not overwrite an already-stored detect string when
a plugin's DLL is replaced — even ifListGetDetectStringwould
return something different — so existing installs keep the old
Office-only detect string and never get asked about PDF, HTML, or
the other newly-supported file types.Two ways to refresh it:
- Remove and re-add the plugin in Total Commander →
Configuration → Options → Plugins → Lister plugins →
Configure. On the next file preview, TC will ask the new
plugin DLL for its detect string and storeEXT="*". - Edit
wincmd.inidirectly — Total Commander's GUI does
not expose a way to change a Lister plugin's detect string at
all,...
- Remove and re-add the plugin in Total Commander →
Release v2.1.0
[v2.1.0] – 2026-05-23
Added
-
Long path support (paths > MAX_PATH / 260 characters), to the extent
Windows and Office permit it. The host process now declares
<longPathAware>true</longPathAware>in its manifest, and
GetModuleFileNameW/GetEnvironmentVariableW(L"APPDATA", …)
callers no longer rely on fixed-size MAX_PATH buffers, so the
plugin can be installed under a long path.Long paths require both
<longPathAware>true</longPathAware>in
the manifest (we ship this) and the system-wide
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled = 1
registry switch (Windows default is0; user/admin must enable it).
With both in place, Win32 / Shell file APIs accept paths longer than
MAX_PATH and we pass the raw path to every preview entry point —
IInitializeWithFile::Initialize,SHCreateStreamOnFileEx,
SHCreateItemFromParsingName, and Office'sDocuments.Open/
Workbooks.Open/Presentations.Open. All of them rejected the
\\?\long-path prefix in testing (Shell APIs withE_INVALIDARG,
Office handlers withE_NOTIMPL), so the prefix is only used for
Win32 file APIs that genuinely benefit from it — currently just
GetFileAttributesExWin the fallback panel — via a new
EnsureLongPathPrefix()helper.Hard limits inside Office that the raw long path could not get
past — Word's preview handler returnedE_NOTIMPLand Excel /
PowerPoint refused both Open() and their preview handlers on paths
above MAX_PATH-1 — are bypassed transparently by creating a
per-LOAD directory junction (NTFS reparse point with
IO_REPARSE_TAG_MOUNT_POINT) in%TEMP%pointing at the file's
parent folder, and passing every consumer a short alias path
(%TEMP%\TCOV_<pid>_<tick>\<filename>) inside that junction. The
kernel transparently follows the junction to the real file, so the
consumer never sees a long path at all. This works regardless of
theLongPathsEnabledregistry switch, requires no privileges
(junctions, unlike symbolic links, are unprivileged) and applies
uniformly to Word / Excel / PowerPoint in both quick and full mode.Junction lifecycle:
- Creation: on the LOAD that exceeds the threshold (
MAX_PATH-9). - Removal on the next LOAD: deferred until AFTER the loader has
closed the previous consumer's document (an earlier draft removed
the junction at the top ofLoadFileWithModeSta, which routinely
failed because Word keeps a directory-change-notification handle on
the parent folder of an open document and that handle survives
untilDocuments.Close). - Removal on
WM_HOST_CLOSE: after the finalUnloadXxxFullSta. - Retry queue: a junction whose
RemoveDirectoryWfails (Office
handle still pending, antivirus scan in flight, …) is parked on a
stale list and re-attempted on every subsequent cleanup opportunity. - Startup sweep: every host process scans
%TEMP%\TCOV_*on
launch and removes junctions whose owning PID is no longer alive.
This is the safety net for orphans left by host crashes or by TC
killing the host during shutdown.
MSG remains the exception: it never needs the junction because
mssvp.dllis initialised throughIInitializeWithItem(Shell-item-
based, immune to path length). - Creation: on the LOAD that exceeds the threshold (
Release v2.0.0
[v2.0.0] – 2026-05-22
Added
- Full render mode for Word, Excel and PowerPoint via a new
[Mode]INI section. Four values are accepted per application:
quick(Preview Handler, no button),quick-switchable(Preview
Handler with overlay button — new default),full(OLE
Automation, no button),full-switchable(OLE Automation with
overlay button). When a full-mode value is set, the plugin launches
a real Word / Excel / PowerPoint instance, opens the file
read-only, and embeds its window into the Lister pane, giving the
full Print Layout / grid / slide rendering instead of the
simplified Preview Handler pipeline. Cold start is ~2–4 s;
memory ~100–300 MB per instance. On any failure the plugin
transparently falls back to quick mode. - Mode-switch overlay button in the top-right of every Word /
Excel / PowerPoint preview (shown when the configured mode is
quick-switchableorfull-switchable). One click toggles the
current preview between quick and full mode without changing the
INI default; the switch is per-preview only — the next file (or
re-opening the same one) starts at the configured default. Button
size and font scale with the monitor's DPI. Always hidden for file
types with no full-mode handler (.msg,.vsdx) regardless of
the setting. - Per-app preview niceties in full mode:
- Word — Print Layout view, page-width zoom that auto-refits
on Lister resize, rulers hidden, runtime read-only enforcement
so typing in the preview is blocked. - Excel — zoom locked to 100% on load; initial frame size
matches the Lister pane. Two intrinsic limitations of embedding
Excel as a child window via OLE Automation, which no combination
of style edits, window-message synthesis or activation tricks
convinced Excel to overcome:- Excel does not relayout when the pane is later resized;
reopening the Lister at the desired size triggers a fresh
correct layout. - Interactive mouse input (cell selection, sheet-tab clicks,
most ribbon buttons) is unreliable, because Excel gates much
of that processing on being the foreground top-level window —
and a reparented child of a foreign process never is. Quick
mode is unaffected; for interactive work, use quick mode.
Full Excel mode is best treated as a read-only viewer.
- Excel does not relayout when the pane is later resized;
- PowerPoint — slide zoom auto-refits to the Lister pane on
every resize. PowerPoint's main window appears briefly on
screen before being embedded (a short visible flash) because
PowerPoint cannot be told to run invisibly; Word and Excel
embed silently.
- Word — Print Layout view, page-width zoom that auto-refits
Changed
- Moved the
AppKindenum declaration beforeHostStateso that
HostState::currentFileAppcan be initialised at compile time without
relying on a forward-declaration hack.
Fixed
- Preview handlers were activated in-process, which violates the
IPreviewHandlercontract.LoadHandlerStaused
CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER, so COM happily loaded any
handler that registered anInProcServer32(the Windows built-in MAPI
Mail Previewer for.msg, in particular) directly into our process.
Such handlers complete activation, initialisation andSetWindow, then
failDoPreviewwithE_FAILbecause Microsoft'sIPreviewHandler
documentation states a handler must be hosted in its own background
process. Activation is nowCLSCTX_LOCAL_SERVERonly, matching the
reference preview-host sample and Windows Explorer's preview pane —
COM now routes through the AppID'sDllSurrogate(typically
prevhost.exe), and MSG previews finally render. CoInitializeSecurityis now established at host start-up. Handlers
that run in Windows' low-integrityprevhost.exesurrogate (notably the
Outlook MSG preview handler) need an explicit process-wide COM security
blanket to perform cross-process calls back to the host; without it
DoPreviewreturnsE_FAIL. The new call matches the settings used by
Windows Explorer's own preview pane (RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE).- Preview handlers requiring an
IPreviewHandlerFramesite failedDoPreview.
Outlook's MSG preview handler (and other handlers hosted inprevhost.exe)
ask the host forIPreviewHandlerFrameandIOleWindowvia a site object
installed throughIObjectWithSite::SetSite; without itDoPreviewreturns
E_FAILand the preview never renders. A newPreviewHostSiteclass
implementsIPreviewHandlerFrame(no-op accelerator translation),
IServiceProvider(routingIPreviewHandlerFrame/IOleWindowlookups
back to itself) andIOleWindow(returning the render window's HWND).
The site is installed before anyIInitializeWith*::Initializecall —
Outlook's MSG handler queries the site from insideInitializeand aborts
the load if it isn't ready yet — and cleared again on unload. The call
order inLoadHandlerStanow matches Microsoft's recommended sequence:
CoCreateInstance → QI IPreviewHandler → SetSite → Initialize → SetWindow
→ DoPreview. - Preview handlers initialised only via
IInitializeWithItemcould not load.
LoadHandlerStapreviously tried onlyIInitializeWithFileand
IInitializeWithStream. Outlook's MSG preview handler rejects both
(E_NOINTERFACE) and supports exclusively the modern Shell-item-based
IInitializeWithItem, which the loader now tries as a third fallback
(SHCreateItemFromParsingName→IInitializeWithItem::Initialize). - Preview handlers missed when registered outside the direct extension key.
FindPreviewHandlerClsidpreviously looked for the preview handler CLSID
only directly on the extension key and via the extension's default ProgID.
This missed handlers registered in any of the other places Windows
Explorer's preview pane consults — notably the MSG handler, which Outlook
registers under a versioned ProgID inHKCR\.msg\OpenWithProgids
(e.g.Outlook.File.msg.16) rather than as the default ProgID. The
lookup now follows the full Shell association chain that Explorer uses:
direct shellex key → default ProgID → each ProgID inOpenWithProgids→
HKCR\SystemFileAssociations\<ext>→HKCR\SystemFileAssociations\<PerceivedType>.
MSG and similar previews now work on systems where Windows Explorer already
shows them. - Plugin deadlock on Lister close / TC exit.
TerminateSessionused an
infinite timeout when writingCLOSEto the host pipe. If the host's pipe
reader thread had already died (e.g. access violation), the write would
block forever, freezing Total Commander. The write now uses a 3-second
timeout and cancels the pending I/O if it expires. - Race condition in plugin
ChildWndProc(use-after-free). The resize
timer handler looked up the session underg_sessionsMutex, released the
lock, and then wrote tosession->hPipe. Between releasing the lock and
the write,ListCloseWindowon another thread could erase anddelete
the session. The mutex is now held for the entire pipe write. - Race condition in host
HostLogcritical-section initialisation.
InitializeCriticalSectionwas called lazily on the firstHostLog
invocation without any synchronisation. Two threads (STA + pipe reader)
could race and initialise the sameCRITICAL_SECTIONtwice, corrupting
it. The CS is now initialised once inwmainbefore the pipe reader
thread is created. - Pipe buffer exhaustion after many file switches. The host sends
OK\n/ERR …\nreplies for everyLOADandCLOSE, but the plugin
never read them. After roughly 5 000ListLoadNextWcalls in a single
Lister session the 64 KB pipe buffer filled up and subsequent writes
blocked indefinitely. A background drain thread now continuously reads
and discards host responses. - Handle leaks in the host process. The log file handle, the logging
CRITICAL_SECTION, and the OfficeJobObjecthandle were never closed
or destroyed before process exit. They are now cleaned up inwmain
after the message loop terminates. - Potential
CreateProcessWcommand-line mutation.CreateProcessW
requires a writable command-line buffer.cmdLine.data()returns
const wchar_t*in pre-C++17 standards, which is undefined behaviour.
Changed to&cmdLine[0], which is writable in all C++ versions. - Missing null check in
ListLoadNextW. Added an explicit guard against
anullptrFileToLoadargument. - Re-entrancy crash when switching modes rapidly (PowerPoint). The retry
loops insideLoadWordFullSta,LoadExcelFullStaand
LoadPowerPointFullStacontainedPeekMessagedispatch loops that pumped
the STA message queue. While a load was still in progress, a second
WM_HOST_SWITCH_MODEmessage could be dispatched recursively, causing
re-entrant COM calls and eventual heap corruption or access violation. The
PeekMessageloops have been replaced with plainSleep, and a
loadingInProgressguard now serialisesLoadFileWithModeStacalls so
that a second switch is deferred until the first one finishes. - Document not closed before quick-mode fallback detach. When full-mode
loading failed and the host fell back to quick mode, the Office document
was left open in the background while the window was detached. The
appropriate close routine (CloseWordDocumentSta,
CloseExcelWorkbookSta,ClosePptPresentationSta) is now called before
detaching the window in the fallback path. - Crash when clicking the embedded Office window's close button.
EmbedOfficeWindowStastrips Win32 caption styles, but Office apps
(Word, Excel, PowerPoint) render their own close button inside the
r...
First public binary release
TCOfficeView previews Microsoft Office documents — Word, Excel, PowerPoint, Visio, Outlook messages and more — directly in Total Commander's F3 / Quick View (Ctrl+Q) pane. It delegates rendering to the Windows Preview Handlers that an MS Office installation already registers, so previews look exactly like those in Windows Explorer, without any document parsing and without a managed runtime dependency.
If MS Office is not installed (or a handler fails to load), the plugin shows a small information panel with the file's basic metadata instead of an empty pane.
Supported formats
| Application | Extensions |
|---|---|
| Word | DOC, DOCX, DOCM, RTF |
| Excel | XLS, XLSX, XLSM, XLSB |
| PowerPoint | PPT, PPTX, PPTM |
| Visio | VSD, VSDX |
| Outlook | MSG |
Installation
Recommended — Total Commander auto-installer:
- Download
TCOfficeView.v1.0.0.zipbelow (and verify the digital signatureTCOfficeView.v1.0.0.zip.asc[see below]) - In Total Commander, navigate to the ZIP and press Enter.
- TC detects
pluginst.infand offers to install the plugin — confirm. - Press F3 or Ctrl+Q on any
.docx/.xlsx/.pptxto verify.
Manual install: unzip into a persistent folder and register TCOfficeView.wlx (32-bit TC) or TCOfficeView.wlx64 (64-bit TC) under Configuration → Options → Plugins → Lister plugins → Configure → Add.
Verifying the download
Each release ships a detached GPG signature alongside the ZIP:
gpg --keyserver keys.openpgp.org --recv-keys 489C5EC80FD62BE89E59B4F719C13E8CE0F5DB61
gpg --verify TCOfficeView.v1.0.0.zip.asc TCOfficeView.v1.0.0.zip
Expected: Good signature from "Michal Růžička <ruzicka.mich@gmail.com>"
Key fingerprint: 489C 5EC8 0FD6 2BE8 9E59 B4F7 19C1 3E8C E0F5 DB61
Full changelog: CHANGELOG.md