Option Strict Off
Option Explicit On
Imports Microsoft.VisualBasic.FileIO
Imports System.IO

Public Class OpenSave
    ' Flag used to indicate the stop button was selected during processing.
    Private StopProcess As Boolean
    Private LastLogFilename As String
    Private Waiting As Boolean
    Private ProcessedAssemblies() As String
    Private ProcessedAssemblyCount As Integer
    Private UserSelectedMode As Boolean
    Private FolderPath, Filter, Filters(5), strFolders(1), StrUnMngdFolders(1), StrMngdFolder, StrMngdFolders(1) As String
    Private FilterSet(5) As Boolean
    Private nFilters As Integer
    Private AssemblyMode As Integer
    Private strSEFileType() As String = {"*.asm", "*.dft", "*.par", "*.psm", "*.pwd"}
    Dim strUpdateFileList, strProcessFiles, Quote As String
    Dim SolidEdgePath As String = ""
    Dim objApp As SolidEdgeFramework.Application
    Dim strSearchScopeFile As String
    Dim objDesignManager As DesignManager.Application
    Public strCacheLocation As String
    Dim strDate As String
    Dim strTempFilenames() As String
    Dim intFileNameCount As Integer
    Dim intTempFilenameCount As Integer
    Dim maxlen As Integer
    Dim intTotFileNameCount As Integer
    Dim Slash As String
    Public TopLevelFolder As Boolean
    Public bolFolder As Boolean = False

    Public Enum PartState
        PartOK = 1
        PartFailed = 2
        PartUnderConstrained = 3
        PartChanged = 4
        PartNotLoaded = 5
        PartPattern = 6
    End Enum

    Private Structure DimensionData
        Dim Name As String
        Dim Prefix As String
        Dim Suffix As String
        Dim Value As Double
        Dim Validated As Boolean
    End Structure

    Private Structure PartData
        Dim Name As String
        Dim Occurrence As Object
        Dim Matrix() As Double
        Dim State As PartState
        Dim PositionState As PartState
    End Structure

    Private Structure AssemblyData
        Dim Name As String
        Dim PartCount As Integer
        Dim Occurrences() As PartData
        Dim Processed As Boolean
    End Structure

    Private Structure AssemblyConfigurationsExist
        Dim AssemblyName As String
        Dim ConfigurationExists As Boolean
    End Structure

    Private Structure MissingDocumentType
        Dim MissingDocument As String
        Dim ParentDocument As String
        Dim Available As Boolean
        Dim DraftReference As Boolean
    End Structure

    '''''''''''''''''''''''''''''''''''''''''''''

    Private Structure STARTUPINFO
        Dim cb As Integer
        Dim lpReserved As String
        Dim lpDesktop As String
        Dim lpTitle As String
        Dim dwX As Integer
        Dim dwY As Integer
        Dim dwXSize As Integer
        Dim dwYSize As Integer
        Dim dwXCountChars As Integer
        Dim dwYCountChars As Integer
        Dim dwFillAttribute As Integer
        Dim dwFlags As Integer
        Dim wShowWindow As Integer
        Dim cbReserved2 As Integer
        Dim lpReserved2 As Integer
        Dim hStdInput As Integer
        Dim hStdOutput As Integer
        Dim hStdError As Integer
    End Structure

    Private Structure PROCESS_INFORMATION
        Dim hProcess As Integer
        Dim hThread As Integer
        Dim dwProcessId As Integer
        Dim dwThreadId As Integer
    End Structure

    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Integer, ByVal dwMilliseconds As Integer) As Integer

    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As Integer, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Integer, ByVal lpThreadAttributes As Integer, ByVal bInheritHandles As Integer, ByVal dwCreationFlags As Integer, ByVal lpEnvironment As Integer, ByVal lpCurrentDirectory As Integer, ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As PROCESS_INFORMATION) As Integer

    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer

    Private Const NORMAL_PRIORITY_CLASS As Integer = &H20
    Private Const INFINITE As Integer = -1
    Private Const STARTF_USESHOWWINDOW As Integer = &H1S
    Private Const SW_HIDE As Integer = 0

    '''''''''''''''''''''''''''''''''''''''''''''

    Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwAccess As Integer, ByVal fInherit As Integer, ByVal hObject As Integer) As Integer

    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)


    Private Sub btnProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcess.Click
        Dim i As Integer
        Dim j As Integer
        Dim k As Integer
        Dim objDoc As Object = Nothing
        Dim objNewWindow As Object = Nothing
        Dim strFileNames() As String
        Dim strPartFiles() As String
        Dim strAssemblyFiles() As String
        Dim strDraftFiles() As String
        Dim strWeldmentFiles() As String

        Dim intPartIndex As Integer
        Dim intAssemblyIndex As Integer
        Dim intDraftIndex As Integer
        Dim intWeldmentIndex As Integer
        Dim LogFile As Integer
        Dim DrawViewCount As Integer
        Dim ErrMessage As String = ""
        Dim V4Dimensions() As DimensionData = Nothing
        Dim DimCount As Integer
        Dim Index As Integer
        Dim OldAssemblies() As AssemblyData = Nothing
        Dim OldAssemblyCount As Integer
        Dim NewAssemblies() As AssemblyData = Nothing
        Dim NewAssemblyCount As Integer
        Dim ConfigurationExists() As AssemblyConfigurationsExist = Nothing
        Dim ConfigFile As String
        Dim TmpFile As Integer
        Dim OriginalFileCount As Integer
        Dim SwitchExists As String
        Dim Response As Object
        Dim LogFileClosed As Boolean
        Dim bNotReady, bGarbage As Boolean
        Dim bIsInputFile As Boolean
        Dim strTitle As String
        'Dim lngFeatType As Integer
        Dim Restart As Integer
        Dim strFileExt As String

        '******* Added because of .NET
        Try
            MessageFilter.Register()
        Catch ex As Exception
            PrintLine("Error registering message filter.")
        End Try
        '******* Added because of .NET


        ' Check to make sure asm file exists.
        If chkUpdate3DStyles.Checked Then
            If Not (File.Exists(Application.StartupPath + "\SourceStyles.asm")) Then
                MsgBox(Application.StartupPath + "\SourceStyles.asm" + ": File missing, cannot update 3D Styles.")
                Exit Sub
            End If
        End If


        If lstFiles.Items.Count = 0 Then
            MsgBox("There are no files to process, please browse to another location")
            GoTo GracefulExit
        End If

        txtStatus.Text = "Processing"
        txtStatus.Update()

        strTitle = "OpenSave"

        bIsInputFile = False
        bNotReady = False
        LogFileClosed = True
        bGarbage = True

        If chkInsight.Checked Then
            Slash = "/"
        Else
            Slash = "\"
        End If

        ' Save the current assembly mode
        GetAssemblyMode(AssemblyMode)
        ' Initialize the counter for the number of assemblies processed.
        OldAssemblyCount = -1
        NewAssemblyCount = -1

        If FileExists((txtLogFile.Text)) Then
            Response = MsgBox(txtLogFile.Text & " exists.  Do you want to overwrite it?", MsgBoxStyle.YesNo, strTitle)
            If Response = MsgBoxResult.Yes Then
                If Not LogFileClosed Then
                    FileClose(LogFile)
                    LogFileClosed = True
                End If
                Kill(txtLogFile.Text)
            Else
                bGarbage = False
                GoTo GracefulExit
            End If
        End If

        ' Change the caption on the cancel button and set the stop processing flag.
        btnExit.Text = "Stop"
        btnExit.Update()
        ' Initialize flag to indicate if the user wants to stop processing files.
        StopProcess = False

        ' Build up list of files to process depending on which option was selected.
        intFileNameCount = 0

        ' Get total number of files in the list
        intTotFileNameCount = lstFiles.Items.Count
        ' Loop through for each file type.

        If intTotFileNameCount > 0 Then
            If lstFiles.SelectedItems.Count = 0 Then
                ' Allocate space to store the filenames.
                ReDim strTempFilenames(intTotFileNameCount)

                ' Load the selected filenames into the array.
                intFileNameCount = -1
                For i = 0 To intTotFileNameCount - 1
                    intFileNameCount = intFileNameCount + 1
                    If chkInsight.Checked Then
                        strTempFilenames(intFileNameCount) = lstFiles.Items(i)
                    Else
                        ' that wonderful microsoft inconsistency again.
                        If TopLevelFolder = True Then
                            strTempFilenames(intFileNameCount) = FolderPath & lstFiles.Items(i)
                        Else
                            strTempFilenames(intFileNameCount) = FolderPath & Slash & lstFiles.Items(i)
                        End If

                    End If
                Next
            Else
                ReDim strTempFilenames(lstFiles.SelectedItems.Count)

                ' Load the selected filenames into the array.
                intFileNameCount = -1
                For i = 0 To lstFiles.SelectedItems.Count - 1
                    intFileNameCount = intFileNameCount + 1
                    If chkInsight.Checked Then
                        strTempFilenames(intFileNameCount) = lstFiles.SelectedItems(i)
                    Else
                        If TopLevelFolder = True Then
                            strTempFilenames(intFileNameCount) = FolderPath & lstFiles.SelectedItems(i)
                        Else
                            strTempFilenames(intFileNameCount) = FolderPath & Slash & lstFiles.SelectedItems(i)
                        End If
                    End If
                Next

            End If
        End If

        ' OK, we have collected all the files in strTempFilenames, so now let's look at processing them.

        OriginalFileCount = intFileNameCount
        If intFileNameCount > -1 Then
            ReDim strPartFiles(intFileNameCount + 1)
            ReDim strAssemblyFiles(intFileNameCount + 1)
            ReDim strDraftFiles(intFileNameCount + 1)
            ReDim strWeldmentFiles(intFileNameCount + 1)
            ReDim ProcessedAssemblies(intFileNameCount + 1)
            ProcessedAssemblyCount = 0

            ' Sort the files base on type.
            intPartIndex = -1
            intAssemblyIndex = -1
            intDraftIndex = -1
            intWeldmentIndex = -1

            For j = 0 To intFileNameCount

                strFileExt = LCase(strTempFilenames(j).Substring(strTempFilenames(j).Length - 3, 3))

                If strFileExt = "par" Then
                    intPartIndex = intPartIndex + 1
                    strPartFiles(intPartIndex) = strTempFilenames(j)
                ElseIf strFileExt = "psm" Then
                    intPartIndex = intPartIndex + 1
                    strPartFiles(intPartIndex) = strTempFilenames(j)
                ElseIf strFileExt = "asm" Then
                    intAssemblyIndex = intAssemblyIndex + 1
                    strAssemblyFiles(intAssemblyIndex) = strTempFilenames(j)
                ElseIf strFileExt = "dft" Then
                    intDraftIndex = intDraftIndex + 1
                    strDraftFiles(intDraftIndex) = strTempFilenames(j)
                ElseIf strFileExt = "pwd" Then
                    intWeldmentIndex = intWeldmentIndex + 1
                    strWeldmentFiles(intWeldmentIndex) = strTempFilenames(j)
                End If
            Next

            ' For unmanaged assemblies.  FTLA does not work on Managed assembly files
            ' Process the assembly list to get the top level assemblies.
            If chkInsight.Checked = False Then
                'New for ST4 if we are updating styles each ASM must be opened individually. CleanAssemblyList will be skipped
                'Open the top-level and save all with the debug switch will not update the sub-asms.
                If chkUpdate3DStyles.Checked = False Then
                    If intAssemblyIndex > -1 Then
                        CleanAssemblyList(strAssemblyFiles, intAssemblyIndex)
                    End If
                End If
            End If

            ' Create a big list of all of the files.
            ' Reset total number of files - remember that the arrays are zero based.
            intTempFilenameCount = -1
            If intPartIndex > -1 Then intTempFilenameCount = intPartIndex
            If intAssemblyIndex > -1 Then
                If intTempFilenameCount > -1 Then
                    intTempFilenameCount = intTempFilenameCount + intAssemblyIndex + 1
                Else
                    intTempFilenameCount = intAssemblyIndex
                End If
            End If
            If intDraftIndex > -1 Then
                If intTempFilenameCount > -1 Then
                    intTempFilenameCount = intTempFilenameCount + intDraftIndex + 1
                Else
                    intTempFilenameCount = intDraftIndex
                End If
            End If
            If intWeldmentIndex > -1 Then
                If intTempFilenameCount > -1 Then
                    intTempFilenameCount = intTempFilenameCount + intWeldmentIndex + 1
                Else
                    intTempFilenameCount = intWeldmentIndex
                End If
            End If
            If intTempFilenameCount = -1 Then
                If optAllFiles.Checked Then
                    ' Clear the status display.
                    txtStatus.Text = ""
                    txtStatus.Update()
                End If

                Activate()
                MsgBox("Unexpected error encountered when processing file list.", MsgBoxStyle.OkOnly + MsgBoxStyle.Critical, "Open & Save")
                Exit Sub
            End If

            ReDim strFileNames(intTempFilenameCount + 1)

            intFileNameCount = -1
            For i = 0 To intPartIndex
                intFileNameCount = intFileNameCount + 1
                strFileNames(intFileNameCount) = strPartFiles(i)
            Next
            For i = 0 To intAssemblyIndex
                intFileNameCount = intFileNameCount + 1
                strFileNames(intFileNameCount) = strAssemblyFiles(i)
            Next

            For i = 0 To intWeldmentIndex
                intFileNameCount = intFileNameCount + 1
                strFileNames(intFileNameCount) = strWeldmentFiles(i)
            Next

            For i = 0 To intDraftIndex
                intFileNameCount = intFileNameCount + 1
                strFileNames(intFileNameCount) = strDraftFiles(i)
            Next

        Else
            If optAllFiles.Checked Then
                txtStatus.Text = ""
                txtStatus.Update()
            End If

            MsgBox("No Solid Edge documents are selected.", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "Open & Save")

            Exit Sub
        End If

        ' Check to see if the configuration files for the assemblies exist.
        ' Need to do it now before they get automatically created during the open save process.
        ' Need to skip this if Managed assembly
        If chkInsight.Checked = False Then
            If intAssemblyIndex > -1 Then
                ReDim ConfigurationExists(intAssemblyIndex + 1)
            End If

            For i = 0 To intAssemblyIndex
                ' Attempt to open the configuration file to see if it exists.
                ConfigFile = strAssemblyFiles(i).Substring(0, strAssemblyFiles(i).Length - 3) & "cfg"

                ' Save the assembly name.
                ConfigurationExists(i).AssemblyName = strAssemblyFiles(i)

                ' Determine whether the configuration exists or not by attempting to open the file.
                Try
                    TmpFile = FreeFile()
                    FileOpen(TmpFile, ConfigFile, OpenMode.Input)
                    ' Save the configuration does exist.
                    ConfigurationExists(i).ConfigurationExists = True
                    FileClose(TmpFile)
                Catch ex As Exception
                    ' Save the configuration does not exist.
                    ConfigurationExists(i).ConfigurationExists = False
                End Try
            Next
        End If

        ' Still not ready to process the list of files.  Need to check for broken links.
        txtStatus.Text = "Checking for broken links"
        txtStatus.Update()

        objDesignManager = CreateObject("DesignManager.Application")
        objDesignManager.FindBrokenLinks(strFileNames, , False, True, True, True, True, True, True, True)
        objDesignManager.Quit()

        ' Do garbage collection here in order to release the documents
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDesignManager)
        GarbageCollection()
        objDesignManager = Nothing

        Try
            LogFile = FreeFile()
            FileOpen(LogFile, txtLogFile.Text, OpenMode.Output)
        Catch ex As Exception
            Activate()
            MsgBox("Error opening specified logfile: '" & txtLogFile.Text & "'" & Chr(13) & "Make sure you have write access", MsgBoxStyle.OkOnly + MsgBoxStyle.Critical, "Open & Save")
            Exit Sub
        End Try

        ' Write header information into log file.
        PrintLine(LogFile, "Open & Save: " & Today & ", " & TimeOfDay)
        PrintLine(LogFile, "")
        If chkUpdate3DStyles.Checked Then
            PrintLine(LogFile, "Updated 3D Face and View Styles")
            PrintLine(LogFile, "")
        End If
        ' Add the list of top level assemblies to the log file
        PrintLine(LogFile, "Top Level Assemblies")

        If intAssemblyIndex > -1 Then
            For i = 0 To intAssemblyIndex
                PrintLine(LogFile, strAssemblyFiles(i))
            Next
        End If
        PrintLine(LogFile, "")

        ' checking to see if Solid Edge is available
        ' Attempt to connect to a running instance of Solid Edge.
        Dim retry As Boolean
        Try
            objApp = GetObject(, "SolidEdge.Application")
            retry = False
        Catch ex As Exception
            txtStatus.Text = "Starting Solid Edge ..."
            txtStatus.Update()
            retry = True
        End Try

        If retry = True Then
            ' Solid Edge is not running.  Clear the previous error.

            Try
                ' Start Solid Edge.
                objApp = CreateObject("SolidEdge.Application")
            Catch ex As Exception
                Activate()
                MsgBox("Cannot start Solid Edge.", MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Open & Save")
                FileClose(LogFile)
                End
            End Try
        End If
        ' Make Solid Edge visible.
        objApp.Visible = True

        ' Set appropriate option to show or suppress all Solid Edge message boxes
        If OptSuppressDialogs.Checked = True Then
            objApp.DisplayAlerts = False
        End If

        If OptShowDialogs.Checked = True Then
            objApp.DisplayAlerts = True
        End If

        ' Set the appropriate mode for opening assemblies.
        If chkAssemblyDifference.Checked And intAssemblyIndex > -1 Then
            ' Set the assembly mode to open assemblies with Occurrences inactive
            SetAssemblyMode(1)
        Else
            ' Set the assembly mode to open assemblies with all Occurrences active.
            SetAssemblyMode(2)
        End If

        ' See if setting and leaving on for the entire session resolves saving resolved asm child files

        If chkProcessReleased.Checked Then
            'check to see if registry location exists
            SwitchExists = QueryValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess")

            If SwitchExists = "" Then
                '-- Create key in CURRENT USER and set it
                SetKeyValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess", "1", REG_DWORD)
            End If

            If SwitchExists = "0" Then
                '-- Create key in CURRENT USER and set it
                SetKeyValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess", "1", REG_DWORD)
            End If
        End If

        ' Now lets start processing the files
        lngStatus = 999
        ' Loop through the list of files.

        Restart = 50
        For i = 0 To intFileNameCount
            ' Check the global variable to see if the stop process command button has been selected
            System.Windows.Forms.Application.DoEvents()
            If StopProcess Then
                Activate()
                MsgBox("Processing aborted.")
                GoTo RegularEnd
            End If

            ' For every 50 files, close and reopen Solid Edge.
            If i = Restart Then
                Restart = Restart + 50
                txtStatus.Text = "Closing and restarting Solid Edge..."
                txtStatus.Update()

                objApp.Quit()

                ' Do garbage collection here in order to release the documents
                If Not objNewWindow Is Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objNewWindow)
                If Not objDoc Is Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDoc)
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                GarbageCollection()
                objDesignManager = Nothing

                objNewWindow = Nothing
                objDoc = Nothing
                objApp = Nothing
                ' Pause a few seconds.
                Sleep(14000)

                ' Start Solid Edge.

                Try
                    objApp = CreateObject("SolidEdge.Application")
                Catch ex As Exception
                    ' Cannot start Solid Edge, so exit the program.
                    Activate()
                    MsgBox("Cannot start Solid Edge.")
                    FileClose(LogFile)
                    End
                End Try

                objApp.Visible = True
                ' Set appropriate option to show or suppress all Solid Edge message boxes
                If OptSuppressDialogs.Checked = True Then
                    objApp.DisplayAlerts = False
                End If

                If OptShowDialogs.Checked = True Then
                    objApp.DisplayAlerts = True
                End If

            End If

            ' Display current status
            txtStatus.Text = "Processing file " & i + 1 & " of " & intFileNameCount + 1 & ": '" & strFileNames(i) & "'"
            txtStatus.Update()

            ' Check to make sure we have write access to the file.
            ' Either need to skip this step for Insight process or get fileattribute in some other manner.
            If chkInsight.Checked = False Then
                If (GetAttr(strFileNames(i)) And FileAttribute.ReadOnly) <> 0 Then
                    objDoc = Nothing
                    ErrMessage = "   The file is read only."
                    GoTo Bypass
                End If
            End If
            If strFileNames(i).EndsWith("asm") Then
                ' To save time, rather than processing all assemblies, when
                ' OpenSave is running, Assembly will save all subassemblies
                ' when it saves a top-level assembly
                SetOpenSaveMacroFlag(1)
            End If

            ' Open the document.
            ' Support for processing Released\Baselined\Obselete status files
            ' Next few lines of code to check doc status but need to skip if Insight.
            If chkInsight.Checked = False Then
                strSEStatus = GetStatus(strFileNames(i))

                If chkProcessReleased.Checked Then
                    'strSEStatus = "RELEASED"
                    If UCase(strSEStatus) = "RELEASED" Then
                        blnChangedStatus = True
                        lngStatus = 0
                    ElseIf UCase(strSEStatus) = "IN WORK" Then
                        blnChangedStatus = True
                        lngStatus = 0
                    ElseIf UCase(strSEStatus) = "BASELINED" Then
                        blnChangedStatus = True
                        lngStatus = 0
                    ElseIf UCase(strSEStatus) = "OBSOLETE" Then
                        blnChangedStatus = True
                        lngStatus = 0
                    End If

                    If lngStatus = 0 Then
                        PrintLine(LogFile, "Released/baselined/obselete/in work document was saved > " & strFileNames(i))
                    End If

                End If

                If UCase(strSEStatus) <> "AVAILABLE" And UCase(strSEStatus) <> "IN REVIEW" Then
                    If blnChangedStatus = False Then
                        blnChangedStatus = False
                        strSEStatus = ""
                        lngStatus = 999
                        PrintLine(LogFile, "***Document is either released, baselined, or obselete and was not processed. > " & strFileNames(i))
                        PrintLine(LogFile, "")
                        GoTo SkipToNext
                    End If
                End If
            End If

            ' Support for processing Released\Baselined\Obselete status files
            ' end of code to check doc status
            Try
                objDoc = objApp.Documents.Open(strFileNames(i))
                retry = False
            Catch ex As Exception
                txtStatus.Text = "Error opening document.  Closing and restarting Solid Edge..."
                txtStatus.Update()

                objDoc = Nothing
                retry = True
            End Try

            If retry = True Then
                Try
                    objDoc = objApp.ActiveDocument
                    objDoc.Close(False)
                    objApp.Quit()

                    ' Do garbage collection here in order to release the documents
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDoc)
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                    GarbageCollection()

                    objDoc = Nothing
                    objApp = Nothing

                    ' Pause for 10 seconds.
                    Sleep(10000)

                Catch ex As Exception

                End Try

            End If

            ' Start Solid Edge.
            If retry = True Then

                Try
                    objApp = CreateObject("SolidEdge.Application")
                    objDoc = objApp.Documents.Open(strFileNames(i))

                Catch ex As Exception
                    ' Cannot start Solid Edge, so exit the program.
                    Activate()
                    MsgBox("Cannot start Solid Edge or open document.")
                    PrintLine(LogFile, strAssemblyFiles(i) & "failed to open, skipping to the next file")

                    GoTo SkipToNext

                End Try
            End If

            objApp.Visible = True

            ' Set appropriate option to show or suppress all Solid Edge message boxes
            If OptSuppressDialogs.Checked = True Then
                objApp.DisplayAlerts = False
            End If

            If OptShowDialogs.Checked = True Then
                objApp.DisplayAlerts = True
            End If

