person.Picture.ReadFromFile() returns everytime an error


i try to upload an image for a person on SuperOffice. I use VisualStudio to do it. My Code is:

Dim soDB AS Database = New SuperOffice.COM.SuperOfficeDB.Database
soDB.Login("user", "password")

Dim Person as SOPerson = soDB.GetPerson(7)

Person.Picture.ReadFromFile(System.AppDomain.CurrentDomain.BaseDirectory & "Bilder\person_stop.jpg")

On the Line Person.Picture.ReadFromFile i get everytime an error HRESULT: 0xC1010317

The path is correct, i try it with a different directories, everytime the same error.

Additional i test to Person.PictureWriteFile, but it also didn't work, no error, but also no file.


I found a example on, so i think this is the correct way.



Here ist the file.


How it should work?

best regards


RE: person.Picture.ReadFromFile() returns everytime an error

Hi Mike,

Read issue: fixed in next 8.5 R05 release.
Write issue works for me but make sure that your file name has a image type extention that is supported: .jpg .jpeg .gif .bmp

Looks like the read method probably never got tested. Bug goes back to pre-Perforce time, feb 2011. I don't even have access to that history any more.

The first guard that tested the filename was:
if ( fname.IsNotEmpty() )
    return SetErrorObject(SoDb_E_PICTURE_READFROMFILE, L"Picture.ReadFromFile", L"Filename cannot be empty");


What can I say. You are the first one to ever use it or noone else bothered to report it.
Thanks for the report!



Af: Conrad Weyns 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

Hi Conrad,

thanks for your fast reply. The image is an .jpg file.

I there any other way to upload an image to a person? The background is, that we want to mark undesirable persons in the system, like the stop-marker on the contactcard.


PS: Now i tested it with an bmp image and i test to shrink to file to 300x300px, but nothing works.

Af: Mike Behrendt 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

You could use the SuperOffice GUI. :)

Af: Martin Andersen 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

I think you misunderstanding my answer.

- Picture::ReadFromFile( filePath ) is totaly broken and as been so from some time before 2011 may be always.
- Picture.:WriteToFile( filePath ) works.  If filePath ends in .jpg, .jpeg, .gif or .bmp it will attempt to convert else it will try some default format.

Once you have added this stop picture to the database, find it's Id and use Picture::Id( xyz ) instead.
All these "Stopped" persons can share the same id.

(I'll give this a try to verify but I reckn it should work)


I am afraid that our COM Person.Picture class looks rather broken. I guess you are the first one to want to use it as these issues seem to go back to before 2011.

This should work.
Assuming your Stopped image blob id = 123

pers.Picture.Id = 123

Instead it seems to delete the blob on the way!
I fear that this has never been propery tested.
I have added a tfs issue: 66489.
I will dig into it by the next 8.5 R05 release.



Af: Conrad Weyns 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

Hi Conrad,


thanks for you tip. It works, if i would set the picture to additional persons, but if i want to remove an picture from one person, superoffice delete the picture from the database, so the picture is not available

best regards


Af: Mike Behrendt 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

Yes, this seems to be in a bit of a mess.
    tfs 66483, Win: COM Person.Picture.ReadFromFile allways fails
is fixed and will be available in the next 8.5 R05 release.
This will allow you to use ReadFromFile as you planned and add a new Stopped image for every person you target.

   tfs 66489, COM Person.Picture issues (never been properly tested?)
I am digging into this now.

In Project, we never delete an Image.
In Person, we do. Your use case however seems to suggest that we should not unless there are no more binaryobjectlink record pointing to it. I don't think we considered your use case. On the face of it, it seems very unikely that 2 persons would have the same image...
Also, we now have Soft Delete of persons and this is done by Netserver. No idea what netserver does with the person picture when hard deleting a person record.

So, avoid sharing when using Picture.Id = 123 even though the COM info says:

 Property Id As Long

Picture id (binary object id) in the database. You can set this id if you want two pictures to share the same binary object.


But I will guard against deleting a shared picture in our c++ person model code!




Af: Conrad Weyns 5. sep 2019

RE: person.Picture.ReadFromFile() returns everytime an error

Ok, ISOPicture is now fixed and tested in latest 8.5.

- ReadFromFile works
- WriteToFile works

- Id = 123 also works and allows you to share an image but only up to some point.
As a rule, don't try to share. There are other places that manipulate person records that will delete a shared picture a.o. the Clear operator of the portrait band in BulkUpdate. Bottom line, use ReadFromFile on all target persons.


Say you have a selection of persons that you want to set the Stopped image to.
First you may want to use the Portrait column in the archive. Unfortunaltely this column is ignored in SoArchiveColumnList.config file (c/o Web tream). Open your local SoCrm Archives.config file, find selectionmemberarchive section and add this column override:

<column name="portraitThumbnail" ignore="false"/>

Force a reconfigure or restart socrm.

This vb script will change all person row's images:
(I use VBSEdit )

------------- App.Archive.Stopped.Picture.vbs ---------

Set app = CreateObject( "SuperOffice.Application" )
If Not app Is Nothing Then
    Set archive = app.GetArchiveInterface( "", "" )
    If Not archive Is Nothing Then
        WScript.Echo archive.ProviderName & "/" & archive.GuiName & vbCrLf

        Set rows =  archive.AllRows
        On Error Resume Next
 ­       For Each row In rows
            If row.tableid = 6 Then
                Set pers = app.Database.GetPerson( row.RecordId )
                If Not pers Is Nothing Then
                    pers.Picture.ReadFromFile( "D:\bilder\stop.jpg" )
                End If
      ­      End If
        WScript.Echo "Unable to get active archive interface!"
    End If
    WScript.Echo "Error getting application object"
End If




Af: Conrad Weyns 5. sep 2019