1

I built this open-file function in PowerShell for a GUI I wrote that lets you find and open various files on a server. I mainly use it for opening SolidWorks files as read-only, but also for PDF files and it should work for just about any other file if there is a file association for it.

The problem is that sometimes it doesn't work when opening the sldprt files. SolidWorks will either ignore the open file request or it wont open as read-only. I think this is mostly just a solidworks issue as sometimes it wont open files when double clicked on from windows explorer.

Anyway my solution is to set the file attribute to read-only. start a job that opens the file in SolidWorks, and then waits for the SolidWorks process to go idle before removing the read-only attribute. It does this through an event that watches for the job state to change. Since this is running through a GUI it has to be done in the background to prevent the GUI from locking up.

Is there a simpler way to open files as read-only with PowerShell?

I think it might be possible using the SolidWorks .dll files, but they are meant to be loaded in C# or VB-script and I have no idea what i'm doing in either of those languages.

function open-File{
    param(
        [parameter(Mandatory=$true)]$file,
        [bool]$readOnly = $true,
        $processName=$null
    )
    [scriptblock]$openFileScriptBlock = {
        param(
            $file,
            $readOnly,
            $processName=$null
        )
        #initiate variables
        $loaded = $false
        $file = get-item $file
        $processLastCpu = 0
        $timeout = 0
        if ($readonly -and !$file.isReadOnly){
            $file.isReadOnly = $true
            #call file with default application
            $attempts = 0
            while ($true){
                try{$startedProcess = start-process "$($file.fullname)" -PassThru; break}
                catch{
                    $attempts++
                    if ($attempts -eq 3){return "cannot open file: $file, Error:$_"}
                }
            }
            start-sleep -seconds 2
            if ($processName){
                $processName = $startedProcess.name
                if ($processName -eq "SWSHEL~1"){$processName = "SLDWORKS"}
            }
            #wait until process shows up in the process manager
            while ($loaded -eq $false -and $timeout -lt 25 ){
                try {
                    $process = get-process -name $processName -erroraction 'stop'
                    if ($?){$loaded = $true; $timeout = 0} else {throw}
                }catch{start-sleep -milliseconds 200; $timeout++}
            }
            start-sleep -seconds 2
            #wait for process to go idle
            while ($process.cpu -ne $processLastCpu -and $timeout -lt 10){
                $processLastCpu = $process.cpu
                start-sleep -milliseconds 500
                $timeout++
            }
            $file.isreadonly = $false
        } else {start-process "$($file.fullname)"}
        return ,$file
    }
    if (!(test-path -path $file)){update-message "File not found: $file"; return}
    $openFileJob = start-job -name 'openfile' -scriptblock $openFileScriptBlock -argumentlist $file, $readOnly, $processName
    Register-ObjectEvent $OpenFileJob StateChanged  -Action {
        $jobResult = $sender | receive-job
        $sender | remove-job -Force
        unregister-event -sourceIdentifier $event.sourceIdentifier
        remove-job -name $event.sourceIdentifier -force
        try{update-message "opened file $($jobResult.name)"}
        catch{update-message $jobResult}
    } | out-null
}

1 Answer 1

0

I know its a old question, but i was wondering if you ever managed to get a solution? If not, there is a few things you could try: first off, if your code is opening any other file just fine, it does not seem to be there the problem is.

File association with all SLD-files are working most of the time; but we do see it going bad from time to time (often related to updates), in that case, double-check that all SLD-file types are set to open with 'Solidworks-Launcher' (and not Solidworks directly). Using the launcher, will ensure Solidworks does not try to open a file, into an already running instance of Solidworks.

Also, try to check the following: Solidworks Options -> Collaboration -> 'Enable Multi-user environments'... is this set? whatever state it is in; try changing is to the opposite. That checkmark is allowing multiple Solidworks-users to open the same file at the same time, and it does so by changing the read-state of the file, back and fourth. (it could be it is interfering with your code)

Both of these things will be PC-specific, so if you change them on one machine, they might also need to be changed on other machines.

Sign up to request clarification or add additional context in comments.

2 Comments

I wasn't aware of the settings you pointed out so I will try what you suggested and see if it makes any difference. I have actually been trying to teach myself c# so I can look further into using the solidworks api's to directly open the files. I did notice, as you suggested, that the solidworks launcher handles the open file call but its also possible to call the solidworks exe directly and bypass the launcher. I have tried both scenarios, and they both act essentially the same way, with the exception that calling the solidworks exe directly is always faster.
I tried changing the multi-user environments setting and the I didn't notice any difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.