AnsweredAssumed Answered

macro works great 500 times, then crashes

Question asked by Terry Raymond on Sep 7, 2011
Latest reply on Jun 28, 2017 by Deepak Gupta

I have a macro that finds SW files on my network, opens them one at a time, runs another macro (VBA) on each file, and closes the file.


It runs correctly on ~400-600 files without problem, but then consistently crashes after running for 15-20 minutes. 


Most common error:

A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in run macro on multiple files.DLL

**** System.Runtime.InteropServices.COMException (0x80010100): System call failed. (Exception from HRESULT: 0x80010100 (RPC_E_SYS_CALL_FAILED))

   at SolidWorks.Interop.sldworks.ISldWorks.OpenDoc6(String FileName, Int32 Type, Int32 Options, String Configuration, Int32& Errors, Int32& Warnings)

   at run_macro_on_multiple_files.vbproj.SolidWorksMacro.OpenFileAndRunMacro(String filename) in L:\zMacros\run macro on multiple files\SwMacro\SolidWorksMacro.vb:line 153*****


Sometimes it gives this error:

The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))


annoying error2.png

annoying error.png


The OpenDoc6 seems to work (errors and warnings = 0), but swDoc goes bad.  Bad pointer?

Solidworks always has the file open when it crashes, so Solidworks does what it is told to do, but doesn't seem to communicate that back to the macro.

I'm able to manually run the second macro without issue.

It doesn't crash on the same file twice, seems like it crashes on whatever file it gets to after 15-20 minutes.

After a crash, I don't need to restart solidworks for it to work again.


I've gone over all the forum posts and couldn't find a solution.  I tried using try-catch; the macro didn't stop but once the error started, the macro encountered the same exception for successive files and couldn't open them.  SPR 524040 looks similar, but is supposidly fixed.


Any ideas?


My code:



' ******************************************************************************

' Macro runner  v0.1

' Function:  Runs a macro on all files inside a folder and subfolder.

' Usage:  Set options below and run.

' ******************************************************************************


Imports SolidWorks.Interop.sldworks

Imports SolidWorks.Interop.swconst

Imports System

Imports System.Diagnostics