Bypass:
            ' account for case of extension
            strFileExt = LCase(strFileNames(i).Substring(strFileNames(i).Length - 3, 3))

            If strFileExt = "par" Or strFileExt = "psm" Then
                If objDoc Is Nothing Then
                    PrintLine(LogFile, "Part/Sheetmetal Document> " & strFileNames(i))
                    PrintLine(LogFile, ErrMessage)
                    PrintLine(LogFile, "")
                Else ' then objDoc is something
                    ' Check for igACISBodyFeatureObject
                    If (objDoc.Type = SolidEdgeConstants.DocumentTypeConstants.igPartDocument Or objDoc.Type = SolidEdgeConstants.DocumentTypeConstants.igSheetMetalDocument) Then
                        If objDoc.Models.Count > 0 Then
                            'Force regeneration of triangle cash
                            objDoc.NewWindow()
                            objNewWindow = objApp.ActiveWindow
                            objNewWindow.View.Fit()
                            ' another timing related issue so adding a sleep
                            Sleep(1000)
                            objNewWindow.Close()

                            ' Update 3D Styles
                            If chkUpdate3DStyles.Checked Then Update3DStyles(objDoc)

                            ' Save the Par/Psm document
                            Try
                                objDoc.Save()
                            Catch ex As Exception
                                MsgBox("Error attempting to save document" & Chr(13) & "Make sure you have write access")
                                'CLose down SE app
                                objApp.Quit()

                                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                                GarbageCollection()

                                GoTo GracefulExit
                            End Try

                            ' Write log information.
                            Call WritePartLogInformation(objDoc, LogFile)

                        Else ' condition of models count

                            ' Update 3D Styles
                            If chkUpdate3DStyles.Checked Then Update3DStyles(objDoc)

                            ' Save the Par/Psm document
                            Try
                                objDoc.Save()
                            Catch ex As Exception
                                MsgBox("Error attempting to save document" & Chr(13) & "Make sure you have write access")
                                'CLose down SE app
                                objApp.Quit()

                                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                                GarbageCollection()

                                GoTo GracefulExit
                            End Try

                            ' The document doesn't contain any features.
                            PrintLine(LogFile, "Part/Sheetmetal Document> " & strFileNames(i))
                            PrintLine(LogFile, "   Document doesn't contain any features.")
                            PrintLine(LogFile, "")
                        End If ' condition of models count
                    End If ' condition of document type.
                End If

            ElseIf strFileExt = "asm" Then
                If objDoc Is Nothing Then
                    PrintLine(LogFile, "Assembly Document> " & strFileNames(i))
                    PrintLine(LogFile, ErrMessage)
                    PrintLine(LogFile, "")
                Else
                    If chkAssemblyDifference.Checked Then
                        ' Get the current state of all of the Occurrences in the current assembly and subassemblies.

                        GetCurrentAssemblyState(objDoc, OldAssemblies, OldAssemblyCount, 4)

                        txtSubAsm.Text = "First pass complete, now load assemly parts active"
                        txtSubAsm.Update()

                        ' Close the document.
                        objDoc.Close(False)

                        ' Do garbage collection here in order to release the documents
                        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDoc)
                        GarbageCollection()

                        ' Pause for a couple of seconds.
                        Sleep(1000)

                        ' Change the registry setting to open with all Occurrences active.
                        SetAssemblyMode(2)

                        ' Reopen the assembly document.
                        Try
                            objDoc = objApp.Documents.Open(strFileNames(i))
                        Catch ex As Exception
                            PrintLine(LogFile, "Problem with processing " & strFileNames(i) & ", skipping to next file")
                            GoTo SkipToNext
                        End Try

                    End If

                    ' Get the state of the assembly now.
                    GetCurrentAssemblyState(objDoc, NewAssemblies, NewAssemblyCount, 5)

                    txtSubAsm.Text = "Writing Assembly log Info"
                    txtSubAsm.Update()

                    ' Write out assembly information.
                    WriteAssemblyLogInformation(OldAssemblies, OldAssemblyCount, NewAssemblies, NewAssemblyCount, LogFile)

                    ' Added for ST4 to copy styles
                    If chkUpdate3DStyles.Checked Then
                        ' turn off force a save on subassemblies
                        'check to see if registry location exists
                        SwitchExists = QueryValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "FORCE_SAVE_LINKED_DOCS")

                        If SwitchExists = "" Or SwitchExists = "0" Then
                            '-- Create key in CURRENT USER and set it
                            SetKeyValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "FORCE_SAVE_LINKED_DOCS", "0", REG_DWORD)
                        End If

                        ' Update 3D Styles
                        Update3DStyles(objDoc)
                    Else
                        ' force a save on subassemblies
                        'check to see if registry location exists
                        SwitchExists = QueryValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "FORCE_SAVE_LINKED_DOCS")

                        If SwitchExists = "" Or SwitchExists = "0" Then
                            '-- Create key in CURRENT USER and set it
                            SetKeyValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "FORCE_SAVE_LINKED_DOCS", "1", REG_DWORD)
                        End If

                    End If

                    txtSubAsm.Text = "Saving Assembly"
                    txtSubAsm.Update()

                    ' Save the ASM document
                    Try
                        objDoc.Save()
                    Catch ex As Exception
                        MsgBox("Error attempting to save document" & Chr(13) & "Make sure you have write access")
                        'CLose down SE app
                        objApp.Quit()

                        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                        GarbageCollection()

                        GoTo GracefulExit
                    End Try
                    txtSubAsm.Text = ""
                    txtSubAsm.Update()

                    ' reset debug key to 0
                    '-- Create key in CURRENT USER and set it
                    SetKeyValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "FORCE_SAVE_LINKED_DOCS", "0", REG_DWORD)

                    ' Let Assembly know that OpenSave is no longer trying to save assembly files
                    SetOpenSaveMacroFlag(0)
                End If

            ElseIf strFileExt = "pwd" Then
                If objDoc Is Nothing Then
                    PrintLine(LogFile, "Weldment Document> " & strFileNames(i))
                    PrintLine(LogFile, ErrMessage)
                    PrintLine(LogFile, "")

                Else
                    If objDoc.Type = SolidEdgeConstants.DocumentTypeConstants.igWeldmentDocument Then
                        'update all links
                        WriteWeldmentLogInfo(objDoc, LogFile)
                        If objDoc.WeldmentModels.Count = 0 Then
                            PrintLine(LogFile, "Weldment Document> " & strFileNames(i))
                            PrintLine(LogFile, "No Linked Assembly.  Empty File")
                            PrintLine(LogFile, "")
                        End If

                    End If

                End If

                ' Force regeneration of triangle cash
                objDoc.NewWindow()
                objNewWindow = objApp.ActiveWindow
                objNewWindow.View.Fit()
                objNewWindow.Close()

                ' Update 3D Styles
                If chkUpdate3DStyles.Checked Then Update3DStyles(objDoc)

                ' Save the PWD document
                Try
                    objDoc.Save()
                Catch ex As Exception
                    MsgBox("Error attempting to save document" & Chr(13) & "Make sure you have write access")
                    'CLose down SE app
                    objApp.Quit()

                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                    GarbageCollection()

                    GoTo GracefulExit
                End Try

            ElseIf strFileExt = "dft" Then
                If objDoc Is Nothing Then
                    PrintLine(LogFile, "Draft Document> " & strFileNames(i))
                    PrintLine(LogFile, ErrMessage)
                    PrintLine(LogFile, "")
                Else
                    ' Only update drawing views if the user explicitly asks for it
                    If chkUpdateDV.Checked Then
                        ' Determine the total number of dimensions in the document.
                        DimCount = 0
                        For j = 1 To objDoc.Sheets.Count
                            DimCount = DimCount + objDoc.Sheets.Item(j).Dimensions.Count
                        Next

                        ' Dimension the array to hold the dimension data.
                        If DimCount > 0 Then
                            ReDim V4Dimensions(DimCount)
                        End If

                        ' Get state of all dimensions before update.
                        Index = -1
                        For j = 1 To objDoc.Sheets.Count
                            For k = 1 To objDoc.Sheets.Item(j).Dimensions.Count
                                Index = Index + 1
                                V4Dimensions(Index).Name = objDoc.Sheets.Item(j).Dimensions.Item(k).Name
                                V4Dimensions(Index).Value = objDoc.Sheets.Item(j).Dimensions.Item(k).Value
                                V4Dimensions(Index).Prefix = objDoc.Sheets.Item(j).Dimensions.Item(k).PrefixString
                                V4Dimensions(Index).Suffix = objDoc.Sheets.Item(j).Dimensions.Item(k).SuffixString
                                V4Dimensions(Index).Validated = False
                            Next
                        Next

                        ' Update the drawing views.
                        For j = 1 To objDoc.ModelLinks.Count
                            objDoc.ModelLinks(j).UpdateViews()
                        Next

                        ' Count the number of views in the document.
                        DrawViewCount = 0
                        For j = 1 To objDoc.Sheets.Count
                            DrawViewCount = DrawViewCount + objDoc.Sheets.Item(j).DrawingViews.Count
                        Next
                    End If

                    ' Write log information
                    WriteDraftLogInformation(objDoc, DrawViewCount, LogFile, V4Dimensions, DimCount, ConfigurationExists, intAssemblyIndex)

                    ' Save the DFT document
                    Try
                        objDoc.Save()
                    Catch ex As Exception
                        MsgBox("Error attempting to save document" & Chr(13) & "Make sure you have write access")
                        'CLose down SE app
                        objApp.Quit()

                        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
                        GarbageCollection()

                        GoTo GracefulExit
                    End Try
                End If

            End If

            ' Close the document without saving changes since they've already been saved.
            If Not objDoc Is Nothing Then
                objDoc.Close(False)
            End If

            ' Release the reference.
            objDoc = Nothing

            'reset flags for next in loop
            blnChangedStatus = False
            strSEStatus = ""
            lngStatus = 999

