Save extra data in Inventor file without Inventor API

By Xiaodong Liang

I believe you have found the two articles below when you wanted to store additional data to an Inventor file.

How to use private storage and stream in C++
Save extra data in Inventor file – 3

They solutions work well in most cases until a customer was frustrated recently: she wanted to store the data but not dirty the file. While the solutions above actually use the wrapped functions of IStorage and IStream which require to make the document dirty.

But if you use IStorage and IStream of pure Windows API, you can bypass this. One 3rd tool http://www.mitec.cz/ssv.html has proved this. I did some investigations and wrote some codes which may help you to get started with. Basically, the data of a Windows file is organized in a hierarchy of storages. The root storage can contain sub storages. In the storage, you can add stream which stores your data.

The attached project adds custom data to an Inventor file and reads it out. You can verify Document.RevisionId is not changed after the modification. And Dirty is false. It assumes a file c:\temp\Part1.ipt exists.

Download Save extra data

The core code:

//create storage
void createST()
{
    HRESULT hr = S_OK;
    IStorage *pStg = NULL;

    //open the root storage
    hr = StgOpenStorageEx(
        _T("c:\\temp\\Part1.ipt"),
        STGM_WRITE | STGM_SHARE_EXCLUSIVE,
        STGFMT_ANY,
        0,
        NULL,
        NULL,
        IID_IStorage,
        reinterpret_cast(&pStg)
    );

    if (FAILED(hr))
    {
        // Handle error if needed
    }
    else
    {
        IStorage *mystorge = NULL;
        //create my storage
        hr = pStg->CreateStorage(
            _T("ADNStorage"),
            STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
            NULL,
            NULL,
            &mystorge
        );
        if (FAILED(hr))
        {
            // Handle error if needed
        }
        else
        {
            IStream *mystream = NULL;
            //create my stream
            hr = mystorge->CreateStream(
                _T("ADNStorage_Stream"),
                STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
                NULL,
                NULL,
                &mystream
            );
            if (FAILED(hr))
            {
                // Handle error if needed
            }
            else
            {
                //write my data to the stream
                const char *data = "mydataaaaaaaaaaaaaaaaaaaaaaaaaaaaada";

                ULONG lsize = strlen(data);
                //hr=mystream->Write( &lsize,sizeof(int), NULL ) ;
                hr = mystream->Write(data, lsize, NULL);
                hr = mystream->Commit(STGC_DEFAULT | STGC_OVERWRITE);
                hr = mystream->Release();
            }

            mystorge->Release();
        }
    }
    pStg->Release();
}

//read data from the file
void readST()
{
    HRESULT hr = S_OK;
    IStorage *pStg = NULL;

    //open the root storage
    hr = StgOpenStorageEx(
        _T("c:\\temp\\Part1.ipt"),
        STGM_READ | STGM_SHARE_EXCLUSIVE,
        STGFMT_ANY,
        0,
        NULL,
        NULL,
        IID_IStorage,
        reinterpret_cast(&pStg)
    );

    if (FAILED(hr))
    {
        // Handle error if needed
    }
    else
    {
        IStorage *mystorge = NULL;

        //open my storage
        hr = pStg->OpenStorage(
            _T("ADNStorage"),
            NULL,
            STGM_READ | STGM_SHARE_EXCLUSIVE,
            NULL,
            NULL,
            &mystorge
        );
        if (FAILED(hr))
        {
            // Handle error if needed
        }
        else
        {
            IStream *mystream = NULL;
            //open my stream
            hr = mystorge->OpenStream(
                _T("ADNStorage_Stream"),
                NULL,
                STGM_READ | STGM_SHARE_EXCLUSIVE,
                NULL,
                &mystream
            );
            if (FAILED(hr))
            {
                // Handle error if needed
            }
            else
            {
                //read the data out
                const int nLen = 255;
                char strText[nLen] = {0};
                ULONG actRead;
                hr = mystream->Read(strText, nLen, &actRead);
                hr = mystream->Release();
            }
            mystorge->Release();
        }
    }
    pStg->Release();
}

Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading