1

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
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
GAL43
  • 11
  • 2
  • UWP has a completely different system for file access. I suggest using either SaveDialog or FileSavePicker (which is appropriate) in the outer scope/domain, and handling the actual writing to file in this outer level. Still do the save work in the sub-domain/inner scope, but instead of writing to disk there **return the stream** created by `SaveAsync()` back to the outer scope/domain to be written to disk. Then you should already have the WindowHandle you need. – Joel Coehoorn Apr 21 '22 at 21:30
  • Thanks Joel for your input! As it happens, the process is moot anyway. I neglected to take into account that WiseJ cannot access the client directly. My new approach takes a different turn as they do have a way to download a file via a specialized method but it doesn't use FileSaveDialog or FileSavePicker. – GAL43 Apr 22 '22 at 19:29

1 Answers1

0

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.

GAL43
  • 11
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 23 '22 at 16:30