SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
Rendering — what the bridge can draw, and what it still has to measure
Drew, 2026-10-02: "Does SW have rendering like fusion so we can get a really
gorgeous shot of this assembly?" — then "go ahead and try it… and if it works,
let's add a bunch of intel into the bridge to handle rendering." The Fusion
bridge has no render verb at all (docs/FUSION-PARITY-REPORT.md), so this is
new ground.
Every line here is [measured] (seen on Drew's laptop) or [unmeasured] (written from the API documentation; not yet run live). Track A was MEASURED LIVE on 2026-10-05 (below); what is still unmeasured is named.
The facts this is built on
- [measured] PhotoView 360 is ABSENT on this edition (3DEXPERIENCE SOLIDWORKS for Makers 2026). The renderer is the viewport itself: RealView, ambient occlusion, shadows and perspective, on an RTX 4090 Laptop GPU.
- [measured]
swx_show_assembly+ViewZoomtofit2work live on the Moveo assembly (C:\Users\Public\adom-hero\BCN3D-Moveo-master\CAD files\BCN3D Moveo assembly.SLDASM, 110 documents, read-only) — the test subject. - [measured]
swx_screenshot(ab's PrintWindow by handle) works, but it is a screen grab capped at the window, about 1568 px wide — not an export. - [measured] SOLIDWORKS Visualize 2026 is installed at
…\SOLIDWORKS 3DEXPERIENCE R2026x\Visualize\SLDWORKSVisualize.exe, takes a model path as its argument, ships no scripting interface on disk, and raises its OWN 3DEXPERIENCE sign-in.
Track A — MEASURED 2026-10-05
On adom_drew2, hosted 0.9.18, SOLIDWORKS 2026 SP3 (Makers), the Moveo assembly (110 documents, read-only), the SOLIDWORKS window MINIMIZED throughout:
| Request | Result |
|---|---|
{width:1920, height:1080} |
ok, 411,368 bytes, PNG header 1920×1080, capped:false, nothing applied or restored, 10,403 ms |
{width:3840, height:2160, view:"isometric", displayStyle:"shaded", perspective:true, realView:true, ambientOcclusion:true, shadows:true, zoomToFit:true} |
ok, 979,997 bytes, PNG header 3840×2160, capped:false, 11,597 ms. Applied: ambientOcclusion false→true, displayMode 5→4, orientation isometric, perspective false→true, realView false→true, zoom fit. Restored: every one read back equal to its old value; camera captured and restored; restoreFailures: [] |
hosted 0.9.19, the same plus zoomFactor:2.0 |
ok, 932,312 bytes, 3840×2160, 11,157 ms, restoreFailures: []. settings.shadows: before true, why:"alreadyAsRequested" (the 0.9.18 gap explained: shadows were already on). settings.realView: before false, after false — the put returned OK and SOLIDWORKS left it off (0.9.19 still said changed:true, why:"applied"; 0.9.20 says setIgnored). zoomFactor: Scale2 0.176 → 0.352, the model twice as large — and the arm's tip clipped at the top edge. enumIds: swDisplayAmbientOcclusionShadows: 485, swDisplayShadowsInShadedMode: 131 |
- [measured] The image is a real render: RealView shading, a floor shadow, the scene's gradient background.
- [measured] PowerShell reflection over the installed swconst DLL resolved all
four preference ids (no
render_enum_unresolved). Measured on SOLIDWORKS 2026 SP3 (0.9.19'senumIds):swDisplayAmbientOcclusionShadows = 485,swDisplayShadowsInShadedMode = 131. The bridge still reads them from the installed DLL every time; these are the record, not a hard-coded table. - [measured] SaveBMP at 4K works with the window MINIMIZED, and 4K costs only ~1.2 s more than 1080p — ask for 3840×2160 for hero-grade output.
- [measured] The gap that led to
settings:shadows:trueappeared in neitherappliedSettingsnorrestoredSettings— already on, or never applied? 0.9.19 accounts for every requested setting (below). - [measured] Framing:
zoomToFitleaves this assembly at ~25% of the frame's width (the fit box is the whole assembly at the window's aspect, then exported 16:9). 0.9.19 addszoomFactor. - [measured]
zoomFactor> 1 zooms IN: 2.0 took Scale2 0.176 → 0.352 and drew the model twice as large — and OVERSHOT on the Moveo (the arm's tip clipped at the top edge). After a fit, 1.4–1.6 usually fills the frame without clipping; 2.0 clipped a tall assembly. - [measured] Shadows were already on in Drew's view (
alreadyAsRequested). - [measured] REALVIEW DID NOT TAKE on this laptop:
ViewDisplayRealViewput returned OK and the read-back stayed false. RealView needs a certified graphics card (this laptop has an RTX 4090 Laptop GPU, not on the certified list) and may also be unavailable while the window is minimized. The image was rendered shaded with shadows and ambient occlusion. Since 0.9.20 every set is read back: a set SOLIDWORKS ignored iswhy:"setIgnored",changed:false,restored:null, absent fromappliedSettings, and the reply'snotes[]carries a sentence saying so. The bridge changes no machine-wide setting to force RealView on — that would be a standing change on the user's machine. - [unmeasured] flicker or resizing with the window VISIBLE; the largest size
(8192×4608); a
backgroundchange (not passed in the live runs); RealView with the window visible.
settings — every requested setting, accounted for (0.9.19)
"settings": {
"<name>": {
"requested": <what was asked: true | "isometric" | "shaded" | "white" | 2.5 …>,
"before": <its value before the render, or null if it could not be read>,
"after": <its value after applying, before the export>,
"changed": true | false,
"restored": true | false | null, // null when nothing was changed
"why": "applied" | "alreadyAsRequested" | "unreadable" | "setFailed" | "idUnresolved" | "setIgnored"
}, …
},
"notes": [ "<one sentence per setting SOLIDWORKS ignored>" ]
setIgnored (0.9.20): the set call returned OK but the read-back right after
was not the requested value — nothing changed, so nothing is restored
(changed:false, restored:null) and it is never listed as applied. RealView's
note is fixed text: "RealView was requested but SOLIDWORKS left it off — RealView
needs a certified graphics card (this laptop has an RTX 4090 Laptop GPU, not on
the certified list) and may also be unavailable while the window is minimized;
the image was rendered shaded with shadows and ambient occlusion."
Names: view, displayStyle, perspective, realView, ambientOcclusion,
shadows, background, zoomToFit, zoomFactor — one row for each one the
caller asked for, and only those.
Track A — swx_render_image (0.9.18; zoomFactor and settings 0.9.19)
swx_render_image {reason, path?, width?, height?,
view?: "current"|"isometric"|"front"|"back"|"left"|"right"|"top"|"bottom"|"trimetric"|"dimetric",
displayStyle?: "shaded"|"shadedWithEdges"|"hiddenLinesRemoved"|"wireframe",
perspective?, realView?, ambientOcclusion?, shadows?: bool,
background?: "current"|"white"|"black"|"transparent", zoomToFit?: bool,
zoomFactor?: number (0.1–20, default 1.0; multiplies the view scale AFTER any fit)}
→ {path, bytes, width, height (read back from the PNG header), requested, capped,
settings, appliedSettings, restoredSettings, restoreFailures, restoreIncomplete,
enumIds, durationMs}
What it does, in order, all against the ACTIVE document:
- Validates: a
reason; 16–8192 px per side (default 1920×1080);pathabsolute, ending.png, its folder EXISTING (never created — omitpathfor<data root>\exports\<doc>-<view>-<w>x<h>-<ts>.png), and not an existing file.background:"transparent"is refusedrender_option_unsupported: the export has no alpha channel. - Captures every setting it is asked to change, then applies it (only what differs). Calls and enums — each from the official API help:
| Setting | Call | Values |
|---|---|---|
| view | IModelDoc2::ShowNamedView2("", id) help |
swStandardViews_e: front 1, back 2, left 3, right 4, top 5, bottom 6, isometric 7, trimetric 8, dimetric 9 help |
| displayStyle | IModelView::DisplayMode get/put help |
swViewDisplayMode_e: wireframe 1, hiddenLinesRemoved 2, shaded 4, shadedWithEdges 5 help |
| perspective | IModelView::HasPerspective / AddPerspective / RemovePerspective help |
bool |
| realView | IModelDocExtension::ViewDisplayRealView get/put help |
bool |
| shadows | ISldWorks::Get/SetUserPreferenceToggle(swDisplayShadowsInShadedMode) — a SYSTEM setting example |
bool |
| ambientOcclusion | ISldWorks::Get/SetUserPreferenceToggle(swDisplayAmbientOcclusionShadows) enum — its scope (system vs document) [unmeasured] |
bool |
| background | ISldWorks::Get/SetUserPreferenceIntegerValue(swColorsBackgroundAppearance) → Plain (0) help, and (swSystemColorsViewportBackground) → COLORREF |
white 0xFFFFFF, black 0 |
| zoomToFit | IModelDoc2::ViewZoomtofit2 help |
— |
| camera (restored) | IModelView::Orientation3, Translation3, Scale2 get/put |
MathTransform, MathVector, double |
The swUserPreference*_e NUMBERS are not on the help pages. The bridge never
guesses one: it reads them by reflection from the installed
SolidWorks.Interop.swconst.dll beside SLDWORKS.exe
(ISldWorks::GetExecutablePath), the way the 3D Interconnect ids were read on
2026-09-17, and a render that needs one it cannot read is refused
render_enum_unresolved before anything changes.
3. Exports with IModelDoc2::SaveBMP(path, width, height) — "If WidthIn or the
HeightIn is less than or equal to 0, then the view size is based on the
current window size" help.
Why not "Save As PNG" with print capture: the export options
swTiffScreenOrPrintCapture (0 screen, 1 print), swTiffPrintDPI,
swTiffPrintPaperSize, swTiffPrintDrawingPaperWidth/Height and
swTiffPrintScaleToFit are documented "For drawings only"
(System Options > Export > TIF/PSD/JPG/PNG),
so for a part or assembly only SaveBMP takes a pixel size. They are not
touched.
4. Restores, newest first, on EVERY path (the error path too), reads each one
back, and lists it in restoredSettings (value = what it was, readBack,
restored). A restore that did not read back is restoreIncomplete:true
with restoreFailures. The camera is put back last. The document is never
saved.
5. Converts the BMP to a PNG itself (the BMP is deleted), writes it, and
VERIFIES BY EFFECT: the file exists, starts with the PNG signature, and its
IHDR width × height are the reply's width/height. If they differ from the
request, capped:true — the export honoured only the window size.
Guards: the readiness gate (it is a COM verb); the user-presence guard when the
request changes anything on screen (a view, a style, RealView, AO, shadows,
perspective, a background, a zoom) — exactly like a sweep, user_is_active
with the evidence. A render of the CURRENT view with nothing changed is NOT
presence-guarded: it changes nothing the user sees. [unmeasured] whether SaveBMP
at a size larger than the window flickers or resizes the viewport while it
renders — the first live run must watch for it, and if it does, that case moves
under the guard too.
Budget: ab waits 600 s (bridge.json timeouts.verbs.render_image); the
render's host call is bounded by the sweep ceiling (540 s). swx_progress
shows the stage.
Track A — what the 2026-10-05 run answered, and what is still open
Answered: 1 (4K honoured, ~11 s, shadow/gradient visible; RealView did NOT take
— uncertified GPU, setIgnored since 0.9.20), 2 (every setting restored), 3
(ids read; 485 / 131 on 2026 SP3), 4 (GetExecutablePath worked, by implication:
the DLL was found), zoomFactor's direction (>1 zooms in; 1.4–1.6 after a fit).
Still open: 5 (visible-window flicker), 6 (8192×4608), a background change, and
the AO setting's scope.
Track A — the original measure-first list
swx_render_image {width:3840, height:2160, view:"isometric", realView:true, ambientOcclusion:true, shadows:true, perspective:true, background:"white", zoomToFit:true, reason}on the Moveo assembly: did SaveBMP honour 3840×2160 (capped:false)? How long (durationMs)? Does the image show RealView, AO and shadows, or does SaveBMP render a plainer pipeline than the screen?- Did every setting read back restored (
restoreIncomplete:false)? Compare the viewport before and after by eye (andswx_screenshot). - Were the swconst ids read (no
render_enum_unresolved)? Record the four ids. IsswDisplayAmbientOcclusionShadowsa system or a document setting? - Does
GetExecutablePathreturn the folder holding SLDWORKS.exe and the swconst DLL? - Did the window flicker or resize during a larger-than-window SaveBMP?
- 8192×4608 — the largest size SaveBMP will produce on this GPU.
Starting Visualize — MEASURED 2026-10-05, built in 0.9.19
- [measured] Starting
SLDWORKSVisualize.exeDIRECTLY is wrong on this edition: the next start raised a#32770titled "SOLIDWORKS Visualize": "SOLIDWORKS Visualize must be opened from the 3DEXPERIENCE Platform or from the desktop shortcut created from the Platform. Do you want to go to the 3DEXPERIENCE Platform?" — Yes / No (No = automationIdCommandButton_7; No exits the process). The coordinator answered it once, on Drew's explicit "deal with this"; the bridge never does. - [measured] The right way is the PLATFORM SHORTCUT, the same form as SOLIDWORKS
Design's:
C:\Users\Public\Desktop\SOLIDWORKS Visualize.lnkor%ProgramData%\Microsoft\Windows\Start Menu\Programs\Dassault Systemes SOLIDWORKS 3DEXPERIENCE R2026x\SOLIDWORKS Visualize.lnk→CATSTART.exe -run "SWXDesktopLauncher.exe" -object "--AppName=\"SWXCVIZ_AP\" -tenant=… -monoapp -3DRegistryURL=…" -nowindow(SOLIDWORKS Design:SWXCSWK_AP). With SOLIDWORKS already signed in, no login appeared; after 45 s:SLDWORKSVisualize(main window classHwndWrapper[SLDWORKSVisualize.exe;Main Application;<guid>], title "SOLIDWORKS Visualize"),SWVisualize.Exchange.PluginHost,SWVisualize.Queue.Server(already running before the launch). - [measured] FIRST RUN: a WPF dialog titled "SOLIDWORKS Visualize": "Please
choose a location for your 'SOLIDWORKS Visualize Content' folder. This folder
will be created to provide a place for this software to store data." — an edit
prefilled
C:\Users\drew\Documents, "…", "Continue". It creates a folder on the user's machine, a standing change: only the user answers it. - [measured] the WPF dialog CAN be read: hosted 0.9.19's
swx_status.visualizeread it through thedesktop_ui_treefallback —waitingOn: "userVisualizeContentFolder", its text, andprefilledPath: "C:/Users/drew/Documents". UIA gives that path with FORWARD slashes (the dialog draws backslashes); the bridge reports it as UIA gave it and does not normalise. On first run the dialog IS the main window (same hwnd, classHwndWrapper[SLDWORKSVisualize.exe;Main Application;…]); 0.9.19 saidhwnd:nullbesidedialog.hwnd, 0.9.20 reports the top-levelhwndwhenever the process has that window, dialog or not. - [unmeasured] whether the shortcut accepts a model path; how to quit Visualize.
0.9.19: swx_start {app:"visualize", reason, waitSeconds?} finds the
platform shortcut (SWX_VISUALIZE_SHORTCUT overrides; only a .lnk named
"SOLIDWORKS Visualize", never the executable), invokes it the same way
SOLIDWORKS's is invoked, and waits up to waitSeconds (20) for the HwndWrapper
main window or a dialog. Readiness = the main window exists and no dialog is
waiting. The three dialogs are classified BY THEIR WORDS and never answered:
the platform notice → visualize_direct_start_refused (the fix: start through
the platform shortcut); the content folder → waitingOn: "userVisualizeContentFolder" with the text and the prefilled path; a
3DEXPERIENCE login → waitingOn:"userSignIn", answered only by
swx_sign_in {userAuthorized:true, window:"visualize"} on the user's say-so.
swx_status.visualize = {running, pid, hwnd, ready, waitingOn, dialog, companions}. A path is not passed (unmeasured). No quit is built — it is the
next measurement.
Track B — SOLIDWORKS Visualize render (DESIGN ONLY, no verb)
Parked: the main window cannot be measured until the user answers the content-folder dialog on Drew's machine.
Visualize renders physically (Fast / Accurate modes, a render queue). It has no API on disk [measured], so the bridge would drive it through UI Automation:
- Launch through the platform shortcut —
swx_start {app:"visualize"}(0.9.19). [measured] the executable takes a model path, but a direct start is refused on this edition; whether the shortcut passes a path on is [unmeasured]. - Answer its 3DEXPERIENCE sign-in with
swx_sign_in {userAuthorized:true, window:"visualize"}[the sign-in path exists; the Visualize host's login was measured on 2026-10-02]. - Wait for the import to finish.
- In the Output Tools panel: output size, render mode (Fast / Accurate), passes or time limit, output folder and file name.
- Start the render; poll the OUTPUT FILE (exists, size stable, PNG header) — verification by effect, never by a progress bar alone.
- Close Visualize (or leave it, on the user's say-so).
Track B — MEASURE FIRST (exactly what to capture live, nothing assumed)
- The main window: class name and title pattern, and whether its accessibility tree is lazy (the login page's was).
- How "import finished" shows: a status text, a progress control's disappearance, the model in the scene tree — its role, name, automationId.
- The Output Tools panel: how it is opened (button name / automationId), and
each control: width, height, aspect lock, render mode (Fast / Accurate), passes
/ time limit, output folder, file name, format — role, name, automationId,
settable/invokable, and whether a background ValuePattern set works or real keystrokes are needed (the login page refused a background set). - The render ("Start Render") button: name, automationId,
invokable. - How completion shows: a dialog, a status text, the render queue entry — and whether the file appears only at the end (so polling the file is enough).
- Whether a second render can be queued while one runs.
- Whether Visualize keeps its own camera / environment per project, and where the project file goes (so the bridge never writes over the user's).
# Rendering — what the bridge can draw, and what it still has to measure
Drew, 2026-10-02: *"Does SW have rendering like fusion so we can get a really
gorgeous shot of this assembly?"* — then *"go ahead and try it… and if it works,
let's add a bunch of intel into the bridge to handle rendering."* The Fusion
bridge has no render verb at all (`docs/FUSION-PARITY-REPORT.md`), so this is
new ground.
Every line here is **[measured]** (seen on Drew's laptop) or **[unmeasured]**
(written from the API documentation; not yet run live). Track A was MEASURED
LIVE on 2026-10-05 (below); what is still unmeasured is named.
## The facts this is built on
- [measured] PhotoView 360 is ABSENT on this edition (3DEXPERIENCE SOLIDWORKS
for Makers 2026). The renderer is the viewport itself: RealView, ambient
occlusion, shadows and perspective, on an RTX 4090 Laptop GPU.
- [measured] `swx_show_assembly` + `ViewZoomtofit2` work live on the Moveo
assembly (`C:\Users\Public\adom-hero\BCN3D-Moveo-master\CAD files\BCN3D Moveo
assembly.SLDASM`, 110 documents, read-only) — the test subject.
- [measured] `swx_screenshot` (ab's PrintWindow by handle) works, but it is a
screen grab capped at the window, about 1568 px wide — not an export.
- [measured] SOLIDWORKS Visualize 2026 is installed at
`…\SOLIDWORKS 3DEXPERIENCE R2026x\Visualize\SLDWORKSVisualize.exe`, takes a
model path as its argument, ships no scripting interface on disk, and raises
its OWN 3DEXPERIENCE sign-in.
## Track A — MEASURED 2026-10-05
On adom_drew2, hosted 0.9.18, SOLIDWORKS 2026 SP3 (Makers), the Moveo assembly
(110 documents, read-only), the SOLIDWORKS window MINIMIZED throughout:
| Request | Result |
|---|---|
| `{width:1920, height:1080}` | ok, 411,368 bytes, PNG header 1920×1080, `capped:false`, nothing applied or restored, 10,403 ms |
| `{width:3840, height:2160, view:"isometric", displayStyle:"shaded", perspective:true, realView:true, ambientOcclusion:true, shadows:true, zoomToFit:true}` | ok, 979,997 bytes, PNG header 3840×2160, `capped:false`, 11,597 ms. Applied: ambientOcclusion false→true, displayMode 5→4, orientation isometric, perspective false→true, realView false→true, zoom fit. Restored: every one read back equal to its old value; camera captured and restored; `restoreFailures: []` |
| hosted 0.9.19, the same plus `zoomFactor:2.0` | ok, 932,312 bytes, 3840×2160, 11,157 ms, `restoreFailures: []`. `settings.shadows`: before true, `why:"alreadyAsRequested"` (the 0.9.18 gap explained: shadows were already on). `settings.realView`: before false, after **false** — the put returned OK and SOLIDWORKS left it off (0.9.19 still said `changed:true, why:"applied"`; 0.9.20 says `setIgnored`). `zoomFactor`: Scale2 0.176 → 0.352, the model twice as large — and the arm's tip clipped at the top edge. `enumIds`: `swDisplayAmbientOcclusionShadows: 485`, `swDisplayShadowsInShadedMode: 131` |
- [measured] The image is a real render: RealView shading, a floor shadow, the
scene's gradient background.
- [measured] PowerShell reflection over the installed swconst DLL resolved all
four preference ids (no `render_enum_unresolved`). Measured on SOLIDWORKS 2026
SP3 (0.9.19's `enumIds`): `swDisplayAmbientOcclusionShadows = 485`,
`swDisplayShadowsInShadedMode = 131`. The bridge still reads them from the
installed DLL every time; these are the record, not a hard-coded table.
- [measured] SaveBMP at 4K works with the window MINIMIZED, and 4K costs only
~1.2 s more than 1080p — ask for 3840×2160 for hero-grade output.
- [measured] The gap that led to `settings`: `shadows:true` appeared in neither
`appliedSettings` nor `restoredSettings` — already on, or never applied?
0.9.19 accounts for every requested setting (below).
- [measured] Framing: `zoomToFit` leaves this assembly at ~25% of the frame's
width (the fit box is the whole assembly at the window's aspect, then exported
16:9). 0.9.19 adds `zoomFactor`.
- [measured] `zoomFactor` > 1 zooms IN: 2.0 took Scale2 0.176 → 0.352 and drew
the model twice as large — and OVERSHOT on the Moveo (the arm's tip clipped at
the top edge). After a fit, 1.4–1.6 usually fills the frame without clipping;
2.0 clipped a tall assembly.
- [measured] Shadows were already on in Drew's view (`alreadyAsRequested`).
- [measured] REALVIEW DID NOT TAKE on this laptop: `ViewDisplayRealView` put
returned OK and the read-back stayed false. RealView needs a certified
graphics card (this laptop has an RTX 4090 Laptop GPU, not on the certified
list) and may also be unavailable while the window is minimized. The image was
rendered shaded with shadows and ambient occlusion. Since 0.9.20 every set is
read back: a set SOLIDWORKS ignored is `why:"setIgnored"`, `changed:false`,
`restored:null`, absent from `appliedSettings`, and the reply's `notes[]`
carries a sentence saying so. The bridge changes no machine-wide setting to
force RealView on — that would be a standing change on the user's machine.
- [unmeasured] flicker or resizing with the window VISIBLE; the largest size
(8192×4608); a `background` change (not passed in the live runs); RealView
with the window visible.
### `settings` — every requested setting, accounted for (0.9.19)
```
"settings": {
"<name>": {
"requested": <what was asked: true | "isometric" | "shaded" | "white" | 2.5 …>,
"before": <its value before the render, or null if it could not be read>,
"after": <its value after applying, before the export>,
"changed": true | false,
"restored": true | false | null, // null when nothing was changed
"why": "applied" | "alreadyAsRequested" | "unreadable" | "setFailed" | "idUnresolved" | "setIgnored"
}, …
},
"notes": [ "<one sentence per setting SOLIDWORKS ignored>" ]
```
`setIgnored` (0.9.20): the set call returned OK but the read-back right after
was not the requested value — nothing changed, so nothing is restored
(`changed:false, restored:null`) and it is never listed as applied. RealView's
note is fixed text: "RealView was requested but SOLIDWORKS left it off — RealView
needs a certified graphics card (this laptop has an RTX 4090 Laptop GPU, not on
the certified list) and may also be unavailable while the window is minimized;
the image was rendered shaded with shadows and ambient occlusion."
Names: `view`, `displayStyle`, `perspective`, `realView`, `ambientOcclusion`,
`shadows`, `background`, `zoomToFit`, `zoomFactor` — one row for each one the
caller asked for, and only those.
## Track A — `swx_render_image` (0.9.18; zoomFactor and settings 0.9.19)
```
swx_render_image {reason, path?, width?, height?,
view?: "current"|"isometric"|"front"|"back"|"left"|"right"|"top"|"bottom"|"trimetric"|"dimetric",
displayStyle?: "shaded"|"shadedWithEdges"|"hiddenLinesRemoved"|"wireframe",
perspective?, realView?, ambientOcclusion?, shadows?: bool,
background?: "current"|"white"|"black"|"transparent", zoomToFit?: bool,
zoomFactor?: number (0.1–20, default 1.0; multiplies the view scale AFTER any fit)}
→ {path, bytes, width, height (read back from the PNG header), requested, capped,
settings, appliedSettings, restoredSettings, restoreFailures, restoreIncomplete,
enumIds, durationMs}
```
What it does, in order, all against the ACTIVE document:
1. Validates: a `reason`; 16–8192 px per side (default 1920×1080); `path`
absolute, ending `.png`, its folder EXISTING (never created — omit `path` for
`<data root>\exports\<doc>-<view>-<w>x<h>-<ts>.png`), and not an existing
file. `background:"transparent"` is refused `render_option_unsupported`:
the export has no alpha channel.
2. Captures every setting it is asked to change, then applies it (only what
differs). Calls and enums — each from the official API help:
| Setting | Call | Values |
|---|---|---|
| view | `IModelDoc2::ShowNamedView2("", id)` [help](https://help.solidworks.com/2024/english/api/sldworksapi/SOLIDWORKS.Interop.sldworks~SOLIDWORKS.Interop.sldworks.IModelDoc2~ShowNamedView2.html) | `swStandardViews_e`: front 1, back 2, left 3, right 4, top 5, bottom 6, isometric 7, trimetric 8, dimetric 9 [help](https://help.solidworks.com/2024/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swStandardViews_e.html) |
| displayStyle | `IModelView::DisplayMode` get/put [help](https://help.solidworks.com/2024/english/api/sldworksapi/SOLIDWORKS.Interop.sldworks~SOLIDWORKS.Interop.sldworks.IModelView~DisplayMode.html) | `swViewDisplayMode_e`: wireframe 1, hiddenLinesRemoved 2, shaded 4, shadedWithEdges 5 [help](https://help.solidworks.com/2024/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swViewDisplayMode_e.html) |
| perspective | `IModelView::HasPerspective` / `AddPerspective` / `RemovePerspective` [help](https://help.solidworks.com/2024/english/api/sldworksapi/SOLIDWORKS.Interop.sldworks~SOLIDWORKS.Interop.sldworks.IModelView~HasPerspective.html) | bool |
| realView | `IModelDocExtension::ViewDisplayRealView` get/put [help](https://help.solidworks.com/2017/english/api/sldworksapi/solidworks.interop.sldworks~solidworks.interop.sldworks.imodeldocextension~viewdisplayrealview.html) | bool |
| shadows | `ISldWorks::Get/SetUserPreferenceToggle(swDisplayShadowsInShadedMode)` — a SYSTEM setting [example](https://help.solidworks.com/2016/english/api/sldworksapi/Display_Shadows_in_Shaded_Mode_Example_CPlusPlus_COM.htm) | bool |
| ambientOcclusion | `ISldWorks::Get/SetUserPreferenceToggle(swDisplayAmbientOcclusionShadows)` [enum](https://help.solidworks.com/2020/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swUserPreferenceToggle_e.html) — its scope (system vs document) [unmeasured] | bool |
| background | `ISldWorks::Get/SetUserPreferenceIntegerValue(swColorsBackgroundAppearance)` → Plain (0) [help](https://help.solidworks.com/2024/english/api/swconst/SOLIDWORKS.Interop.swconst~SOLIDWORKS.Interop.swconst.swColorsBackgroundAppearance_e.html), and `(swSystemColorsViewportBackground)` → COLORREF | white 0xFFFFFF, black 0 |
| zoomToFit | `IModelDoc2::ViewZoomtofit2` [help](https://help.solidworks.com/2024/english/api/sldworksapi/SOLIDWORKS.Interop.sldworks~SOLIDWORKS.Interop.sldworks.IModelDoc2~ViewZoomtofit2.html) | — |
| camera (restored) | `IModelView::Orientation3`, `Translation3`, `Scale2` get/put | MathTransform, MathVector, double |
The `swUserPreference*_e` NUMBERS are not on the help pages. The bridge never
guesses one: it reads them by reflection from the installed
`SolidWorks.Interop.swconst.dll` beside SLDWORKS.exe
(`ISldWorks::GetExecutablePath`), the way the 3D Interconnect ids were read on
2026-09-17, and a render that needs one it cannot read is refused
`render_enum_unresolved` before anything changes.
3. Exports with `IModelDoc2::SaveBMP(path, width, height)` — "If WidthIn or the
HeightIn is less than or equal to 0, then the view size is based on the
current window size" [help](https://help.solidworks.com/2024/english/api/sldworksapi/SOLIDWORKS.Interop.sldworks~SOLIDWORKS.Interop.sldworks.IModelDoc2~SaveBMP.html).
Why not "Save As PNG" with print capture: the export options
`swTiffScreenOrPrintCapture` (0 screen, 1 print), `swTiffPrintDPI`,
`swTiffPrintPaperSize`, `swTiffPrintDrawingPaperWidth/Height` and
`swTiffPrintScaleToFit` are documented "For drawings only"
([System Options > Export > TIF/PSD/JPG/PNG](https://help.solidworks.com/2017/english/api/swconst/filesaveastifpsdoptions.htm)),
so for a part or assembly only SaveBMP takes a pixel size. They are not
touched.
4. Restores, newest first, on EVERY path (the error path too), reads each one
back, and lists it in `restoredSettings` (`value` = what it was, `readBack`,
`restored`). A restore that did not read back is `restoreIncomplete:true`
with `restoreFailures`. The camera is put back last. The document is never
saved.
5. Converts the BMP to a PNG itself (the BMP is deleted), writes it, and
VERIFIES BY EFFECT: the file exists, starts with the PNG signature, and its
IHDR width × height are the reply's `width`/`height`. If they differ from the
request, `capped:true` — the export honoured only the window size.
Guards: the readiness gate (it is a COM verb); the user-presence guard when the
request changes anything on screen (a view, a style, RealView, AO, shadows,
perspective, a background, a zoom) — exactly like a sweep, `user_is_active`
with the evidence. A render of the CURRENT view with nothing changed is NOT
presence-guarded: it changes nothing the user sees. [unmeasured] whether SaveBMP
at a size larger than the window flickers or resizes the viewport while it
renders — the first live run must watch for it, and if it does, that case moves
under the guard too.
Budget: ab waits 600 s (`bridge.json` `timeouts.verbs.render_image`); the
render's host call is bounded by the sweep ceiling (540 s). `swx_progress`
shows the stage.
### Track A — what the 2026-10-05 run answered, and what is still open
Answered: 1 (4K honoured, ~11 s, shadow/gradient visible; RealView did NOT take
— uncertified GPU, `setIgnored` since 0.9.20), 2 (every setting restored), 3
(ids read; 485 / 131 on 2026 SP3), 4 (GetExecutablePath worked, by implication:
the DLL was found), `zoomFactor`'s direction (>1 zooms in; 1.4–1.6 after a fit).
Still open: 5 (visible-window flicker), 6 (8192×4608), a background change, and
the AO setting's scope.
### Track A — the original measure-first list
1. `swx_render_image {width:3840, height:2160, view:"isometric", realView:true,
ambientOcclusion:true, shadows:true, perspective:true, background:"white",
zoomToFit:true, reason}` on the Moveo assembly: did SaveBMP honour 3840×2160
(`capped:false`)? How long (`durationMs`)? Does the image show RealView, AO and
shadows, or does SaveBMP render a plainer pipeline than the screen?
2. Did every setting read back restored (`restoreIncomplete:false`)? Compare the
viewport before and after by eye (and `swx_screenshot`).
3. Were the swconst ids read (no `render_enum_unresolved`)? Record the four ids.
Is `swDisplayAmbientOcclusionShadows` a system or a document setting?
4. Does `GetExecutablePath` return the folder holding SLDWORKS.exe and the
swconst DLL?
5. Did the window flicker or resize during a larger-than-window SaveBMP?
6. 8192×4608 — the largest size SaveBMP will produce on this GPU.
## Starting Visualize — MEASURED 2026-10-05, built in 0.9.19
- [measured] Starting `SLDWORKSVisualize.exe` DIRECTLY is wrong on this edition:
the next start raised a `#32770` titled "SOLIDWORKS Visualize": "SOLIDWORKS
Visualize must be opened from the 3DEXPERIENCE Platform or from the desktop
shortcut created from the Platform. Do you want to go to the 3DEXPERIENCE
Platform?" — Yes / No (No = automationId `CommandButton_7`; No exits the
process). The coordinator answered it once, on Drew's explicit "deal with
this"; the bridge never does.
- [measured] The right way is the PLATFORM SHORTCUT, the same form as SOLIDWORKS
Design's: `C:\Users\Public\Desktop\SOLIDWORKS Visualize.lnk` or
`%ProgramData%\Microsoft\Windows\Start Menu\Programs\Dassault Systemes
SOLIDWORKS 3DEXPERIENCE R2026x\SOLIDWORKS Visualize.lnk` → `CATSTART.exe -run
"SWXDesktopLauncher.exe" -object "--AppName=\"SWXCVIZ_AP\" -tenant=… -monoapp
-3DRegistryURL=…" -nowindow` (SOLIDWORKS Design: `SWXCSWK_AP`). With SOLIDWORKS
already signed in, no login appeared; after 45 s: `SLDWORKSVisualize` (main
window class `HwndWrapper[SLDWORKSVisualize.exe;Main Application;<guid>]`,
title "SOLIDWORKS Visualize"), `SWVisualize.Exchange.PluginHost`,
`SWVisualize.Queue.Server` (already running before the launch).
- [measured] FIRST RUN: a WPF dialog titled "SOLIDWORKS Visualize": "Please
choose a location for your 'SOLIDWORKS Visualize Content' folder. This folder
will be created to provide a place for this software to store data." — an edit
prefilled `C:\Users\drew\Documents`, "…", "Continue". It creates a folder on
the user's machine, a standing change: only the user answers it.
- [measured] the WPF dialog CAN be read: hosted 0.9.19's `swx_status.visualize`
read it through the `desktop_ui_tree` fallback — `waitingOn:
"userVisualizeContentFolder"`, its text, and `prefilledPath:
"C:/Users/drew/Documents"`. UIA gives that path with FORWARD slashes (the
dialog draws backslashes); the bridge reports it as UIA gave it and does not
normalise. On first run the dialog IS the main window (same hwnd, class
`HwndWrapper[SLDWORKSVisualize.exe;Main Application;…]`); 0.9.19 said
`hwnd:null` beside `dialog.hwnd`, 0.9.20 reports the top-level `hwnd` whenever
the process has that window, dialog or not.
- [unmeasured] whether the shortcut accepts a model path; how to quit Visualize.
**0.9.19:** `swx_start {app:"visualize", reason, waitSeconds?}` finds the
platform shortcut (`SWX_VISUALIZE_SHORTCUT` overrides; only a `.lnk` named
"SOLIDWORKS Visualize", never the executable), invokes it the same way
SOLIDWORKS's is invoked, and waits up to `waitSeconds` (20) for the HwndWrapper
main window or a dialog. Readiness = the main window exists and no dialog is
waiting. The three dialogs are classified BY THEIR WORDS and never answered:
the platform notice → `visualize_direct_start_refused` (the fix: start through
the platform shortcut); the content folder → `waitingOn:
"userVisualizeContentFolder"` with the text and the prefilled path; a
3DEXPERIENCE login → `waitingOn:"userSignIn"`, answered only by
`swx_sign_in {userAuthorized:true, window:"visualize"}` on the user's say-so.
`swx_status.visualize` = `{running, pid, hwnd, ready, waitingOn, dialog,
companions}`. A `path` is not passed (unmeasured). No quit is built — it is the
next measurement.
## Track B — SOLIDWORKS Visualize render (DESIGN ONLY, no verb)
Parked: the main window cannot be measured until the user answers the
content-folder dialog on Drew's machine.
Visualize renders physically (Fast / Accurate modes, a render queue). It has no
API on disk [measured], so the bridge would drive it through UI Automation:
1. Launch through the platform shortcut — `swx_start {app:"visualize"}`
(0.9.19). [measured] the executable takes a model path, but a direct start
is refused on this edition; whether the shortcut passes a path on is
[unmeasured].
2. Answer its 3DEXPERIENCE sign-in with `swx_sign_in {userAuthorized:true,
window:"visualize"}` [the sign-in path exists; the Visualize host's login was
measured on 2026-10-02].
3. Wait for the import to finish.
4. In the Output Tools panel: output size, render mode (Fast / Accurate),
passes or time limit, output folder and file name.
5. Start the render; poll the OUTPUT FILE (exists, size stable, PNG header) —
verification by effect, never by a progress bar alone.
6. Close Visualize (or leave it, on the user's say-so).
### Track B — MEASURE FIRST (exactly what to capture live, nothing assumed)
- The main window: class name and title pattern, and whether its accessibility
tree is lazy (the login page's was).
- How "import finished" shows: a status text, a progress control's disappearance,
the model in the scene tree — its role, name, automationId.
- The Output Tools panel: how it is opened (button name / automationId), and
each control: width, height, aspect lock, render mode (Fast / Accurate), passes
/ time limit, output folder, file name, format — role, name, automationId,
`settable` / `invokable`, and whether a background ValuePattern set works or
real keystrokes are needed (the login page refused a background set).
- The render ("Start Render") button: name, automationId, `invokable`.
- How completion shows: a dialog, a status text, the render queue entry — and
whether the file appears only at the end (so polling the file is enough).
- Whether a second render can be queued while one runs.
- Whether Visualize keeps its own camera / environment per project, and where
the project file goes (so the bridge never writes over the user's).