Give Download the Explorer folder dialog instead of the old tree - #2
Closed
skfd wants to merge 4 commits into
Closed
Give Download the Explorer folder dialog instead of the old tree#2skfd wants to merge 4 commits into
skfd wants to merge 4 commits into
Conversation
FolderBrowserDialog on .NET Framework is still the SHBrowseForFolder tree: no path bar, no search, no typing or pasting a path. There is no AutoUpgradeEnabled to set on net4x, so the Explorer dialog has to be asked for directly through IFileOpenDialog with FOS_PICKFOLDERS. RootFolder = MyComputer made it worse by rooting the tree at This PC, so every download started the walk from the top. Download was the only place left on the old dialog; the three upload paths already use OpenFileDialog, which is the modern dialog on net4x anyway. FolderPicker falls back to FolderBrowserDialog if the shell call fails, so nothing is lost where the COM dialog is unavailable. It also reopens on the folder used for the last download, and the dialog is now disposed, which the old code never did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
build.ps1 and xtb.ps1 mirror the other xrm-* tools, so this fork is driven the same way: build.ps1 drops the dll into the XrmToolBox in Downloads, xtb.ps1 brings up a throwaway XrmToolBox holding nothing but this tool, pointed at the active pac organization. Two things had to differ, because this is the non-SDK, packages.config project inherited from upstream rather than a project written here. dotnet build cannot compile it at all -- the .resx files hold images, and the SDK build refuses those unless the project takes on a System.Resources.Extensions dependency upstream does not have -- so build.ps1 uses the full MSBuild and hands the result to Start-XtbSandbox as -DllPath -NoBuild. And the dll lands straight in bin\Debug with no target framework folder, which -DllPath has to spell out. Retargeted to v4.8 because the 4.7 targeting pack is no longer installable and nothing here needs 4.7; XrmToolBox itself is built against 4.6.2. test_doc.docx is the one from the X-Ray tool, put on the clipboard at launch because uploading needs a local .docx and that is the thing you always hunt for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The download path could not be shown working at all: the test organization has no document templates, so the grid is empty and Download stays disabled. seed.ps1 creates six against tables the organization actually has, and takes the names from the tables so the grid reads like a real system rather than "test 1, 2, 3". Three things about that were not guessable. associatedentitytypecode reads like an integer type code but is a string holding the table's logical name. Setting it is not enough either, because the server takes the association from the template content's customXml and overwrites the attribute from that, so seed.ps1 rebinds the customXml of test_doc.docx per table rather than uploading it unchanged -- otherwise every record lands as "none" with no formatted value, and the tool throws "Unable to load formatted value for associatedentitytypecode" and takes XrmToolBox down with it. And the record has to be built in C#, because assigning through Entity's indexer from PowerShell stores a PSObject the WCF serializer then refuses. dialog-shots.ps1 opens each dialog directly instead of driving XrmToolBox: the old five lines for the before, FolderPicker out of the built assembly for the after. It is also the one place the two PrintWindow flags are documented -- the modern dialog needs PW_RENDERFULLCONTENT and comes out blank without it, while the old dialog's tree is a child window that only appears under flag 0. ui.ps1 photographs the grid. It is left in as the only way to see the seeded data in the tool, but it is not reliable, and its header says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR modernizes the Download destination folder selection by replacing the legacy .NET Framework FolderBrowserDialog tree with an Explorer-style folder picker (IFileOpenDialog + FOS_PICKFOLDERS). It also includes local build/sandbox tooling and test scripts to seed data and capture UI/dialog screenshots.
Changes:
- Replace Download’s folder selection UI with an Explorer-style folder picker, reopening at the last-used download folder.
- Add
Helper/FolderPicker.cs(COM-based folder picker with legacy fallback) and wire it into the project. - Add local scripts for build/sandbox runs and for seeding + photographing UI/dialog behavior; update
.gitignorefor local artifacts.
Reviewed changes
Copilot reviewed 8 out of 13 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| DocTemplateManagerControl.cs | Switch Download destination selection to FolderPicker.Pick and remember last download folder. |
| Helper/FolderPicker.cs | New Explorer-style folder picker via IFileOpenDialog, with fallback to FolderBrowserDialog. |
| Futurez.Xrm.Tools.DocTemplateManager.csproj | Retarget to .NET Framework 4.8 and include the new FolderPicker compile item. |
| build.ps1 | New local build/deploy script using full MSBuild + nuget restore. |
| xtb.ps1 | New local script to build and launch a private XrmToolBox sandbox instance. |
| tests/seed.ps1 | New script to seed mock templates into an org for manual/E2E validation. |
| tests/ui.ps1 | New UIAutomation-based script to capture screenshots of the tool’s grid state. |
| tests/dialog-shots.ps1 | New script to capture “before vs after” folder dialog screenshots via PrintWindow. |
| .gitignore | Ignore local tooling artifacts (.xtb/, .claude/, .nuget-apikey). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+48
to
+52
| var hwnd = owner != null ? owner.Handle : IntPtr.Zero; | ||
| if (dialog.Show(hwnd) != 0) | ||
| { | ||
| return null; // cancelled | ||
| } |
Comment on lines
+41
to
+45
| object item; | ||
| if (SHCreateItemFromParsingName(start, IntPtr.Zero, typeof(IShellItem).GUID, out item) == 0) | ||
| { | ||
| dialog.SetFolder((IShellItem)item); | ||
| } |
| & $msbuild $solution /t:Build /p:Configuration=Debug /p:Platform="Any CPU" /v:minimal /nologo | ||
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | ||
|
|
||
| $pluginDir = "C:\Users\kk\Downloads\XrmToolbox\Plugins" |
| <RootNamespace>Futurez.Xrm.Tools</RootNamespace> | ||
| <AssemblyName>Futurez.Xrm.Tools.DocTemplateManager</AssemblyName> | ||
| <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> | ||
| <TargetFrameworkVersion>v4.8</TargetFrameworkVersion> |
Reproducing that crash needs a template whose associated table cannot be resolved, and the ordinary seeding path deliberately produces the opposite: it rebinds the content customXml to a table the organization has, so the association resolves. -Broken uploads test_doc.docx unrebound, still naming cr543_opportunity. That is what moving a template between organizations does, and it lands as 'none' with no formatted value, which is the state #1 is about. Run it against a build without that fix and XrmToolBox terminates. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review before any of this goes upstream. Only the first commit is meant for
jamesnovak/XrmDocumentTemplateManager; the other two are local tooling.
The change
PerformDownloadTemplatesopenedFolderBrowserDialogwithRootFolder = MyComputer.On .NET Framework that is still the SHBrowseForFolder tree -- no path bar, no search, no
typing or pasting a path -- and
MyComputerrooted it at This PC, so every download startedthe walk from the top. There is no
AutoUpgradeEnabledon net4x, so the Explorer dialog hasto be asked for directly through
IFileOpenDialogwithFOS_PICKFOLDERS.Download was the only place left on the old dialog. The three upload paths already use
OpenFileDialog, which is the modern dialog on net4x anyway.Helper/FolderPicker.csis ported from the Plugin Documenter tool, namespace change only.It falls back to
FolderBrowserDialogif the shell call fails, so nothing is lost where theCOM dialog is unavailable. It also reopens on the folder used for the last download, and the
dialog is now disposed, which the old code never did.
Before and after
Both in
docs/shots/, produced bytests/dialog-shots.ps1:dialog-before.pngdialog-after.pngThe "after" shot is
FolderPicker.Pickreflected out of the built assembly, so it is theshipping code rather than a mock-up.
Commits
82aa266Give Download the Explorer folder dialog instead of the old tree -- the fix.Self-contained and the only one that should go upstream. Touches
DocTemplateManagerControl.cs, addsHelper/FolderPicker.cs, one<Compile>entry.2e6dccfBuild and run the tool the way the sibling tools do --build.ps1andxtb.ps1, matching the other xrm-* tools. Local only.9e7ca4bSeed mock templates and photograph the two folder dialogs --tests/seed.ps1,tests/dialog-shots.ps1,tests/ui.ps1, the screenshots. Local only.Things worth a look while reviewing
v4.7tov4.8in2e6dccf. The 4.7 targeting pack is no longerinstallable, so the project would not build as it stood. Nothing here needs 4.7 and
XrmToolBox itself is built against 4.6.2 -- but it is a change to the project file, so it
should probably be left out of anything sent upstream.
dotnet buildcannot compile this project at all. The.resxfiles hold images andthe SDK build refuses them (MSB3823/MSB3822) unless the project takes on a
System.Resources.Extensionsdependency it does not have today.build.ps1uses the fullMSBuild instead, and
xtb.ps1hands the result toStart-XtbSandboxas-DllPath -NoBuild.That
-NoBuildswitch is now onmaininxrmtoolbox-sandbox
(
2232af7), but it has not been published to the PowerShell Gallery yet -- theinstalled module is still 0.1.0, so
xtb.ps1needs aPSModulePathpointing at that repountil a release goes out.
tests/ui.ps1is not reliable and its header says so. XrmToolBox rebuilds itsautomation tree while the tab opens, so elements go stale between being found and being
used. It is kept only because it is the one way to see the seeded data in the tool. The
dialog shots deliberately do not depend on it.
9e7ca4b.associatedentitytypecodeis a string holding the table's logical name despite the name,and setting it is not enough because the server derives the association from the template
content's customXml and overwrites the attribute from it.
Related
Found while testing this: #1, where a template whose associated table cannot be resolved
crashes XrmToolBox outright. Fixed separately in #3.