добавление / редактирование новых расширенных свойств на вкладку сведений в существующих файлах - PullRequest
0 голосов
/ 04 июня 2018

Я пытался посмотреть это на SO, но все вопросы, на которые пытались ответить, не дают полного ответа.

Я на самом деле хочу добавить свойство на вкладку сведений существующего файла.Файл имеет расширение sldprt.Свойство / значение должно быть видно в проводнике Windows.

Не знаете, как это сделать с помощью Windows API Code Pack Shell или DSOFile?Любое другое решение тоже подойдет.

Я использую VS, C # в Windows 10.

Если бы кто-то мог предоставить подробное решение, я был бы очень благодарен.

Идеальное решение было бы:

  • Добавьте свойство в файл с помощью dsofile, ADS или любыми возможными способами.
  • Редактирование в Windows Registery или любой другой части Windows, которая отвечает за отображениеновое свойство на вкладке сведений о свойствах файла и в проводнике Windows
  • Показать, как можно изменить значение свойства.

Этот ответ на этот вопрос делаетне добавляйте атрибуты на вкладку сведений и подробный вид Windows Explorer.

Я думаю, что это возможно, поскольку SOLIDWORKS (3d-пакет) добавляет свойство с именем sw, которое последний раз сохранялось с , во все файлы SOLIDWORKS.В окне сведений есть множество других свойств.

Пожалуйста, если у вас нет правильного решения, не отвечайте.Большое спасибо.

Я не уверен, что этот вопрос является дубликатом Добавить новые свойства метаданных в файл .

Превью:

enter image description here enter image description here

Редактировать:

Зарегистрироваться для sldprtрасширение (для справочных целей):

enter image description here

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Существует два полномасштабных примера проектов, демонстрирующих, как это сделать в пакете примеров Windows 7 SDK: RecipePropertyHandler и PlaylistPropertyHandler .

Основная идея заключается в том,реализация интерфейса IPropertyStore , который немного похож на коллекцию / итератор:

Commit    Saves a property change.
GetAt     Gets a property key from an item's array of properties.
GetCount  Gets the number of properties attached to the file.
GetValue  Gets data for a specific property.
SetValue  Sets a new property value, or replaces or removes an existing value.

Ваш код должен инициализировать обработчик путем реализации интерфейса IInitializeWithStream .Затем он должен ответить на вызовы GetCount, GetAt и GetValue, чтобы указать имя и значение свойства.

Образцы проектов, которые мне нравятся, делают все это и идут с инструкциями покак зарегистрировать обработчики свойств.

PS Ответ Mnistic в основном говорит о способе добавления свойств (и значений) к отдельным файлам , существующим в некоторой файловой системе.Этот ответ предоставляет общее решение для добавления свойства в конкретный файл type .

0 голосов
/ 08 июня 2018

Вкладка сведений в окне свойств заполнена обработчиками свойств метаданных .Система свойств метаданных - это то, что Microsoft представила в Windows Vista, и она стала открытой и расширяемой, что позволяет независимым разработчикам (таким как Solidworks) реализовывать и поддерживать свои собственные свойства файлов.Грубо говоря, поток выполнения выглядит примерно так:

User clicks file properties
Look up property handler for the file format
If found property handler:
    Query property handler for properties
    Populate file details with queried properties
Else:
    Populate file details with generic file info

Обработчики свойств являются объектами COM. COM (объектная модель компонентов) - это попытка Microsoft создать независимую от языка объектно-ориентированную инфраструктуру, происхождение которой восходит к девяностым годам, но для целей этого объяснения достаточно сказать, что объект COM являетсякласс C ++, который реализует интерфейс IUnknown.В дополнение к этому обработчик свойств должен реализовать интерфейс IPropertyStore:

struct IPropertyStore : public IUnknown
{
public:
    virtual HRESULT GetCount( 
        DWORD *cProps) = 0;

    virtual HRESULT GetAt( 
        DWORD iProp,
        PROPERTYKEY *pkey) = 0;

    virtual HRESULT GetValue( 
        REFPROPERTYKEY key,
        PROPVARIANT *pv) = 0;

    virtual HRESULT SetValue( 
        REFPROPERTYKEY key,
        REFPROPVARIANT propvar) = 0;

    virtual HRESULT Commit( void) = 0;
};

Удобная реализация этого интерфейса - CLSID_InMemoryPropertyStore, предоставленная разработчикам.чтобы облегчить собственную реализацию IPropertyStore.Интересные методы здесь GetValue и SetValue.Для свойств назначается уникальный GUID, который структура PROPERTYKEY, переданная в эти функции, содержит для идентификации свойства.Детали реализации для GetValue и SetValue оставлены на усмотрение разработчика, так что разработчик должен решить, как и где хранить значение для каждого свойства - эти значения могут быть сохранены в другом файле, в потоке альтернативного файла.или в реестре назвать несколько вариантов - но по соображениям транспортабельности рекомендуется хранить значения в самом файле.Таким образом, если файл заархивирован и отправлен, например, по электронной почте, свойства идут вместе с ним.

