2

I am trying to use customizable File Open Dialog in my C# application, and I found out that Common Item Dialog provides easy API for customization. However it requires some COM Interop magic, and since I am complete noob when it comes to COM I think it will be good learning excercise. Now I am stuck with following problem:

I created following *.bat file to generate interop assembly:

set OUT_DIR=.\com_interop

if not exist %OUT_DIR% mkdir "%OUT_DIR%

call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"

set SDK_DIR="C:\Program Files\Microsoft SDKs\Windows\v7.1"
%SDK_DIR%\Bin\midl.exe /server none /client stub /out "%OUT_DIR%" /tlb ShObjIdl.tlb /x64  %SDK_DIR%\Include\ShObjIdl.idl

%SDK_DIR%\Bin\TlbImp.exe "%OUT_DIR%\ShObjIdl.tlb" /out:ComInterop.ShObj.dll /namespace:ComInterop.ShObj /machine:X64

move /Y ComInterop.ShObj.dll "%OUT_DIR%\ComInterop.ShObj.dll" 

All x64-related switches come from my (failed) attempts to resolve my problem, and I am not sure if they are necessary.

Now, the problem is: midl.exe generates symbols where handles are converted to _RemotableHandle type. Instead of Show(IntPtr) method, it generates RemoteShow(_RemotableHandle):

[Guid("D57C7288-D4AD-4768-BE02-9D969532D960")]
[InterfaceType(1)]
public interface IFileOpenDialog : IFileDialog
{
    void AddPlace(IShellItem psi, FDAP FDAP);
    void Advise(IFileDialogEvents pfde, out uint pdwCookie);
    void ClearClientData();
    void Close(int hr);
    void GetCurrentSelection(out IShellItem ppsi);
    void GetFileName(out string pszName);
    void GetFileTypeIndex(out uint piFileType);
    void GetFolder(out IShellItem ppsi);
    void GetOptions(out uint pfos);
    void GetResult(out IShellItem ppsi);
    void GetResults(out IShellItemArray ppenum);
    void GetSelectedItems(out IShellItemArray ppsai);
    void RemoteShow([ComAliasName("ComInterop.ShObj.wireHWND")] ref _RemotableHandle hwndOwner);  // <===== argument, why u no HWND?
    void SetClientGuid(ref Guid guid);
    void SetDefaultExtension(string pszDefaultExtension);
    void SetDefaultFolder(IShellItem psi);
    void SetFileName(string pszName);
    void SetFileNameLabel(string pszLabel);
    void SetFileTypeIndex(uint iFileType);
    void SetFileTypes(uint cFileTypes, ref _COMDLG_FILTERSPEC rgFilterSpec);
    void SetFilter(IShellItemFilter pFilter);
    void SetFolder(IShellItem psi);
    void SetOkButtonLabel(string pszText);
    void SetOptions(uint fos);
    void SetTitle(string pszTitle);
    void Unadvise(uint dwCookie);
}

Is it possible to generate methods which use regular handles? If not, how am I supposed to call RemoteShow from my application? Bonus question: Why does it happen this way (COM-wise)?

In some other thread I found a suggestion to convert IntPtr to _RemotableHandle with following code:

    _RemotableHandle HWNDtoRemotableHandle(IntPtr handle)
    {
        return (_RemotableHandle)Marshal.PtrToStructure(handle, typeof(_RemotableHandle));
    }

But it fails with AccessViolation error, and I believe that such conversion is not very clean thing to do.

Maciek
  • 1,696
  • 12
  • 19
  • Does the accepted answer to http://stackoverflow.com/questions/4077326/tlbimp-exe-converts-hwnd-to-remotablehandle answer your question? If not, why not? – Jeroen Mostert Sep 19 '16 at 09:30
  • @Jeroen Mostert I've seen this thread before (that's where my attempt at conversion comes from), but accepted answer is not really helpful for me, because: 1. As OP mentioned, after passing `_MIDL_DECLARE_WIREM_HANDLE` flag to **midl** I get errors about handle types not being defined, but unfortunately I do not know how (and where) to define them, and 2. I believe this flag is an internal setting, and adding definition of missing handle types would require editing of IDL files contained in SDK, what does not seem to be really good (or correct!) solution to me. – Maciek Sep 19 '16 at 11:52

0 Answers0