Add Window Handle to FileSavePicker Sub Running in Sub-Domain

71 views Asked by At

I'm trying to integrate the functionality of the Windows.Graphics.Printing3D API into a WiseJ VB.Net app to create .3mf files.

The Printing3D methods depend on UWP, so I created a sub-domain that allows the methods to function. All is well until it hits my SaveTo3mf() method, which utilizes FileSavePicker. At this point I get an InvalidWindowHandle exception and the method fails on this line:

Dim storageFile = Await savePicker.PickSaveFileAsync()

I've researched the problem and I understand or think I understand the problem is the sub-domain is operating outside the main domain, so it can't retrieve a window handle. My attempt to solve this is shown below by using IInitializeWithWindow. I used Invoke() believing it would return the method in question to the main domain, but the error persists.

I cobbled the code together and can't claim any expertise whatsoever in manipulating domains or threading. Is an alternate approach, or is there is a mistake in my implementation? The code compiles fine with the required references.

 <ComImport>
    <Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")>
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Interface IInitializeWithWindow
        Sub Initialize(ByVal hwnd As IntPtr)
    End Interface

   Delegate Sub Invoker(localPackage As Printing3D3MFPackage)

   Public Async Sub Build3MF()

        Dim packages = Await CreatePackageAsync()'method not shown, it seems to work properly once I added the sub-domain

        Dim c1 As New FilePicker
        Dim msd As Invoker = AddressOf c1.SaveTo3mf
        msd.Invoke(packages)

    End Sub

    Private Class FilePicker
        Inherits Page

        Public Async Sub SaveTo3mf(localPackage As Printing3D3MFPackage)
            Dim savePicker As FileSavePicker = New FileSavePicker()
            savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary
            savePicker.DefaultFileExtension = ".3mf"
            savePicker.FileTypeChoices.Add("3MF File", {".3mf"})

            Dim hWnd = Me.Handle'I added this to see if it produced a result; it does

            Dim initWindow As IInitializeWithWindow = CType(CObj(savePicker), IInitializeWithWindow)
            initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle)

            Dim storageFile = Await savePicker.PickSaveFileAsync()'Fail point

            If storageFile Is Nothing Then
            Else
                Using stream = Await localPackage.SaveAsync()
                    stream.Seek(0)

                    Using dataReader = New DataReader(stream)
                        Await dataReader.LoadAsync(CUInt(stream.Size))
                        Dim buffer = dataReader.ReadBuffer(CUInt(stream.Size))
                        Await FileIO.WriteBufferAsync(storageFile, buffer)
                    End Using
                End Using
            End If
        End Sub

    End Class
1

There are 1 answers

1
GAL43 On BEST ANSWER

As it happens for me programming is another word for learning the hard way. My vb.net understanding is being augmented by learning WiseJ. They have a simple function Application.Download(File,"FileName"). This allowed me to take the stream directly and download it applying a file name in the process. It doesn't have the elegance of allowing the user to select a location but the file is downloaded to the "Downloads" folder for the user to access.