-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for IFileOpenDialog #5319
Conversation
7be57f3
to
c7e69fb
Compare
@kant2002 , how do we test these changes? |
@dreddy-work I assume some manual smoke test and writing more automated tests in separate PRs if needed. I would like to know what tests do you need to feel confident in the change? |
MAybe problem that we do not detect issue lies in the fact that tests do not create winforms/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/FileDialogTests.cs Line 701 in 94e03c4
|
List of cases which are not covered right now and which will fails at runtime.
In general I do not see any tests which exercise opening actual
I would like add these small tests somehere, but not sure what location best suited for that. |
In order to make writing tests morepleasant I add shortcuts for operations inside form That allow me express tests better then just counting tabs and pressing enter. This currently catches issue in dotnet#5319
83d1ad2
to
3381540
Compare
I do not get why Debug tests succeed. Release fails as expected in the new test which I add in #5344 |
|
Have you tried running tests locally under Release? |
Failure is expected, success is not. I rebase with test commit to test that we catch issue with prev implementation. I run under Debug locally and it fails, that's how I check that test catch what I want. Did not run under Release locally. |
This number reduce count of times the test succeed when it should fail. I assume this is because of WER doing it's job and process do not exit in time. Related dotnet#5319
@JeremyKuhne can you take a quick look at this change and share your feedback? |
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.FileOpenDialogWrapper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.ShellItemWrapper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.ShellItemWrapper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.ShellItemWrapper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.ShellItemWrapper.cs
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.FileOpenDialogWrapper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.FileOpenDialogWrapper.cs
Outdated
Show resolved
Hide resolved
@@ -14,5 +14,14 @@ internal static class IID | |||
|
|||
// 7BF80980-BF32-101A-8BBB-00AA00300CAB | |||
internal static Guid IPicture = new Guid(0x7BF80980, 0xBF32, 0x101A, 0x8B, 0xBB, 0x00, 0xAA, 0x00, 0x30, 0x0C, 0xAB); | |||
|
|||
// 43826D1E-E718-42EE-BC55-A1E261C37BFE | |||
internal static Guid IShellItem = new Guid(0x43826D1E, 0xE718, 0x42EE, 0xBC, 0x55, 0xA1, 0xE2, 0x61, 0xC3, 0x7B, 0xFE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change these to internal static Guid IShellItem { get } = new();
please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still haven't changed these to properties as requested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I change only these who I add in this PR, should I modify others too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you could apply the change to all of these - it'd be great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only IAccessible left, because it is used for ref Guid
parameters. I think that maybe changed in follow-up PR if needed.
We probably shouldn't be taking changes of this nature into v6 at this point. We'll discuss the best way to handle making progress for v7 as a team and come back with info. If you can clean up the local variable names and double check ref counting and allocations I'll take another look. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please clean up the local variable names and take a look at the other feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
if (hr == S_OK) | ||
{ | ||
Marshal.Release(externalComObject); | ||
return new ShellItemWrapper(shellItemComObject); | ||
} | ||
|
||
throw new NotImplementedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we not want to call Marshal.Release(externalComObject);
before throwing the exception?
Should we do this:
try
{
// if (..) return ...
}
finally
{
Marshal.Release(externalComObject);
}
throw new NotImplementedException();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should not do that. If we reach this path, that's mean something within WinForms pass to internal ComWrappers borked value. That should not happens. That means serious bug for me which should be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed we have a bug, we thrown and the app crashed... But would we not leak the COM object in this situation? I'm genuinely curious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can leak COM object if it is created out-of-process. That may happens only if we work with WebBrowser or DataObject probably. All of them are problematic even for this approach and better discuss that problem when we implement this parts.
What if COM object would be passed by the user(this is how I think we end-up in this hypotetical scenario) if we release his object during exception(our bug) he maybe unhappy since that's leave him without workaround. I'm more in the camp let it fail since that means major screwup on our side.
Marshal.ThrowExceptionForHR((int)result); | ||
} | ||
|
||
pszName = Marshal.PtrToStringUni(pszName_local)!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To confirm, even when the call fails we still get a non-null pszName_local
buffer and we never return pszName
as null?
@RussKie now yes. |
@@ -9,13 +9,22 @@ internal static class IID | |||
// 618736E0-3C3D-11CF-810C-00AA00389B71 | |||
public static Guid IAccessible = new Guid(0x618736E0, 0x3C3D, 0x11CF, 0x81, 0x0C, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a follow up issue/PR to get this one fixed. Part of the idea here with using static properties is to avoid accidentally modifying these values. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. If the dialog hasn't been manually tested it should be before checking in.
I implement almost same way as DllImportGenerator handle that https://github.com/dotnet/runtime/blob/8d5f5267d33f7703c014cc89670f1f7aa47544f9/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs#L91-L99
@JeremyKuhne Take a look at ac142c4 that's important point to consider. Also because |
That, and introducing `SHCreateShellItemViaComWrappers` make Folder browser dialog works. `SHCreateShellItemViaComWrappers` is temporary means until I walk through all paths and replace usages of old function which rely on built-in COM one by one. That's should be easier for me tot test, and for you to review.
@JeremyKuhne @RussKie in last commit I add unwrapping RCW and that make things working. I validate changes manually by running |
/azp run |
Azure Pipelines successfully started running 2 pipeline(s). |
@RussKie anything else left? |
I'm OOF. @dreddy-work @JeremyKuhne please merge , if you have no further feedback. Thanks. |
Ooh!! Yeah!!! Thanks you guys a lot!!! |
Hi @kant2002, it looks like you just commented on a closed PR. The team will most probably miss it. |
CCW Wrapper in the PR was autogenerated using source generator
and tailored based on my previous experience.
As such I have strange local variables sometimes.
Also I do not implemented anything yet for following interfaces
Shell32.IFileDialogEvents
(CCW needed) Operate open file dialog using ComWrappers #6574Shell32.IShellItem
(RCW from built-in COM)Shell32.IShellItemArray
(RCW from built-in COM)Shell32.IFileDialogCustomize
(FileOpenDialogWrapper RCW need support for that interface)I plan to implement them, when collect all feedback on quality of this PR, so all improvements would be passed to next work.
What to do with code which maybe never called. How to detect that code? or should I bother with that and provide implementation for all methods?
For example I do not see errors in tests from
Shell32.IFileDialogEvents
, even if this interface used byVistaDialogEvents
and passed toIFileOpenDialog.Advise
method. So removing code and look where it fails in tests would be not practical.Would like to ask question about
IShellItem
andIShellItemArray
relationships. I will lookup on MSDN, but maybe collective conscionesness maybe help me better.So question: Does these completely unrelated interfaces, or there some
IShellItem
implementation which implementIShellItemArray
as well. Answer affects how I implement RCW for these interfaces.Contributes to #5163
Microsoft Reviewers: Open in CodeFlow