Partial Class SolidWorksMacro


    '*** User Options (Set all these as necessary, back up your data!)***

    Public startpath As String = "S:\QUOTES"  'Root folder Name. Change to folder that has SolidWorks files (end with \)

    Public fileextension1 As String = "sldprt"   'file type to run macro (ie "sldprt")

    Public fileextension2 As String = "sldasm"   'file type to run macro (ie "sldasm")

    Public MacroToRun As String = "L:\zMacros\property copier.swp"        'full path to macro file you want to run on each file

    Public ModuleToRun As String = "propertycopier1"       'module inside the macro you want to run


    Public FileLimit As Integer = 50000    'max number of files to run macro on

    Public FileStart As Integer = 1360        'number of file to start processing

    Public FolderLimit As Integer = 50000  'max number of folders to check

    Public DepthLimit As Integer = 100     'max depth of subfolders to check (0 = don't look in any subfolders)

    '*** end options ***



    Public swApp As SldWorks

    Public swFiletype As Integer

    Public FolderCount As Integer = 0

    Public FileCount As Integer = 0

    Public FolderDepth As Integer = 0


    Public Sub main()


        Debug.Print("  === Start === ")


        'Start looking for files



    End Sub



    'looks for all files with the right file extension in a folder

    'runs OpenFileAndRunMacro on each found file

    'looks for subdirectories in the folder, and recursively runs itself

    'will stop when it hits either the Folder limit, File limit, or folder depth limit.


    Sub FindFilesInSubfolders(ByVal path As String)

        Debug.Print("Folder # " & FolderCount & " - " & path & "     depth:" & FolderDepth)


        'get a list of all the files (not folders) in current directory

        Dim files1() As System.IO.FileInfo = My.Computer.FileSystem.GetDirectoryInfo(path).GetFiles("*." & fileextension1)

        Dim files2() As System.IO.FileInfo = My.Computer.FileSystem.GetDirectoryInfo(path).GetFiles("*." & fileextension2)

        Dim AllFiles(0) As System.IO.FileInfo

        Dim skipfile As Boolean = False

        Dim i As Integer = 0


        Array.Resize(AllFiles, files1.Length + files2.Length)


        For Each file As System.IO.FileInfo In files1

            AllFiles(i) = file

            i += 1



        For Each file As System.IO.FileInfo In files2

            AllFiles(i) = file

            i += 1



        Debug.Print(" number of files = " & AllFiles.Length)


        'loop through each file, and run the external macro function on each file

        For Each file As System.IO.FileInfo In AllFiles

            Debug.Print("  File # " & FileCount & " - " & file.FullName)



            'count how many files we have opened, exit if we have hit the limit

            If FileCount >= FileLimit + FileStart Then Exit For


            If (file.Exists) Then

                FileCount += 1

                skipfile = False


                'see if file is read only

                If file.Attributes And IO.FileAttributes.ReadOnly Then

                    Debug.Print("      File is read only! removing read only flag.")

                    file.Attributes = file.Attributes - IO.FileAttributes.ReadOnly

                End If


                'see if file is hidden

                If file.Attributes And IO.FileAttributes.Hidden Then

                    Debug.Print("      File is hidden, skipping.")

                    skipfile = True

                End If


                'see if file is temp sw file  (make this try to delete??? or rename??? if fail, file is open by someone.)

                If Left(file.FullName, 1) = "~" Then

                    Debug.Print("      File is a temporary SW working file, skipping.")

                    skipfile = True

                End If


                'don't run we've reached the first start file

                If FileCount <= FileStart Then

                    skipfile = True

                End If


                'open file unless skipping

                If (Not skipfile) Then


                End If

            End If



        'get a list of all the subfolders in current directory

        Dim subfolders() As System.IO.DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(path).GetDirectories()

        Debug.Print(" number of subfolders = " & subfolders.Length)


        'check how deep we are, exit if we have hit the limit

        If FolderDepth > DepthLimit Then Exit Sub


        'get ready to go one level deeper

        FolderDepth += 1


        'loop through each folder, and recursively run this function on each found folder

        For Each subfolder As System.IO.DirectoryInfo In subfolders


            'count how many folders we have opened, exit if we have hit the limit

            FolderCount += 1

            If FolderCount > FolderLimit Then Exit Sub


            'recursively run the search function again on subfolder




        'we are now back a level

        FolderDepth -= 1


    End Sub



    'Opens a file, runs a macro, saves file, closes file.


    Sub OpenFileAndRunMacro(ByVal filename As String)

        Dim swDoc As ModelDoc2 = Nothing

        Dim bool As Boolean

        Dim errors As Long

        Dim warnings As Long


        'Exit Sub   'enable to just find and count files


        'Open file

        swDoc = swApp.OpenDoc6(filename, GetSWDocType(filename), 0, "", errors, warnings)

        Debug.Print("      Opening file. [" & My.Computer.Clock.LocalTime.ToLongTimeString & "]" & swDoc.GetTitle)


        'Run macro

        bool = swApp.RunMacro2(MacroToRun, ModuleToRun, "main", 0, errors)


        'Close file



    End Sub


    Function GetSWDocType(ByVal filename As String) As Long

        ' Determine type of SolidWorks file based on file extension

        If InStr(LCase(filename), "sldprt") > 0 Then

            GetSWDocType = swDocumentTypes_e.swDocPART

        ElseIf InStr(LCase(filename), "sldasm") > 0 Then

            GetSWDocType = swDocumentTypes_e.swDocASSEMBLY

        ElseIf InStr(LCase(filename), "slddrw") > 0 Then

            GetSWDocType = swDocumentTypes_e.swDocDRAWING

        Else           ' Not a SolidWorks file

            GetSWDocType = swDocumentTypes_e.swDocNONE

        End If

    End Function

End Class