Task 668: .SLDASM File Format

Task 668: .SLDASM File Format

1. List of Properties Intrinsic to the .SLDASM File Format

The .SLDASM file format is a proprietary binary format used by SolidWorks for assembly documents. For versions up to SolidWorks 2014, it is based on the Microsoft Compound File Binary Format (OLE structured storage), which includes embedded streams and storages containing metadata and data. From SolidWorks 2015 onward, it uses a custom binary format with a different structure. Detailed specifications are not publicly documented, but based on available information from reverse-engineering efforts and format analyses, the following properties are intrinsic to the format and can be extracted from metadata streams (in OLE versions) or headers (in binary versions). These include standard document metadata and format-specific identifiers:

  • File Signature (magic bytes, e.g., D0 CF 11 E0 A1 B1 1A E1 for OLE versions or potentially SLDWKSBF\0\0\0\0 for binary versions)
  • Version History Value (an integer indicating the SolidWorks version, e.g., 17000 for SolidWorks 2024)
  • File Type Identifier (distinguishing assembly from part or drawing)
  • Title
  • Subject
  • Author
  • Keywords
  • Comments
  • Template
  • Last Author
  • Revision Number
  • Edit Time
  • Last Printed Time
  • Create Date/Time
  • Last Save Date/Time
  • Page Count
  • Word Count
  • Character Count
  • Application Name
  • Security Level
  • Category
  • Presentation Format
  • Byte Count
  • Line Count
  • Paragraph Count
  • Slide Count
  • Note Count
  • Hidden Count
  • Multimedia Clip Count
  • Scale Flag
  • Heading Pairs
  • Document Parts
  • Manager
  • Company
  • Links Dirty Flag
  • Character Count with Spaces
  • Shared Document Flag
  • Link Base
  • Hyperlinks
  • Hyperlink Changed Flag
  • Version Number
  • Digital Signature
  • Content Type
  • Content Status
  • Language
  • Document Version

These properties are primarily derived from the SummaryInformation and DocumentSummaryInformation streams in OLE-based files. For binary files (2015+), equivalent metadata may exist but requires custom parsing, as public details are limited.

These links provide sample .SLDASM files from public GitHub repositories for testing purposes.

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .SLDASM File Property Dump

The following is an HTML page with embedded JavaScript that can be embedded in a Ghost blog or similar platform. It allows users to drag and drop a .SLDASM file, checks if it is an OLE compound file (for versions up to 2014), and dumps the listed properties to the screen if possible. Parsing OLE in JavaScript is complex without external libraries; this implementation uses a basic approach to detect the format and extract metadata assuming a simple structure. For full functionality, integration with a library like 'ole-doc' is recommended, but it is not included here.

SLDASM Property Dumper
Drag and drop .SLDASM file here

4. Python Class for .SLDASM File Handling

The following Python class uses the olefile library (install via pip install olefile) to open, decode, read, write, and print the properties from OLE-based .SLDASM files. For binary formats (2015+), it provides basic signature checking but limited metadata extraction, as specifications are proprietary.

import olefile
import datetime

class SldasmHandler:
    def __init__(self, filename):
        self.filename = filename
        self.ole = None
        self.metadata = None
        self.properties = {}

    def open(self):
        self.ole = olefile.OleFileIO(self.filename)
        if self.ole.exists('\x05SummaryInformation'):
            si = self.ole.openstream('\x05SummaryInformation')
            self.metadata = olefile.OleMetadata(si)
            self._extract_properties()
        else:
            # Check for binary format
            with open(self.filename, 'rb') as f:
                header = f.read(12)
                if header.startswith(b'SLDWKSBF\x00\x00\x00\x00'):
                    self.properties['File Signature'] = 'SolidWorks Binary Format'
                    # Version example; actual offset unknown
                    self.properties['Version History Value'] = int.from_bytes(header[8:12], 'little')
                else:
                    raise ValueError("Invalid .SLDASM file")

    def _extract_properties(self):
        props = [
            'Title', 'Subject', 'Author', 'Keywords', 'Comments', 'Template', 'Last Author',
            'Revision Number', 'Edit Time', 'Last Printed', 'Create Date/Time', 'Last Save Date/Time',
            'Page Count', 'Word Count', 'Character Count', 'Application Name', 'Security',
            'Category', 'Manager', 'Company'  # Add more as needed
        ]
        for prop in props:
            value = getattr(self.metadata, prop.lower().replace(' ', '_').replace('/', ''), None)
            if isinstance(value, datetime.datetime):
                value = value.isoformat()
            self.properties[prop] = value

    def print_properties(self):
        for key, value in self.properties.items():
            print(f"{key}: {value}")

    def write_property(self, key, value):
        if self.metadata:
            setattr(self.metadata, key.lower().replace(' ', '_').replace('/', ''), value)
            # To write back, need to recreate the stream; simplified here
            print(f"Property {key} set to {value} (write not fully implemented in this example)")

    def close(self):
        if self.ole:
            self.ole.close()

# Usage example:
# handler = SldasmHandler('example.sldasm')
# handler.open()
# handler.print_properties()
# handler.write_property('Author', 'New Author')
# handler.close()

5. Java Class for .SLDASM File Handling

The following Java class uses Apache POI (add dependency via Maven: org.apache.poi:poi:5.2.3) to handle OLE-based .SLDASM files. Binary format support is limited.

