ironfede / openmcdf

Microsoft Compound File .net component - pure C# - netstandard 2.0
Mozilla Public License 2.0
309 stars 76 forks source link

Is there is any way to modify / add new properties? #47

Closed FoggyFinder closed 7 months ago

FoggyFinder commented 5 years ago

I want to have ability modify or add some properties. I tried to do something like that:

var stream = (CFStream)item;
var containter = ((CFStream)item).AsOLEPropertiesContainer();
containter.NewProperty(OpenMcdf.Extensions.OLEProperties.VTPropertyType.VT_INT, 78787878, "Some test property");
var pr = containter.Properties.First(p => p.PropertyName.Contains(name));
pr.Value = "This is a new test value";

But when I'd opened file I didn't see any changes.

Am I doing it in wrong way or it is current library limitation?

Numpsy commented 5 years ago

Try calling Save on the OLEPropertiesContainer and/or CompoundFile ?

FoggyFinder commented 5 years ago

I tried - doesn't work either

ironfede commented 5 years ago

@FoggyFinder OLEProperties are currently in development stage. I'll try to give a look at your issue this week but I'm currently involved in other work activities and i can't give a definite time schedule for full implementation. Thank you for your patience.

Yvorl1 commented 1 year ago

Hello @ironfede, do you have any update on this? It would be nice to be able to add new properties to the DocumentSummaryInformation. Thank you.

Numpsy commented 1 year ago

I tried having a go at adding/manipulating properties in the document summary information set, using

using (CompoundFile cf = new CompoundFile("_Test.ppt"))
{
    var dsiStream = cf.RootStorage.GetStream("\u0005DocumentSummaryInformation");
    var co = dsiStream.AsOLEPropertiesContainer();

    co.Properties.First(prop => prop.PropertyName == "PIDDSI_COMPANY").Value = "RHUBARB";

    var newProp = co.NewProperty(OpenMcdf.Extensions.OLEProperties.VTPropertyType.VT_LPSTR, 0x0000000E, "PIDDSI_MANAGER");
    newProp.Value = "The Boss";
    co.AddProperty(newProp);

    co.Save(dsiStream);

    cf.SaveAs(@"S:\test\test.ppt");
}

And it appeared to work, except that the manager value is displayed ok in structured storage explorer but is shown as The Bos in power point.

I think the issue is that the strings are supposed to be written into the file with null terminator characters included in the length, and the current OpenMcdf function doesn't do it -

image

So I guess that powerpoint must be cutting off the last char or something, rather than the last null?

I'll have a go at making https://github.com/ironfede/openmcdf/blob/2ecc5da15111923bb5ab4d9abc371bf799f95626/sources/OpenMcdf.Extensions/OLEProperties/PropertyFactory.cs#L423 write an extra null byte when i get some time.

ironfede commented 7 months ago

@Numpsy , do you think that your recent PRs closes this issue? Many thanks!

Numpsy commented 7 months ago

I think the main functionality for writing properties should be working now, besides the other case with unaligned strings discussed in #98

ironfede commented 7 months ago

Many thanks @Numpsy . I close this issue to mark advancements in this subject. Thank you!

farfilli commented 4 months ago

I have tried this code:

Dim cfg As CFSConfiguration = CFSConfiguration.SectorRecycle Or CFSConfiguration.EraseFreeSectors
Dim fs = New FileStream("C:\Users\stazione41\Documents\cil2.par", FileMode.Open, FileAccess.ReadWrite)

Dim cf As CompoundFile = New CompoundFile(fs, CFSUpdateMode.Update, cfg)
Dim foundStream As CFStream = cf.RootStorage.GetStream("SummaryInformation")

Dim c As OLEPropertiesContainer = foundStream.AsOLEPropertiesContainer
c.Properties(2).Value = "801050004 MODIFICATO"

'c.Save(foundStream)
'cf.Save(foundStream.AsIOStream)
'cf.Commit()

cf.Close()

I read and modify the property Title correctly, however I'm not able to save it

With cf.Commit the change to the property Title it's not saved With c.Save(foundStream) the Document properties are no longer visible With cf.Save(foundStream.AsIOStream) the code never terminate

Any suggestion or there are code changes on their way?

Numpsy commented 4 months ago

Try doing c.Save(foundStream) followed by cf.Commit() ?

There are some tests that update properties at https://github.com/ironfede/openmcdf/blob/591eaea6c8c31abd944c6e441ea1f8b9c0353188/sources/Test/OpenMcdf.Extensions.Test/OLEPropertiesExtensionsTest.cs#L133 and I have apps working with it, though there are still a few bugs in it, e.g. https://github.com/ironfede/openmcdf/pull/128

farfilli commented 4 months ago

Thanks for the effort @Numpsy but nothing is working; I looked at the examples but simply doesn't work; can you post your working code to modify a SummaryInformation section property?

In the attachment the file I try to change the properties cil2.zip

Numpsy commented 4 months ago

I'll give it a proper test later, but it might be that this VT_CF type property is falling over #128 when writing the file:

image

I didn't have a test file with such a property when I did #128, so I'll have a look and see if that is falling over the same bug

Numpsy commented 4 months ago

That does look to be the problem - If I just use OpenMcdf to open and then save the SummaryInformation section in that file without any other changes then StructuredStorageExplorer gets an error when trying to read it afterwards, and it seems ok when ising the changes from #128.

farfilli commented 4 months ago

Many thanks @Numpsy this code works now

Dim cfg As CFSConfiguration = CFSConfiguration.SectorRecycle Or CFSConfiguration.EraseFreeSectors
Dim fs = New FileStream("C:\Users\stazione41\Documents\cil2.par", FileMode.Open, FileAccess.ReadWrite)

Using cf As CompoundFile = New CompoundFile(fs, CFSUpdateMode.Update, cfg)

    Dim dsiStream As CFStream = cf.RootStorage.GetStream("SummaryInformation")
    Dim co As OLEPropertiesContainer = dsiStream.AsOLEPropertiesContainer

    Dim titleProp = co.Properties.First(Function(Prop) Prop.PropertyName = "PIDSI_TITLE")
    titleProp.Value = "XXXX PROVA"

    co.Save(dsiStream)
    cf.Commit()

End Using