Unable to read all folder properties

Jun 18, 2010 at 10:20 PM

I am having problem reading all folder's propertiy's values. My code throws an exception after reading the third property and every one after that. Here is what I do

 void getProperties(folder folder) {
  property_bag bag = folder.get_property_bag();
  vector<prop_id> ids = bag.get_prop_list();
  for(vector<prop_id>::const_iterator it = ids.begin(); it != ids.end(); ++it) {

   try {
      // the line below works for first two properties (12289:PR_DISPLAY_NAME and 12292:PR_COMMENT), but starting with third (13826:PR_CONTENT_COUNT) it throws
      // "key not found" exception in line 1411 of node.h 
      //=======================================
      pstsdk::prop_stream stream(bag.open_prop_stream( *it));    
      std::vector<pstsdk::byte> content = bag.read_prop<std::vector<pstsdk::byte>>( *it);
      sreeam.close();
   } catch (std:exceptio n& e) {
      error = e.what();
   }

   //... do something with content

  }
 }

Coordinator
Jun 18, 2010 at 11:13 PM
The problem here is that you can only open strings and other variable length props as streams. This should probably throw a better error and/or be documented better.
Jun 19, 2010 at 12:25 AM

Does it mean that it is impossible to read all the properties from PST layer?  I may be missing something, but open_prop_stream is the only public "content reading" method of  property_bag class.

Coordinator
Jun 19, 2010 at 2:57 AM

open_prop_stream is not the only public "content reading" method of the property_bag class - in fact, you correctly used the main content reading method in your example: read_prop<T>. Properties are typed, so you're responsible for giving the correct T for the property type you're reading (for PR_CONTENT_COUNT, you'll probably want read_prop<ulong>). All you're doing with the stream is immediately opening it and then closing it. I'm not sure why you're doing that - although I'd like to know what led you to believe you had to, so I can improve the documentation.

The purpose of open_prop_stream is to give users the option of creating a stream interface over any property which is too large to be comfortable read with read_prop<T>. You probably only want to use it when reading very large properties, or when you only want to read a small part of a large property.

Jun 19, 2010 at 3:10 PM
Edited Jun 19, 2010 at 3:18 PM

The reason why I tried to use the streams is because my code needs to compare properties of two folders (or messages) with the same name. I code doesn't really care about the type or content. Having that in mind dumping the property value into a byte vector and comparing two vectors seemed like good idea.

Dec 14, 2010 at 1:50 PM

On the topic of reading and dumping all the properties, I have the following. Can someone help me fill out the types which I have left blank in the code below? Specifically, how to read (a) variable and multi value types and (b) apptime - how to convert that into time_t?

void dump_property_bag (const property_bag &bag)
{
  vector<pstsdk::prop_id> props = bag.get_prop_list();
  prop_type pt;

  int j = 0;
  for(vector<prop_id>::iterator i = props.begin(); i != props.end(); ++i) {
    pt = bag.get_prop_type(*i);

    cout << "Prop # "           << setw(3) << right   << j++
         << "  Prop_Id = 0x"    << hex     << setw(5) << *i
         << "  Prop_type_id = " << dec     << setw(4) << pt   << ": ";

    switch (pt) {

    case prop_type_unspecified:
      wcout << "Unspecified Prop Type";
      break;
    case prop_type_null:
      wcout << "Null Prop Type";
      break;
    case prop_type_short:
      wcout << bag.read_prop<short>(*i);
      break;
    case prop_type_long:
      wcout << bag.read_prop<long>(*i);
      break;
    case prop_type_float:
      wcout << bag.read_prop<float>(*i);
      break;
    case prop_type_double:
      wcout << bag.read_prop<double>(*i);
      break;
    case prop_type_boolean:
      wcout << bag.read_prop<bool>(*i);
      break;
    case prop_type_longlong:
      wcout << bag.read_prop<long long>(*i);
      break;
    case prop_type_string:
      cout << bag.read_prop<string>(*i);
      break;
    case prop_type_wstring:
      wcout << bag.read_prop<wstring>(*i);
      break;
    case prop_type_currency: {
      uint64_t curr = bag.read_prop<uint64_t>(*i);
      long long major = curr / 1000;
      int       minor = curr % 1000;
      wcout << major + minor/1000.0;
      break;
    }
    case prop_type_error:
      wcout << bag.read_prop<uint32_t>(*i);
      break;
    case prop_type_binary: {
      unsigned short size = bag.read_prop<unsigned short>(*i);
      wcout << size << " bytes: ";
      // Need Help
      break;
    }
    case prop_type_systime: {
      time_t t = filetime_to_time_t(bag.read_prop<ulonglong>(*i));
      wcout << ctime(&t);
      break;
    }
    case prop_type_apptime:
    case prop_type_guid:
    case prop_type_object:
    case prop_type_mv_short:
    case prop_type_mv_long:
    case prop_type_mv_float:
    case prop_type_mv_double:
    case prop_type_mv_currency:
    case prop_type_mv_apptime:
    case prop_type_mv_longlong:
    case prop_type_mv_string:
    case prop_type_mv_wstring:
    case prop_type_mv_systime:
    case prop_type_mv_guid:
    case prop_type_mv_binary:
      wcout << "** Multi Value Type. Need Help here, please!";
      break;
    default: 
      wcout << "** Default Type. Error.";
    }
    wcout << endl;
  }
}

Coordinator
Dec 14, 2010 at 7:18 PM

For any property T, to read the multivalued version of that property use read_prop<std::vector<T>>(id);

For binary properties, call read_prop<std::vector<byte>>(id);

For a multivalued binary property, call read_prop<std::vector<std::vector<byte>>>(id); etc.

There is also a time_t specific method to use for non-VC compilers.

Dec 15, 2010 at 7:49 AM

Terry, thanks for your response. If I modify the above code and send it over, would you be interested in including it in the samples/ directory?

Coordinator
Dec 16, 2010 at 10:18 PM

Sure!