import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class SldasmHandler {
    private String filename;
    private POIFSFileSystem fs;
    private SummaryInformation si;
    private DocumentSummaryInformation dsi;
    private Map<String, Object> properties = new HashMap<>();

    public SldasmHandler(String filename) {
        this.filename = filename;
    }

    public void open() throws IOException {
        fs = new POIFSFileSystem(new FileInputStream(filename));
        si = fs.getPropertySet(SummaryInformation.DEFAULT_STREAM_NAME);
        dsi = fs.getPropertySet(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
        extractProperties();
    }

    private void extractProperties() {
        // Extract from SummaryInformation
        properties.put("Title", si.getTitle());
        properties.put("Subject", si.getSubject());
        properties.put("Author", si.getAuthor());
        properties.put("Keywords", si.getKeywords());
        properties.put("Comments", si.getComments());
        properties.put("Last Author", si.getLastAuthor());
        properties.put("Revision Number", si.getRevNumber());
        properties.put("Create Date/Time", si.getCreateDateTime());
        properties.put("Last Save Date/Time", si.getLastSaveDateTime());
        // Extract from DocumentSummaryInformation
        properties.put("Category", dsi.getCategory());
        properties.put("Manager", dsi.getManager());
        properties.put("Company", dsi.getCompany());
        // Add more as needed
        // For binary, add custom logic if known
    }

    public void printProperties() {
        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    public void writeProperty(String key, Object value) {
        // Example for SummaryInformation
        if ("Title".equals(key)) {
            si.setTitle((String) value);
        }
        // To persist, write back to file; not fully implemented here
        System.out.println("Property " + key + " set to " + value + " (write requires file save)");
    }

    public void close() throws IOException {
        if (fs != null) {
            fs.close();
        }
    }

    // Usage example in main method or elsewhere
}

6. JavaScript Class for .SLDASM File Handling

The following JavaScript class handles .SLDASM files in a Node.js environment (requires 'ole-doc' library via npm install ole-doc). It reads and prints properties; writing is conceptual, as full serialization is complex.

const OleCompoundDoc = require('ole-doc').OleCompoundDoc;

class SldasmHandler {
    constructor(filename) {
        this.filename = filename;
        this.properties = {};
    }

    async open() {
        const doc = new OleCompoundDoc(this.filename);
        await doc.read();
        const siStream = await doc.stream('\x05SummaryInformation');
        if (siStream) {
            // Parse metadata; simplified, as ole-doc provides buffer
            this.properties['Title'] = 'Extracted Title'; // Implement actual buffer parsing
            // Add similar for others
        } else {
            // Binary check
            const fs = require('fs');
            const buffer = fs.readFileSync(this.filename);
            const sig = buffer.slice(0, 8).toString('ascii');
            if (sig === 'SLDWKSBF') {
                this.properties['File Signature'] = 'SolidWorks Binary Format';
            } else {
                throw new Error('Invalid .SLDASM file');
            }
        }
    }

    printProperties() {
        for (const [key, value] of Object.entries(this.properties)) {
            console.log(`${key}: ${value}`);
        }
    }

    writeProperty(key, value) {
        this.properties[key] = value;
        console.log(`Property ${key} set to ${value} (full write requires serialization)`);
    }
}

// Usage example:
// const handler = new SldasmHandler('example.sldasm');
// await handler.open();
// handler.printProperties();
// handler.writeProperty('Author', 'New Author');

7. C++ Class for .SLDASM File Handling

The following C++ class uses the libgsf library (for OLE parsing; compile with pkg-config --cflags --libs gsf-1) to handle .SLDASM files. Binary support is limited.

#include <gsf/gsf-infile.h>
#include <gsf/gsf-infile-msole.h>
#include <iostream>
#include <map>
#include <string>

class SldasmHandler {
private:
    std::string filename;
    GsfInfile *infile;
    std::map<std::string, std::string> properties;

public:
    SldasmHandler(const std::string &fn) : filename(fn), infile(nullptr) {}

    ~SldasmHandler() { close(); }

    bool open() {
        GError *err = nullptr;
        infile = gsf_infile_msole_new(filename.c_str(), &err);
        if (err) {
            std::cerr << "Error: " << err->message << std::endl;
            g_error_free(err);
            // Check binary
            FILE *f = fopen(filename.c_str(), "rb");
            if (f) {
                char header[12];
                fread(header, 1, 12, f);
                if (std::string(header, 8) == "SLDWKSBF") {
                    properties["File Signature"] = "SolidWorks Binary Format";
                }
                fclose(f);
            }
            return false;
        }
        extractProperties();
        return true;
    }

    void extractProperties() {
        // Access SummaryInformation stream
        GsfInput *si = gsf_infile_child_by_name(infile, "\005SummaryInformation");
        if (si) {
            // Parse properties; libgsf provides access, but manual parsing needed for values
            properties["Author"] = "Extracted Author"; // Implement actual extraction
            g_object_unref(si);
        }
    }

    void printProperties() {
        for (const auto &pair : properties) {
            std::cout << pair.first << ": " << pair.second << std::endl;
        }
    }

    void writeProperty(const std::string &key, const std::string &value) {
        properties[key] = value;
        std::cout << "Property " << key << " set to " << value << " (write requires output file)" << std::endl;
    }

    void close() {
        if (infile) {
            g_object_unref(infile);
            infile = nullptr;
        }
    }
};

// Usage example in main:
// SldasmHandler handler("example.sldasm");
// if (handler.open()) {
//     handler.printProperties();
//     handler.writeProperty("Author", "New Author");
// }