COM-объект обработчика свойств компилируется в DLL и регистрируется в системе с regsvr32.Это позволяет Windows знать, где искать свойства для этого конкретного формата файла.После регистрации обработчик свойства можно получить несколькими способами, одним из которых является вспомогательная функция SHGetPropertyStoreFromParsingName:

HRESULT GetPropertyStore(PCWSTR pszFilename, GETPROPERTYSTOREFLAGS gpsFlags, IPropertyStore** ppps)
{
    WCHAR szExpanded[MAX_PATH];
    HRESULT hr = ExpandEnvironmentStrings(pszFilename, szExpanded, ARRAYSIZE(szExpanded)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
    if (SUCCEEDED(hr))
    {
        WCHAR szAbsPath[MAX_PATH];
        hr = _wfullpath(szAbsPath, szExpanded, ARRAYSIZE(szAbsPath)) ? S_OK : E_FAIL;
        if (SUCCEEDED(hr))
        {
            hr = SHGetPropertyStoreFromParsingName(szAbsPath, NULL, gpsFlags, IID_PPV_ARGS(ppps));
        }
    }
    return hr;
}

После получения GetValue и SetValue можно вызвать для объекта IPropertyStore, чтобы получить, изменить или установить новое значение для свойства.Однако при использовании SetValue обязательно вызовите также Commit.


Microsoft предоставляет утилиту под названием PropertyEdit, чтобы получитьи установить свойства метаданных для файла как часть их классических образцов Windows.Жаль, что они нигде не упоминают об этом на своих страницах помощи.Поскольку у вас уже установлен Solidworks, обработчик свойств для форматов файлов, которые вас интересуют, уже должен быть зарегистрирован в системе, и это должно быть вопросом компиляции PropertyEdit и использования его для получения и установки свойств метаданных, поддерживаемых обработчиком.,Это простая утилита командной строки.

Если вам нужно или вы хотите поддерживать собственные метаданные для вашего собственного формата файла, есть также полнофункциональный обработчик свойств образца: RecipePropertyHandler.

Для справки: установить свойство по его каноническому имени:

HRESULT GetPropertyStore(PCWSTR pszFilename, GETPROPERTYSTOREFLAGS gpsFlags, IPropertyStore** ppps)
{
    WCHAR szExpanded[MAX_PATH];
    HRESULT hr = ExpandEnvironmentStrings(pszFilename, szExpanded, ARRAYSIZE(szExpanded)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
    if (SUCCEEDED(hr))
    {
        WCHAR szAbsPath[MAX_PATH];
        hr = _wfullpath(szAbsPath, szExpanded, ARRAYSIZE(szAbsPath)) ? S_OK : E_FAIL;
        if (SUCCEEDED(hr))
        {
            hr = SHGetPropertyStoreFromParsingName(szAbsPath, NULL, gpsFlags, IID_PPV_ARGS(ppps));
        }
    }
    return hr;
}

HRESULT SetPropertyValue(PCWSTR pszFilename, PCWSTR pszCanonicalName, PCWSTR pszValue)
{
    // Convert the Canonical name of the property to PROPERTYKEY
    PROPERTYKEY key;
    HRESULT hr = PSGetPropertyKeyFromName(pszCanonicalName, &key);
    if (SUCCEEDED(hr))
    {
        IPropertyStore* pps = NULL;

        // Call the helper to get the property store for the
        // initialized item
        hr = GetPropertyStore(pszFilename, GPS_READWRITE, &pps);
        if (SUCCEEDED(hr))
        {
            PROPVARIANT propvarValue = {0};
            hr = InitPropVariantFromString(pszValue, &propvarValue);
            if (SUCCEEDED(hr))
            {
                hr = PSCoerceToCanonicalValue(key, &propvarValue);
                if (SUCCEEDED(hr))
                {
                    // Set the value to the property store of the item.
                    hr = pps->SetValue(key, propvarValue);
                    if (SUCCEEDED(hr))
                    {
                        // Commit does the actual writing back to the file stream.
                        hr = pps->Commit();
                        if (SUCCEEDED(hr))
                        {
                            wprintf(L"Property %s value %s written successfully \n", pszCanonicalName, pszValue);
                        }
                        else
                        {
                            wprintf(L"Error %x: Commit to the propertystore failed.\n", hr);
                        }
                    }
                    else
                    {
                        wprintf(L"Error %x: Set value to the propertystore failed.\n", hr);
                    }
                }
                PropVariantClear(&propvarValue);
            }
            pps->Release();
        }
        else
        {
            wprintf(L"Error %x: getting the propertystore for the item.\n", hr);
        }
    }
     else
    {
        wprintf(L"Invalid property specified: %s\n", pszCanonicalName);
    }
    return hr;
}
...