SkipToNext:

        Next

RegularEnd:

        Activate()

        ' Close the log file.
        FileClose(LogFile)

        ' Reset the assembly mode
        If intAssemblyIndex > 0 Then
            SetAssemblyMode(AssemblyMode)
        End If

        'CLose down SE app
        objApp.Quit()

        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
        GarbageCollection()

        ' support for processing Released\Baselined\Obselete status files
        If chkProcessReleased.Checked Then
            'retval = SetKeyValue(HKEY_CURRENT_USER, "Software\Unigraphics Solutions\Solid Edge\Version " & strSEVersion & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess", "0", REG_DWORD)
            DeleteValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess")
        End If


        ' Dismiss the status form.
        txtStatus.Text = "Finished processing."
        txtStatus.Update()
        txtSubAsm.Text = ""
        txtSubAsm.Update()

        btnExit.Text = "Exit"

        '******* Added because of .NET
        Try
            MessageFilter.Revoke()
        Catch ex As Exception
            PrintLine("Error revoking the message filter.")
        End Try
        '******* Added because of .NET

        Exit Sub



GracefulExit:

        ' support for processing Released\Baselined\Obselete status files
        If chkProcessReleased.Checked Then
            DeleteValue(HKEY_CURRENT_USER, strRegistryBase & "\Debug", "DocMgmt_OverrideStatusCheckForFileAccess")
        End If

        ' more garbage collection
        If Not objDoc Is Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDoc)
        If Not objApp Is Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objApp)
        GarbageCollection()

        UserSelectedMode = False
        txtStatus.Text = "Select new options or Exit"
        txtStatus.Update()

        btnExit.Text = "Exit"

        '******* Added because of .NET
        Try
            MessageFilter.Revoke()
        Catch ex As Exception
            PrintLine("Error revoking the message filter.")
        End Try
        '******* Added because of .NET

    End Sub


    Private Sub OpenSave_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Quote = Chr(34)
        Slash = "\"
        lblStyles.Visible = False

        strUpdateFileList = " Select " & Quote & "Update File List" & Quote
        strProcessFiles = "Files to be processed"

        FolderPath = System.Windows.Forms.Application.StartupPath()
        FolderBrowserDialog1.SelectedPath = FolderPath
        strFolders(0) = FolderPath
        strDate = System.DateTime.Now.Hour.ToString + "_" + System.DateTime.Now.Minute.ToString + "_" + System.DateTime.Now.Second.ToString + " " + System.DateTime.Now.Month.ToString + "-" + System.DateTime.Now.Day.ToString + "-" + System.DateTime.Now.Year.ToString

        lstPath.Items.Add(FolderPath)

        ' Initialize the default log file.
        txtLogFile.Text = FolderPath & "\OpenSave" & strDate & ".log"
        LastLogFilename = txtLogFile.Text
        chkPart.CheckState = CheckState.Checked
        chkSheetmetal.CheckState = CheckState.Checked

        If GetSolidEdgePath(SolidEdgePath) = False Then
            MsgBox("Unable to determine the path for Solid Edge")
            End
        End If
        ' Check to see if SE is running
        strRegistryBase = "Software\Siemens\Solid Edge\Version " & strSEVersion
        Try
            objApp = GetObject(, "SolidEdge.Application")
            If objApp.Documents.Count > 0 Then
                MsgBox("You must close all open Solid Edge documents before running this utility.", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "Open & Save")
                objApp.Activate()
                End
            End If
            Try
                strRegistryBase = objApp.RegistryPath
            Catch ex As Exception
                strRegistryBase = "Software\Siemens\Solid Edge\Version " & strSEVersion
            End Try
        Catch ex As Exception
            ' OK to go forward
        End Try

        btnUpdateFiles.Enabled = False
        btnProcess.Enabled = False

    End Sub

    Function FileExists(ByRef TestFile As String) As Boolean
        Dim ret As String

        Try
            ret = CStr(FileDateTime(TestFile))
            FileExists = True
        Catch ex As Exception
            Debug.Print("file not found")
            FileExists = False
        End Try

    End Function


    Public Sub SetFileList(ByVal strPath)
        If FolderPath = strPath Then lstFiles.Items.Clear()
        If chkPart.Checked Then
            FileList(strPath, "*.par")
        End If
        If chkSheetmetal.Checked Then
            FileList(strPath, "*.psm")
        End If
        If chkAssembly.Checked Then
            FileList(strPath, "*.asm")
        End If
        If chkDraft.Checked Then
            FileList(strPath, "*.dft")
        End If
        If chkWeldment.Checked Then
            FileList(strPath, "*.pwd")
        End If
        SetFilters()

    End Sub

    Private Sub FileList(ByVal Path As String, ByVal Filter As String)
        Dim FileName As String
        Dim lenPath, len, retval As Integer
        Dim ListOfDocs As Object = Nothing
        Dim intNumberOfDocsFound As Long
        Dim PropertyList(3) As Object  'Currently limited to 3
        Dim ConditionList(3) As Object  'Currently limited to 3
        Dim PropertyValueList(3) As Object  'Currently limited to 3
        Dim i As Integer
        Dim blnUseSearchScope, blnSubfolders As Boolean
        Dim strFoldersToSearch As String
        Dim NumProps As Integer

        Cursor.Current = System.Windows.Forms.Cursors.WaitCursor

        blnSubfolders = False
        blnUseSearchScope = False

        If chkInsight.Checked Then
            txtStatus.Text = "Searching Insight for Files, be patient"
            txtStatus.Update()
            strFoldersToSearch = Path
            lenPath = Path.Length

            Try
                objDesignManager = CreateObject("DesignManager.Application")
                If strCacheLocation = "" Then objDesignManager.GetGlobalParameter(DesignManager.ApplicationGlobalConstants.seApplicationGlobalInsightCacheLocation, strCacheLocation)
            Catch ex As Exception
                MsgBox("Cannot start Revision Manager.", vbCritical + vbOKOnly, "Open & Save")
            End Try

            If optAllFiles.Checked Then blnSubfolders = True

            retval = objDesignManager.SearchDocuments(bUseSearchScope:=blnUseSearchScope,
                    bstrFolders:=strFoldersToSearch,
                    bIncludeSubFolders:=blnSubfolders,
                    ListOfFoundDocuments:=ListOfDocs,
                    iNumDocsFound:=intNumberOfDocsFound,
                    varFileFilterOrText:=Filter, PropertyList:=PropertyList,
                    ConditionList:=ConditionList, PropertyValueList:=PropertyValueList, varNumProps:=NumProps)
            objDesignManager.Quit()

            If retval <> 0 Then
                MsgBox("Error querying to find list of documents", vbOKOnly, "Reset status")
                End
            End If

            ' Do garbage collection here in order to release the documents
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objDesignManager)
            GarbageCollection()
            objDesignManager = Nothing

            For i = 0 To intNumberOfDocsFound - 1
                lstFiles.Items.Add(ListOfDocs(i))
            Next

        Else
            lenPath = FolderPath.Length
            My.Computer.FileSystem.CurrentDirectory = Path

            txtStatus.Text = "Generating file list"
            txtStatus.Update()
            For Each foundFile As String In FileSystem.GetFiles(Path, FileIO.SearchOption.SearchTopLevelOnly, Filter)
                ' need to handle the wonderful microsoft inconsistency of path derfinition when the directory is the drive root level; i.e. "E:"
                ' For all subdirectories under the root, the folder path will not include an ending "\"; i.e. "E:\temp"
                ' But the root level path is "E:\".  So we have to test and adjust the length.

                len = foundFile.Length
                If foundFile.Length + Path.Length - FolderPath.Length > maxlen Then maxlen = len
                If TopLevelFolder = True Then
                    FileName = foundFile.Substring(lenPath, len - lenPath)
                Else
                    FileName = foundFile.Substring(lenPath + 1, len - lenPath - 1)
                End If
                lstFiles.Items.Add(FileName)
            Next
            ' this is to adjust the lstfiles column width such that the complete filename can be viewed
            If 5 * maxlen > 250 Then lstFiles.ColumnWidth = 5 * maxlen
        End If
        If lstFiles.Items.Count > 0 Then
            txtStatus.Text = "Files found, proceed with processing or select options"
            txtStatus.Update()
            ' Get total number of files in the list
            intTotFileNameCount = lstFiles.Items.Count
            btnProcess.Enabled = True
        Else
            txtStatus.Text = "No files found, select options or browse to new location"
            btnProcess.Enabled = False

        End If

        txtFilesFound.Text = lstFiles.Items.Count
        txtFilesFound.Update()

        Cursor.Current = System.Windows.Forms.Cursors.Default

    End Sub

    Private Sub FolderList()
        Dim i As Integer
        lstPath.Items.Clear()
        For i = 0 To UBound(strFolders) - 1
            lstPath.Items.Add(strFolders(i))
        Next

    End Sub

    Sub LoadSEFiles()
        ' Loops through the selected folders to populate the file list
        If optAllInDirectory.Checked And lstPath.SelectedItems.Count = 0 Then
            SetFileList(FolderPath)
        Else
            For i = 0 To UBound(strFolders) - 1
                SetFileList(strFolders(i))
            Next
        End If
    End Sub

    Private Function IsInitializedArrayOfStrings(ByRef strArray() As String) As Boolean

        Dim lL As Integer 'lower bound of array
        Dim lU As Integer 'upper bound of array

        Try
            lL = LBound(strArray)
            lU = UBound(strArray)

            IsInitializedArrayOfStrings = (lU >= lL)
            Exit Function

        Catch ex As Exception
            IsInitializedArrayOfStrings = False

        End Try

    End Function

    Private Sub CleanAssemblyList(ByRef strAssemblyFiles() As String, ByRef AssemblyCount As Integer)
        Dim strTempFileList() As String
        Dim TempInputFilename As String
        Dim TempResultsFilename As String
        Dim FilePointer As Integer
        Dim i As Integer

        ReDim strTempFileList(AssemblyCount)

        ' Get temp filenames.
        TempInputFilename = GetTempFile()
        TempResultsFilename = GetTempFile()

        ' Open the file.
        FilePointer = FreeFile()
        FileOpen(FilePointer, TempInputFilename, OpenMode.Output)

        ' Write the list of assemblies to the temp file.
        For i = 0 To AssemblyCount
            PrintLine(FilePointer, strAssemblyFiles(i))
        Next

        FileClose(FilePointer)

        txtStatus.Text = "Determining top level assemblies ..."
        txtStatus.Update()
        ExecCmd(SolidEdgePath & "\ftla.exe " & TempInputFilename & " " & TempResultsFilename)

        ' Open the new list and read it.
        FilePointer = FreeFile()
        FileOpen(FilePointer, TempResultsFilename, OpenMode.Input)

        AssemblyCount = -1
        Do While Not EOF(FilePointer)
            AssemblyCount = AssemblyCount + 1
            strAssemblyFiles(AssemblyCount) = LineInput(FilePointer)
        Loop

        FileClose(FilePointer)

        ' Delete the temp files.
        Kill(TempInputFilename)
        Kill(TempResultsFilename)
    End Sub

    Public Sub ExecCmd(ByRef cmdline As String)
        Dim proc As PROCESS_INFORMATION
        Dim start As STARTUPINFO = Nothing
        Dim ret As Integer

        ' Initialize the STARTUPINFO structure:
        start.dwFlags = STARTF_USESHOWWINDOW
        start.wShowWindow = SW_HIDE
        start.cb = Len(start)

        ' Start the shelled application:
        ret = CreateProcessA(0, cmdline, 0, 0, 1, NORMAL_PRIORITY_CLASS, 0, 0, start, proc)

        ' Wait for the shelled application to finish:
        ret = WaitForSingleObject(proc.hProcess, INFINITE)
        ret = CloseHandle(proc.hProcess)
    End Sub

    Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
        Dim strLogFile As String
        ReDim strFolders(1)
        Dim valid As Boolean = False

        strLogFile = "\OpenSave" & strDate & ".log"

        If chkInsight.Checked Then
            txtLogFile.Text = System.Windows.Forms.Application.StartupPath() & strLogFile
            ' Get path to SearchScope.txt
            OpenFileDialog1.Filter = "Text files (*.txt)|*.txt"
            OpenFileDialog1.FileName = ""
            OpenFileDialog1.ShowDialog()
            strSearchScopeFile = OpenFileDialog1.FileName
            If strSearchScopeFile = "" Then
                Exit Sub
            End If

            lblPaths.Text = strSearchScopeFile
            lblPaths.Update()

            LoadInsightPaths()
            SetFileList(FolderPath)

            FolderPath = lstPath.Items(0)

        Else
            FolderBrowserDialog1.ShowDialog()
            FolderPath = FolderBrowserDialog1.SelectedPath
            FileSystem.CurrentDirectory = FolderPath

            TopLevelFolder = False
            If FolderPath.Substring(FolderPath.Length - 1, 1) = Slash Then
                TopLevelFolder = True
                txtLogFile.Text = FolderPath.Substring(0, FolderPath.Length - 1) & strLogFile
            Else
                txtLogFile.Text = FolderPath & strLogFile
            End If


            strFolders(0) = FolderPath

            ' if processing subfolders as well, then let's get the folder list here
            If optAllFiles.Checked Then
                GetSubFolders(FolderPath)
            End If

            FolderList()
            LoadSEFiles()
        End If

    End Sub

    Private Sub GetSubFolders(ByVal strDir)
        Dim courier As String
        Dim strNewDirs() As String = Nothing
        If strDir.substring(strDir.length - 1, 1) = Slash Then strDir = strDir.substring(0, strDir.length - 1)

        courier = Dir(strDir & "\", FileAttribute.Directory) ' Retrieve the first entry.
        Do While courier <> "" ' Start the loop.
            ' Ignore the current directory and the encompassing directory.
            If courier <> "." And courier <> ".." Then
                ' Use bitwise comparison to make sure MyName is a directory.
                If (GetAttr(strDir & "\" & courier) And FileAttribute.Directory) = FileAttribute.Directory Then
                    If Not IsInitializedArrayOfStrings(strNewDirs) Then
                        ReDim strNewDirs(0)
                    Else
                        ReDim Preserve strNewDirs(UBound(strNewDirs) + 1)
                    End If

                    strNewDirs(UBound(strNewDirs)) = strDir & "\" & courier

                    ' Let's hold on to all the folders we will consider
                    ReDim Preserve strFolders(UBound(strFolders) + 1)
                    strFolders(UBound(strFolders) - 1) = strDir & "\" & courier
                End If ' it represents a directory.
            End If
            courier = Dir() ' Get next entry.
        Loop

        If IsInitializedArrayOfStrings(strNewDirs) Then
            For i = LBound(strNewDirs) To UBound(strNewDirs)
                GetSubFolders(strNewDirs(i))
            Next
        End If

    End Sub

    Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
        If btnExit.Text = "Stop" Then
            StopProcess = True
            btnExit.Text = "Cancel"
        Else
            End
        End If
    End Sub

    Private Sub chkPart_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkPart.CheckedChanged
        If chkPart.Checked Then
            FilterSet(0) = True
        Else
            FilterSet(0) = False
        End If
        SetFilters()
        If chkInsight.Checked Then
            btnUpdateFiles.Enabled = True
            btnProcess.Enabled = False
            lblFileList.Text = strUpdateFileList
            lblFileList.Update()
        Else
            LoadFileList()
        End If

    End Sub

    Private Sub chkSheetmetal_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkSheetmetal.CheckedChanged
        If chkSheetmetal.Checked Then
            FilterSet(1) = True
        Else
            FilterSet(1) = False
        End If
        SetFilters()
        If chkInsight.Checked Then
            btnUpdateFiles.Enabled = True
            btnProcess.Enabled = False
            lblFileList.Text = strUpdateFileList
            lblFileList.Update()
        Else
            LoadFileList()
        End If

    End Sub

    Private Sub chkAssembly_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkAssembly.CheckedChanged
        If chkAssembly.Checked Then
            FilterSet(2) = True
        Else
            FilterSet(2) = False
        End If
        SetFilters()
        If chkInsight.Checked Then
            btnUpdateFiles.Enabled = True
            btnProcess.Enabled = False
            lblFileList.Text = strUpdateFileList
            lblFileList.Update()
        Else
            LoadFileList()
        End If

    End Sub

    Private Sub chkDraft_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkDraft.CheckedChanged
        If chkDraft.Checked Then
            FilterSet(3) = True
        Else
            FilterSet(3) = False
        End If
        SetFilters()
        If chkInsight.Checked Then
            btnUpdateFiles.Enabled = True
            btnProcess.Enabled = False
            lblFileList.Text = strUpdateFileList
            lblFileList.Update()
        Else
            LoadFileList()
        End If

    End Sub

    Private Sub chkWeldment_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkWeldment.CheckedChanged
        If chkWeldment.Checked Then
            FilterSet(4) = True
        Else
            FilterSet(4) = False
        End If
        SetFilters()
        If chkInsight.Checked Then
            btnUpdateFiles.Enabled = True
            btnProcess.Enabled = False
            lblFileList.Text = strUpdateFileList
            lblFileList.Update()
        Else
            LoadFileList()
        End If

    End Sub

    Sub SetFilters()
        nFilters = -1
        If chkPart.Checked Then
            nFilters = nFilters + 1
            Filters(nFilters) = "*.par"
        End If
        If chkSheetmetal.Checked Then
            nFilters = nFilters + 1
            Filters(nFilters) = "*.psm"
        End If
        If chkAssembly.Checked Then
            nFilters = nFilters + 1
            Filters(nFilters) = "*.asm"
        End If
        If chkDraft.Checked Then
            nFilters = nFilters + 1
            Filters(nFilters) = "*.dft"
        End If
        If chkWeldment.Checked Then
            nFilters = nFilters + 1
            Filters(nFilters) = "*.pwd"
        End If

    End Sub

    Private Sub WritePartLogInformation(ByRef objDoc As Object, ByRef LogFile As Integer)
        Dim i As Integer
        Dim objFeatures As Object
        Dim objPartData As New clsPartDocument
        Dim ErrMessage As String = ""

        ' Write PartFilename.
        PrintLine(LogFile, "Part/Sheetmetal Document> " & objDoc.FullName)

        ' Get the feature information.
        If objDoc.Models.Count > 0 Then
            objFeatures = objDoc.Models.item(1).Features
            For i = 1 To objFeatures.Count
                On Error Resume Next
                If objFeatures(i).status(ErrMessage) = SolidEdgeConstants.FeatureStatusConstants.igFeatureFailed Then
                    If Err.Number Then
                        PrintLine(LogFile, "    ******* Skipping status reporting for feature # " & i & ": Automation interface not implemented for this feature type.")
                    End If
                    objPartData.FailedItems.Add(objFeatures(i).Name & ", " & ErrMessage)
                ElseIf objFeatures(i).status(ErrMessage) = SolidEdgeConstants.FeatureStatusConstants.igFeatureWarned Then
                    objPartData.WarnedItems.Add(objFeatures(i).Name & ", " & ErrMessage)
                End If
            Next

            PrintLine(LogFile, "   Number of Failed Features = " & objPartData.FailedItems.Count)
            If objPartData.FailedItems.Count > 0 Then
                ' Write failed Occurrences.
                For i = 1 To objPartData.FailedItems.Count
                    PrintLine(LogFile, "     " & objPartData.FailedItems.Item(i).Name)
                Next
            End If

            ' Write underconstrained Occurrences.
            PrintLine(LogFile, "   Number of Warned Features = " & objPartData.WarnedItems.Count)
            If objPartData.WarnedItems.Count > 0 Then
                For i = 1 To objPartData.WarnedItems.Count
                    PrintLine(LogFile, "     " & objPartData.WarnedItems.Item(i).Name)
                Next
            End If
        End If

        PrintLine(LogFile, "")
    End Sub

    Private Sub GetCurrentAssemblyState(ByRef objDoc As Object, ByRef Assemblies() As AssemblyData, ByRef AssemblyCount As Integer, ByRef Version As Integer)
        Dim i As Integer
        Dim MatchFound As Boolean
        Dim objOccurrence As Object
        Dim objPartDoc As Object
        Dim CurrentAssembly As Integer
        Dim tmpOccurrence As Object
        Dim TmpFile As Integer

        txtSubAsm.Text = "ASM Loop " & Version - 3 & ": " & objDoc.FullName
        txtSubAsm.Update()

        ' Initialize flag
        MatchFound = False

        ' Check to see if current assembly has already been processed.
        For i = 0 To AssemblyCount
            If objDoc.FullName = Assemblies(i).Name Then
                MatchFound = True
                Exit For
            End If
        Next

        ' If no match was found, process this assembly.
        If Not MatchFound Then
            ' Increment the counter
            AssemblyCount = AssemblyCount + 1

            ' Add one more index to the assembly data array.
            ReDim Preserve Assemblies(AssemblyCount + 1)

            ' Save the assembly data.
            Assemblies(AssemblyCount).Name = objDoc.FullName
            Assemblies(AssemblyCount).PartCount = objDoc.Occurrences.Count

            ' Initialize the flag indicating whether this assembly has been written out or not.
            Assemblies(AssemblyCount).Processed = False

            ' Allocate memory for the part information.
            If objDoc.Occurrences.Count > 0 Then
                ReDim Assemblies(AssemblyCount).Occurrences(objDoc.Occurrences.Count)
            End If

            ' Save the current count in a local variable so it doesn't get changed.
            ' first time thru should be 0
            CurrentAssembly = AssemblyCount

            ' Get the information for the Occurrences within this assembly.
            For i = 0 To objDoc.Occurrences.Count - 1
                objOccurrence = objDoc.Occurrences.item(i + 1)

                'test for saving subassemblies
                'objOccurrence.makewritable()

                ' Save the name.
                Assemblies(CurrentAssembly).Occurrences(i).Name = objOccurrence.Name

                ' Save the part itself.
                Assemblies(CurrentAssembly).Occurrences(i).Occurrence = objOccurrence

                ' Save the transformation matrix.  .Net does not like arrays dimensioned inside structure
                ' so have to do outside to initialize
                ReDim Assemblies(CurrentAssembly).Occurrences(i).Matrix(16)

                objOccurrence.GetMatrix(Assemblies(CurrentAssembly).Occurrences(i).Matrix)

                ' inserting a sleep to give SE a chance for very large assemblies
                Sleep(70)

                If objOccurrence.Relations3d.Count = 0 Then
                    ' Special case for Occurrences that are components of a pattern.
                    ' Since pattern Occurrences aren't specifically identified this assumes
                    ' that any part that doesn't have any relationships is a pattern part.
                    Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartPattern
                ElseIf objOccurrence.status = SolidEdgeAssembly.PartStatusConstants.igPartStatusFixed Or objOccurrence.status = SolidEdgeAssembly.PartStatusConstants.igPartStatusWellDefined Then
                    Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartOK
                ElseIf objOccurrence.status = SolidEdgeAssembly.PartStatusConstants.igPartStatusUnderDefined Then
                    Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartUnderConstrained
                Else
                    Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartFailed
                End If

                ' Check to see if this Occurrence was loaded.
                If Version = 5 Then
                    Try
                        tmpOccurrence = objOccurrence.PartDocument
                    Catch ex As Exception
                        Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartNotLoaded
                    End Try
                ElseIf objOccurrence.Subassembly Then
                    ' Attempt to open the file to see if it exists.
                    Try
                        TmpFile = FreeFile()
                        FileOpen(TmpFile, objOccurrence.PartFileName, OpenMode.Input)
                        FileClose(TmpFile)
                    Catch ex As Exception
                        Assemblies(CurrentAssembly).Occurrences(i).State = PartState.PartNotLoaded
                    End Try
                End If

                ' If this Occurrence is an assembly, call this function again.
                If objOccurrence.Subassembly And Assemblies(CurrentAssembly).Occurrences(i).State <> PartState.PartNotLoaded Then
                    ' interative calls can throw an exception unless we pass a specific object for objDoc
                    objPartDoc = objOccurrence.PartDocument
                    GetCurrentAssemblyState(objPartDoc, Assemblies, AssemblyCount, Version)
                End If
            Next
        End If
    End Sub

    Private Sub WriteAssemblyLogInformation(ByRef OldAssemblies() As AssemblyData, ByRef OldAssemblyCount As Integer, ByRef NewAssemblies() As AssemblyData, ByRef NewAssemblyCount As Integer, ByRef LogFile As Integer)
        Dim i As Integer
        Dim j As Integer
        Dim k As Integer
        Dim m As Integer
        Dim OldState As String = ""
        Dim StateChanged As Boolean
        Dim NewState As String = ""
        Dim PartChanged As Boolean
        Dim MoveTolerance As Double
        Dim AngleTolerance As Double
        Dim StatusWritten As Boolean

        AngleTolerance = 0.001
        MoveTolerance = 0.00002
        If chkAssemblyDifference.Checked Then
            ' Look through the assemblies to see if there are any that haven't been processed.
            For i = 0 To OldAssemblyCount
                If Not OldAssemblies(i).Processed Then
                    ' Set flag indicating it's been processed.
                    OldAssemblies(i).Processed = True

                    'If chkProcessReleased.Checked = False Then
                    '    strSEStatus = GetStatus(OldAssemblies(i).Name)
                    '    If UCase(strSEStatus) = "RELEASED" Or UCase(strSEStatus) = "IN WORK" Or UCase(strSEStatus) = "BASELINED" Or UCase(strSEStatus) = "OBSOLETE" Then
                    '        PrintLine(LogFile, "***Document is either released, baselined, or obselete and was not processed. > " & OldAssemblies(i).Name)
                    '        PrintLine(LogFile, "")
                    '        GoTo SKIPTONEXT
                    '    End If
                    'End If


                    ' Check to see if the position or orientation changed.
                    PartChanged = False

                    ' find the corresponding data in the new list.
                    For j = 0 To NewAssemblyCount
                        StatusWritten = False

                        If OldAssemblies(i).Name = NewAssemblies(j).Name Then
                            PrintLine(LogFile, "Assembly Document> " & OldAssemblies(i).Name)

                            ' Iterate through all of the Occurrences of the assembly.
                            For k = 0 To OldAssemblies(i).PartCount - 1
                                If OldAssemblies(i).Occurrences(k).State <> PartState.PartPattern Then
                                    StateChanged = False
                                    ' Check to see if the state remained the same.
                                    If OldAssemblies(i).Occurrences(k).State <> NewAssemblies(j).Occurrences(k).State Then
                                        StateChanged = True

                                        Select Case OldAssemblies(i).Occurrences(k).State
                                            Case PartState.PartOK
                                                OldState = "Part OK"
                                            Case PartState.PartFailed
                                                OldState = "Part Failed"
                                            Case PartState.PartUnderConstrained
                                                OldState = "Part UnderConstrained"
                                        End Select

                                        Select Case NewAssemblies(j).Occurrences(k).State
                                            Case PartState.PartOK
                                                NewState = "Part OK"
                                            Case PartState.PartFailed
                                                NewState = "Part Failed"
                                            Case PartState.PartUnderConstrained
                                                NewState = "Part UnderConstrained"
                                            Case PartState.PartNotLoaded
                                                NewState = "Part Not Loaded"
                                        End Select
                                    End If

                                    ' Check to see if the before and after transform is different.
                                    If OldAssemblies(i).Occurrences(k).State = PartState.PartOK Then
                                        'For m = 1 To 11
                                        For m = 0 To 10
                                            If System.Math.Abs(OldAssemblies(i).Occurrences(k).Matrix(m) - NewAssemblies(j).Occurrences(k).Matrix(m)) > AngleTolerance Then
                                                PartChanged = True
                                                Exit For
                                            End If
                                        Next

                                        'For m = 13 To 15
                                        For m = 12 To 14
                                            If System.Math.Abs(OldAssemblies(i).Occurrences(k).Matrix(m) - NewAssemblies(j).Occurrences(k).Matrix(m)) > MoveTolerance Then
                                                PartChanged = True
                                                Exit For
                                            End If
                                        Next
                                    End If

                                    If StateChanged And PartChanged Then
                                        PrintLine(LogFile, "   " & OldAssemblies(i).Occurrences(k).Name & "> State changed from " & OldState & " to " & NewState & " and")
                                        PrintLine(LogFile, Space(Len(OldAssemblies(i).Occurrences(k).Name) + 5) & "part moved or rotated from original position.")
                                        If chkGroundParts.CheckState = System.Windows.Forms.CheckState.Checked Then
                                            PrintLine(LogFile, Space(Len(OldAssemblies(i).Occurrences(k).Name) + 5) & "Part's existing relationships have been deleted and ")
                                            PrintLine(LogFile, Space(Len(OldAssemblies(i).Occurrences(k).Name) + 5) & "part has been grounded in its original position.")
                                            Call GroundPart(NewAssemblies(j).Occurrences(k), OldAssemblies(i).Occurrences(k))
                                        End If
                                        StatusWritten = True
                                    ElseIf StateChanged Then
                                        PrintLine(LogFile, "   " & OldAssemblies(i).Occurrences(k).Name & "> State changed from " & OldState & " to " & NewState)
                                        StatusWritten = True
                                    ElseIf PartChanged Then
                                        PrintLine(LogFile, "   " & OldAssemblies(i).Occurrences(k).Name & "> Moved or rotated from original position.")
                                        If chkGroundParts.CheckState = System.Windows.Forms.CheckState.Checked Then
                                            PrintLine(LogFile, Space(Len(OldAssemblies(i).Occurrences(k).Name) + 5) & "Part's existing relationships have been deleted and ")
                                            PrintLine(LogFile, Space(Len(OldAssemblies(i).Occurrences(k).Name) + 5) & "part has been grounded in its original position.")
                                            Call GroundPart(NewAssemblies(j).Occurrences(k), OldAssemblies(i).Occurrences(k))
                                        End If
                                        StatusWritten = True
                                    End If
                                End If
                            Next

                            If Not StatusWritten Then
                                PrintLine(LogFile, "   Processed Successfully")
                            End If

                            PrintLine(LogFile, "")
                        End If
                    Next
                End If
SKIPTONEXT:
            Next
        Else
            ' Iterate through all of the assemblies.
            For i = 0 To NewAssemblyCount
                ' Look for assemblies not processed yet.
                If Not NewAssemblies(i).Processed Then
                    ' Initialize flag indicating no status has been written for this assembly yet.
                    StatusWritten = False

                    ' Set flag indicating it's been processed.
                    NewAssemblies(i).Processed = True

                    PrintLine(LogFile, "Assembly Document> " & NewAssemblies(i).Name)

                    ' Iterate through all of the Occurrences of the assembly.
                    For j = 1 To NewAssemblies(i).PartCount
                        Select Case NewAssemblies(i).Occurrences(j).State
                            Case PartState.PartOK, PartState.PartPattern
                                NewState = "Part OK"
                            Case PartState.PartFailed
                                NewState = "Part Failed"
                            Case PartState.PartUnderConstrained
                                NewState = "Part UnderConstrained"
                            Case PartState.PartNotLoaded
                                NewState = "Unable to load document"
                        End Select

                        If NewState <> "Part OK" Then
                            PrintLine(LogFile, "   " & NewAssemblies(i).Occurrences(j).Name & "> " & NewState)

                            ' Set flag indicating status information has been written for this assembly.
                            StatusWritten = True
                        End If
                    Next

                    ' Write message when not other problems were found.
                    If Not StatusWritten Then
                        PrintLine(LogFile, "   Processed Successfully")
                    End If

                    PrintLine(LogFile, "")
                End If
            Next
        End If
    End Sub

    Private Sub GroundPart(ByRef NewPart As PartData, ByRef OldPart As PartData)
        Dim i As Integer

        ' Delete the existing relationships from the part.
        For i = NewPart.Occurrence.Relations3d.Count To 1 Step -1
            NewPart.Occurrence.Relations3d(i).DELETE()
        Next

        ' Ground the part.
        NewPart.Occurrence.Parent.Parent.Relations3d.AddGround(NewPart.Occurrence)

        ' Reposition the part back to its original position.
        NewPart.Occurrence.PutMatrix(Matrix:=OldPart.Matrix, Replace:=True)
    End Sub

    Private Sub WriteDraftLogInformation(ByRef objDoc As Object, ByRef ViewCount As Integer, ByRef LogFile As Integer, ByRef V4Dimensions() As DimensionData, ByRef DimensionCount As Integer, ByRef ConfigurationExists() As AssemblyConfigurationsExist, ByRef AssemblyCount As Integer)
        Dim i As Integer
        Dim j As Integer
        Dim k As Integer
        Dim m As Integer
        Dim DimName As String
        Dim objSheets As Object
        Dim objGroup As Object
        Dim objTmpModelDocument As Object
        Dim iDimCount As Integer
        Dim LinkFilename As String
        Dim ConfigFound As Boolean
        Dim ConfigFile As String
        Dim TmpFile As Integer

        PrintLine(LogFile, "DraftDocument> " & objDoc.FullName)

        If Not chkUpdateDV.Checked Then
            PrintLine(LogFile, "   Drawing views not updated.")
        Else
            PrintLine(LogFile, "   Processed " & ViewCount & " drawing views.")

            For i = 1 To objDoc.ModelLinks.Count
                LinkFilename = objDoc.ModelLinks.Item(i).filename

                On Error Resume Next
                objTmpModelDocument = objDoc.ModelLinks.Item(i).ModelDocument
                If Err.Number Then
                    PrintLine(LogFile, "   The referenced document '" & LinkFilename & "' is not accessible.")
                Else
                    ' If the link is to an assembly check to see if a configuration exists.
                    If LinkFilename.EndsWith("asm") Then
                        ' Check to see if the current assembly is in the list.
                        ConfigFound = False
                        For j = 1 To AssemblyCount
                            If ConfigurationExists(j).AssemblyName = objDoc.FullName And Not ConfigurationExists(j).ConfigurationExists Then
                                ConfigFound = True
                                PrintLine(LogFile, "   The configuration file for '" & LinkFilename & "' is missing.")
                                PrintLine(LogFile, "      If there are exploded views of this assembly they will be incorrect.")
                                Exit For
                            End If
                        Next

                        ' The assembly is not a top level assembly so it's not in the list.
                        ' Check for the configuration now.
                        If Not ConfigFound Then
                            ' Attempt to open the configuration file to see if it exists.
                            ConfigFile = LinkFilename.Substring(0, LinkFilename.Length - 3) & "cfg"
                            ' Determine whether the configuration exists for not by attempting to open the file.
                            On Error Resume Next
                            TmpFile = FreeFile()
                            FileOpen(TmpFile, ConfigFile, OpenMode.Input)
                            If Err.Number Then
                                PrintLine(LogFile, "   The configuration file for '" & LinkFilename & "' is missing.")
                                PrintLine(LogFile, "      If there are exploded views of this assembly they will be incorrect.")
                            Else
                                FileClose(TmpFile)
                            End If
                        End If
                    End If
                End If

                Err.Clear()
                On Error GoTo 0
            Next

            For i = 1 To objDoc.Sheets.Count
                For j = 1 To objDoc.Sheets.Item(i).DrawingViews.Count
                    If objDoc.Sheets.Item(i).DrawingViews.Item(j).DrawingViewType <> SolidEdgeConstants.DrawingViewTypeConstants.igUserView Then
                        ' Check to see if the ModelDocument is accessible.  If not, assume the file doesn't exist.
                        On Error Resume Next
                        objTmpModelDocument = objDoc.Sheets.Item(i).DrawingViews.Item(j).ModelLink.ModelDocument
                        If Err.Number Then
                            PrintLine(LogFile, "   Document '" & objDoc.Sheets.Item(i).DrawingViews.Item(j).ModelLink.filename & "' referenced by drawing view '" & objDoc.Sheets(i).DrawingViews(j).Caption & "' is not accessible.")
                        End If
                        Err.Clear()
                        On Error GoTo 0
                    End If
                Next
            Next

            PrintLine(LogFile, "   Total number of dimensions> " & DimensionCount)

            ' Check for any changes in the value of dimensions.
            iDimCount = 0
            For i = 1 To objDoc.Sheets.Count
                For j = 1 To objDoc.Sheets.Item(i).Dimensions.Count
                    DimName = objDoc.Sheets.Item(i).Dimensions.Item(j).Name
                    For k = 0 To DimensionCount - 1
                        If DimName = V4Dimensions(k).Name Then
                            V4Dimensions(k).Validated = True

                            If System.Math.Abs(V4Dimensions(k).Value - objDoc.Sheets.Item(i).Dimensions.Item(j).Value) > 0.0000000001 Then
                                iDimCount = iDimCount + 1
                                objDoc.Sheets.Item(i).Dimensions.Item(j).OverrideString = "**Value Changed**"
                                Exit For
                            End If
                        End If
                    Next
                Next
            Next
            PrintLine(LogFile, "   Number of dimensions where value changed> " & iDimCount)

            '** Check for any dropped dimensions.

            ' Set a reference to the sheets collection.
            objSheets = objDoc.Sheets

            ' Iterate through all of the sheets of the document.
            iDimCount = 0
            For i = 1 To objSheets.Count
                ' Iterate through all of the groups on the current sheet.
                For j = 1 To objSheets.Item(i).Groups.Count
                    ' Set a reference to the current group.
                    objGroup = objSheets.Item(i).Groups.Item(j)

                    ' Iterate through the contents of the group.
                    For k = 1 To objGroup.Count
                        ' Look for any dimensions in the group.
                        If objGroup(k).Type = SolidEdgeConstants.ObjectType.igDimension Then
                            DimName = objGroup(k).Name
                            iDimCount = iDimCount + 1

                            ' Find the corresponding V4 dimension and flag as being processed.
                            For m = 0 To DimensionCount - 1
                                If DimName = V4Dimensions(m).Name Then
                                    V4Dimensions(m).Validated = True
                                    Exit For
                                End If
                            Next
                        End If
                    Next
                Next
            Next
            PrintLine(LogFile, "   Number of dimensions that were dropped> " & iDimCount)

            ' Check to see if any dimensions existed in V4 that haven't been validated.
            iDimCount = 0
            For i = 0 To DimensionCount - 1
                If Not V4Dimensions(i).Validated Then
                    iDimCount = iDimCount + 1
                End If
            Next
            PrintLine(LogFile, "   Number of dimensions that were deleted> " & iDimCount)
        End If

        PrintLine(LogFile, "")
    End Sub

    Private Sub WriteBadDocumentLogInformation(ByRef LogFile As Integer, ByRef DocName As String, ByRef ErrorMessage As String)
        PrintLine(LogFile, "BadDocument> " & DocName)
        PrintLine(LogFile, "    Error> " & ErrorMessage)
        PrintLine(LogFile, "")
    End Sub


    Public Function WriteWeldmentLogInfo(ByRef objDoc As Object, ByRef LogFile As Integer) As Object

        Dim objWeldment As Object
        Dim objWeldments As Object
        Dim objFeatures As Object
        Dim i As Integer
        Dim ErrMessage As String = ""
        Dim objWeldmentData As New clsWeldmentDocument
        ' Write PartFilename.
        PrintLine(LogFile, "Weldment Document> " & objDoc.FullName)

        objWeldments = objDoc.WeldmentModels
        i = objWeldments.count
        If objDoc.WeldmentModels.Count > 0 Then
            For Each objWeldment In objWeldments
                i = objWeldment.assemblyweldments.count
                'Note hard-code to one as you can only link 1 assembly to a weldment file
                If objWeldment.AssemblyWeldments.Item(1).LinkStatus = SolidEdgeConstants.WeldmentLinkStatusConstants.seLinkBroken Then
                    PrintLine(LogFile, "   Broken Link.  Can not find : " & objWeldment.filename)
                End If

                objFeatures = objWeldment.Features
                For i = 1 To objFeatures.Count
                    On Error Resume Next
                    If objFeatures.Item(i).status(ErrMessage) = SolidEdgeConstants.FeatureStatusConstants.igFeatureFailed Then
                        If Err.Number And i <> 1 Then
                            PrintLine(LogFile, "    ******* Skipping status reporting for feature # " & i & ": Automation interface not implemented for this feature type.")
                        End If
                        objWeldmentData.FailedItems.Add(objFeatures.Item(i).Name & ", " & ErrMessage)
                    ElseIf objFeatures(i).status(ErrMessage) = SolidEdgeConstants.FeatureStatusConstants.igFeatureWarned Then
                        objWeldmentData.WarnedItems.Add(objFeatures.Item(i).Name & ", " & ErrMessage)
                    End If
                Next

                PrintLine(LogFile, "   Number of Failed Features = " & objWeldmentData.FailedItems.Count)
                If objWeldmentData.FailedItems.Count > 0 Then
                    ' Write failed Occurrences.
                    For i = 1 To objWeldmentData.FailedItems.Count
                        PrintLine(LogFile, "     " & objWeldmentData.FailedItems.Item(i).Name)
                    Next
                End If

                ' Write underconstrained Occurrences.
                PrintLine(LogFile, "   Number of Warned Features = " & objWeldmentData.WarnedItems.Count)
                If objWeldmentData.WarnedItems.Count > 0 Then
                    For i = 1 To objWeldmentData.WarnedItems.Count
                        PrintLine(LogFile, "     " & objWeldmentData.WarnedItems.Item(i).Name)
                    Next
                End If

            Next objWeldment
        End If
        PrintLine(LogFile, "     ")
    End Function

    Private Sub lstFiles_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstFiles.SelectedIndexChanged
        'If Not optSelected.Checked Then optSelected.Checked = True
        ReDim strTempFilenames(intTotFileNameCount)

        ' Load the selected filenames into the array.
        intFileNameCount = -1
        For i = 0 To intTotFileNameCount - 1
            If lstFiles.GetSelected(i) Then
                intFileNameCount = intFileNameCount + 1
                If chkInsight.Checked Then
                    strTempFilenames(intFileNameCount) = lstFiles.Items(i)
                Else
                    If TopLevelFolder = True Then
                        strTempFilenames(intFileNameCount) = FolderPath & lstFiles.Items(i)
                    Else
                        strTempFilenames(intFileNameCount) = FolderPath & Slash & lstFiles.Items(i)
                    End If
                End If
            End If
        Next
        txtStatus.Text = "Files found, proceed with processing or select options"
        txtStatus.Update()

    End Sub

    Private Sub chkInsight_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkInsight.CheckedChanged
        Dim i As Integer
        lstPath.Items.Clear()
        lstFiles.Items.Clear()

        If chkInsight.Checked Then
            lstFiles.Items.Clear()
            Slash = "/"
            If StrMngdFolder = "" Then
                ' Get path to SearchScope.txt

                strSearchScopeFile = QueryValue(HKEY_CURRENT_USER, strRegistryBase & "\Global", "Searchscope")

                If strSearchScopeFile = Nothing Then strSearchScopeFile = ""

                If strSearchScopeFile.Length > 0 Then strSearchScopeFile = strSearchScopeFile.Substring(0, strSearchScopeFile.Length - 1)
                If FileExists((strSearchScopeFile)) = False Then
                    txtStatus.Text = "Cannot find SearchScope.txt file, browse to file"
                    txtStatus.Update()
                    Exit Sub
                Else
                    txtStatus.Text = "Reading SearchScope.txt"
                    txtStatus.Update()
                End If
                btnBrowse.Text = "Browse to SearchScope"
                lstFiles.MultiColumn = False
                lstFiles.HorizontalScrollbar = False
            End If
        Else
            Slash = "\"
            chkInsight.Checked = False
            btnBrowse.Text = "Browse to Folder"
            lstFiles.MultiColumn = True
            If strFolders(0) = "" Then
                FolderPath = System.Windows.Forms.Application.StartupPath()
                strFolders(0) = FolderPath
                TopLevelFolder = False
                If FolderPath.Substring(FolderPath.Length - 1, 1) = Slash Then TopLevelFolder = True
                'Else
            End If
            If optAllInDirectory.Checked Then
                lstPath.Items.Add(strFolders(0))
            Else
                For i = 0 To UBound(strFolders) - 1
                    lstPath.Items.Add(strFolders(i))
                Next
            End If
            FolderPath = strFolders(0)
            StrMngdFolder = ""
        End If


        If chkInsight.Checked Then
            If StrMngdFolder = "" Then
                LoadInsightPaths()
            Else
                FolderPath = StrMngdFolder
                For i = 0 To UBound(StrMngdFolders)
                    lstPath.Items.Add(StrMngdFolders(i))
                Next

            End If

        End If
        btnUpdateFiles.Enabled = False
        btnProcess.Enabled = True
        LoadFileList()
    End Sub

    Private Sub optAllFiles_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles optAllFiles.CheckedChanged
        If optAllFiles.Checked Then
            lstFiles.SelectedItems.Clear()

            If chkInsight.Checked = True Then
                ' Managed
                SetFileList(FolderPath)

            Else
                ' Unmanaged
                GetSubFolders(FolderPath)
                FolderList()
                LoadSEFiles()
            End If
        Else
            If chkInsight.Checked = False Then
                lblFileList.Text = strProcessFiles
                lblFileList.Update()
                If lstFiles.SelectedItems.Count > 0 Then
                    lstPath.Items.Clear()
                    lstPath.Items.Add(FolderPath)
                End If
            End If
        End If
    End Sub

    Private Sub optAllInDirectory_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles optAllInDirectory.CheckedChanged
        If optAllInDirectory.Checked Then
            lstFiles.SelectedItems.Clear()
            lstPath.Items.Clear()
            If FolderPath <> "" Then lstPath.Items.Add(FolderPath)
            ' should not be necessary but optSelected change to other does not update correctly otherwise

            optAllInDirectory.Checked = True
            If chkInsight.Checked Then
                SetFileList(FolderPath)
            Else
                ReDim strFolders(1)
                strFolders(0) = FolderPath
                LoadSEFiles()
            End If
        End If
    End Sub


    Private Sub lstPath_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstPath.SelectedIndexChanged
        ' This is intended to provide a means of allowing the user to select a subfolder or folders for processing
        ' The trick here will be to properly update the lstFiles as that drives the file list for processing.

        Dim i, j, nFolders As Integer
        nFolders = lstPath.Items.Count - 1


        If lstPath.SelectedItems.Count > 0 Then

            ' save unmanaged folders
            If chkInsight.Checked = False And bolFolder = False Then
                bolFolder = True
                ReDim StrUnMngdFolders(nFolders + 1)
                For i = 0 To nFolders
                    StrUnMngdFolders(i) = strFolders(i)
                Next
            End If

            ReDim strFolders(0)
            j = -1
            For i = 0 To nFolders
                If lstPath.GetSelected(i) Then
                    j = j + 1
                    If chkInsight.Checked Then
                        If j = 0 Then
                            FolderPath = lstPath.Items(i)
                        Else
                            FolderPath = FolderPath & ";" & lstPath.Items(i)
                        End If

                    Else

                        ReDim Preserve strFolders(j + 1)
                        strFolders(j) = lstPath.Items(i)

                    End If
                End If
            Next

            If chkInsight.Checked Then
                btnUpdateFiles.Enabled = True
                btnProcess.Enabled = False
                lblFileList.Text = strUpdateFileList
                lblFileList.Update()
            Else
                LoadFileList()
                btnUpdateFiles.Enabled = False
                btnProcess.Enabled = True
                lblFileList.Text = strProcessFiles
                lblFileList.Update()
            End If

        Else

            If chkInsight.Checked Then
                btnUpdateFiles.Enabled = True
                btnProcess.Enabled = False
                lblFileList.Text = strUpdateFileList
                lblFileList.Update()
            Else
                ReDim strFolders(nFolders + 1)
                For i = 0 To nFolders
                    strFolders(i) = StrUnMngdFolders(i)
                Next
                LoadFileList()
                btnUpdateFiles.Enabled = False
                btnProcess.Enabled = True
                lblFileList.Text = strProcessFiles
                lblFileList.Update()
            End If

        End If

    End Sub

    Private Sub LoadInsightPaths()
        Dim strSearchScopeText As String
        Dim valid As Boolean
        Dim i As Integer

        lstPath.Items.Clear()
        ' Open SearchSAcope
        Try
            FileOpen(1, strSearchScopeFile, OpenMode.Input)
        Catch ex As Exception
            MsgBox("error opening file")
            Exit Sub
        End Try

        ' Now let's parse the SearchScope file for locations
        Do Until EOF(1)
            strSearchScopeText = LineInput(1)
            If strSearchScopeText.Length > 7 Then
                ' Fix for PR# 6968476 where there are uncommented lines related Search Service Application
                ' that this routine has no way to interpret or set path for.  
                ' Set test to be explicit for "http://"
                'If strSearchScopeText.Substring(0, 2) <> "\\" Then
                If strSearchScopeText.Substring(0, 7) = "http://" Then
                    lstPath.Items.Add(strSearchScopeText)
                    FolderPath = lstPath.Items(0)
                    valid = True
                End If
            End If
        Loop
        If lstPath.Items.Count > 1 Then
            StrMngdFolders(0) = lstPath.Items(0)
            For i = 1 To lstPath.Items.Count - 1
                ReDim Preserve StrMngdFolders(i)
                StrMngdFolders(i) = lstPath.Items(i)
                FolderPath = FolderPath & ";" & lstPath.Items(i)
            Next
        End If
        StrMngdFolder = FolderPath
        FileClose(1)
        If valid = False Then
            MsgBox("No path entries in SearchScope.txt, browse to file")
            Exit Sub
        End If

    End Sub

    Private Sub btnUpdateFiles_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdateFiles.Click
        lstFiles.Items.Clear()
        LoadFileList()
        btnProcess.Enabled = True
        lblFileList.Text = strProcessFiles
        lblFileList.Update()
        btnUpdateFiles.Enabled = False

    End Sub

    Private Sub LoadFileList()
        lstFiles.Items.Clear()

        If chkInsight.Checked Then
            SetFileList(FolderPath)
        Else
            LoadSEFiles()
        End If

    End Sub

    Private Sub Update3DStyles(ByRef pDoc)
        'Added for V104: Updates and Adds Face and View Styles in 3D documents per global setting
        Dim bV As Boolean = True
        Dim pStyles As SolidEdgeFramework.ViewStyles
        Dim pDefault As SolidEdgeFramework.ViewStyle
        Dim pTmpStyle As SolidEdgeFramework.ViewStyle
        Dim str3DStyleSourceFile As String

        'Set the source file for the updated styles

        str3DStyleSourceFile = Application.StartupPath + "\SourceStyles.asm"
        If Not (File.Exists(str3DStyleSourceFile)) Then
            Exit Sub
        End If


        Try
            'Update the document face styles
            pDoc.ImportStyles(str3DStyleSourceFile, bV)
        Catch
            Return
        End Try

        'Update the view styles
        pDoc.Activate()
        pStyles = CType(pDoc.ViewStyles, SolidEdgeFramework.ViewStyles)

        'Copy/Add the additional new view styles from the style source template
        Try
            'Delete the style if it already exists
            pTmpStyle = CType(pStyles.Item("High Quality"), SolidEdgeFramework.ViewStyle)
            pTmpStyle.Delete()
        Catch
            pTmpStyle = Nothing
        End Try
        pTmpStyle = pStyles.AddFromFile(str3DStyleSourceFile, "High Quality")

        Try
            'Delete the style if it already exists
            pTmpStyle = CType(pStyles.Item("Rendering"), SolidEdgeFramework.ViewStyle)
            pTmpStyle.Delete()
        Catch
            pTmpStyle = Nothing
        End Try
        pTmpStyle = pStyles.AddFromFile(str3DStyleSourceFile, "Rendering")

        'Update the default view style
        Try
            'Get the current default style
            pDefault = CType(pStyles.Item("Default"), SolidEdgeFramework.ViewStyle)
            'Add the new style from the source. (SE Will rename it, not overwrite it)
            'We will copy settings from this style and then delete it.
            pTmpStyle = pStyles.AddFromFile(str3DStyleSourceFile, "Default")
        Catch
            'Current default style does not exist in the file. Add the new one and skip copy of the settings.
            pDefault = pStyles.AddFromFile(str3DStyleSourceFile, "Default")
            GoTo Apply_Default_View_Style
        End Try

        'Copy the settings from pTmpStyle to pDefault and then delete pTmpStyle
        Dim ii As Integer
        Dim pfRed As Single
        Dim pfGreen As Single
        Dim pfBlue As Single
        Dim pfTheta As Single
        Dim pfPhi As Single

        Try
            pDefault.AmbientRed = pTmpStyle.AmbientRed
            pDefault.AmbientBlue = pTmpStyle.AmbientBlue
            pDefault.AmbientGreen = pTmpStyle.AmbientGreen

            pDefault.BackgroundImageFile = pTmpStyle.BackgroundImageFile

            pDefault.Perspective = pTmpStyle.Perspective
            pDefault.AntialiasLevel = pTmpStyle.AntialiasLevel
            pDefault.RenderMode = pTmpStyle.RenderMode
            pDefault.RenderModeType = pTmpStyle.RenderModeType
            pDefault.HiddenLineMode = pTmpStyle.HiddenLineMode
            pDefault.HiddenLines = pTmpStyle.HiddenLines
            pDefault.DimPercentage = pTmpStyle.DimPercentage

            pDefault.Textures = pTmpStyle.Textures
            pDefault.Silhouettes = pTmpStyle.Silhouettes
            pDefault.SilhouettesEnabled = pTmpStyle.SilhouettesEnabled

            pDefault.Reflections = pTmpStyle.Reflections
            pDefault.DropShadow = pTmpStyle.DropShadow
            pDefault.FloorReflection = pTmpStyle.FloorReflection
            pDefault.DepthFading = pTmpStyle.DepthFading
            pDefault.CastShadows = pTmpStyle.CastShadows

            Dim PI As Double = 3.1415926535897931
            Dim PI_slice As Double = PI / 4
            Dim tol As Double = 0.0001
            Dim L1_Not_Added As Boolean = True
            Dim L2_Not_Added As Boolean = True
            Dim nLight As Integer

            ii = 0
            While ii < pDefault.NumLights
                pDefault.GetLight(ii, pfRed, pfGreen, pfBlue, pfTheta, pfPhi)
                'Set all existing lights to black
                pfRed = 0.0
                pfGreen = 0.0
                pfBlue = 0.0

                If (pfTheta - 3 * PI_slice) < tol And (pfTheta - 3 * PI_slice) > -tol Then
                    pfRed = 0.53
                    pfGreen = 0.52
                    pfBlue = 0.6
                    pfPhi = 20 * PI / 180
                    L1_Not_Added = False
                ElseIf (pfTheta - 7 * PI_slice) < tol And (pfTheta - 7 * PI_slice) > -tol Then
                    pfRed = 0.9
                    pfGreen = 0.9
                    pfBlue = 0.9
                    pfPhi = 50 * PI / 180
                    L2_Not_Added = False
                End If

                pDefault.SetLight(ii, pfRed, pfGreen, pfBlue, pfTheta, pfPhi)
                ii = ii + 1
            End While

            If L1_Not_Added And pDefault.NumLights < 8 Then
                'Add the L1 light
                pfRed = 0.53
                pfGreen = 0.52
                pfBlue = 0.6
                pfTheta = 3 * PI_slice
                pfPhi = 20 * PI / 180
                pDefault.AddLight(pfRed, pfGreen, pfBlue, pfTheta, pfPhi, nLight)
            End If

            If L2_Not_Added And pDefault.NumLights < 8 Then
                'Add the L2 light
                pfRed = 0.9
                pfGreen = 0.9
                pfBlue = 0.9
                pfTheta = 7 * PI_slice
                pfPhi = 50 * PI / 180
                pDefault.AddLight(pfRed, pfGreen, pfBlue, pfTheta, pfPhi, nLight)
            End If

            pTmpStyle.Delete()

        Catch ex As Exception
            Dim tt As String = ex.Message
        End Try

        ' Set the following to true and rebuild if you want to update the displayed view to the new Default View Style
Apply_Default_View_Style:
#If False Then
		Try
			Dim pWindowObj As SolidEdgeFramework.Window
			Dim pView As SolidEdgeFramework.View
			Dim pWindow As SolidEdgeFramework.Window
			pWindowObj = CType(pDoc.Windows.Item(1), SolidEdgeFramework.Window)
			pWindow = CType(pWindowObj, SolidEdgeFramework.Window)
			pView = CType(pWindow.View, SolidEdgeFramework.View)
			pView.ViewStyle = pDefault
		Catch
			Return
		End Try
#End If
    End Sub

    Private Sub chkUpdate3DStyles_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkUpdate3DStyles.CheckedChanged
        If chkUpdate3DStyles.Checked Then
            lblStyles.Visible = True
        Else
            lblStyles.Visible = False
        End If
    End Sub
End Class
