adding/editing 现有文件中详细信息选项卡的新扩展属性
adding/editing new extended properties to the details tab in existing files
我试着在 SO 上看这个,但所有试图回答的问题都没有提供完整的答案。
我实际上想在现有文件的详细信息选项卡中添加一个 属性。文件的扩展名为 sldprt。 property/value 必须在 Windows 资源管理器中可见。
不确定如何使用 Windows API 代码包 Shell 或 DSOFile 来完成?任何其他解决方案也可以。
我在 Windows 10.
上使用 VS、C#
如果有人能提供详细的解决方案,将不胜感激
完美的解决方案是:
- 通过 dsofile、ADS 或任何可能的方式将 属性 添加到文件中。
- 编辑 Windows 注册表或 Windows 的任何部分,负责在文件属性的详细信息选项卡和 Windows 资源管理器中显示新的 属性
- 说明如何编辑 属性 的值。
这个 question 的回答没有向详细信息选项卡添加属性,也没有向 Windows 资源管理器详细视图添加属性。
我认为这是可能的,因为 SOLIDWORKS(3d 包)向所有 SOLIDWORKS 文件添加了一个名为 sw 最后保存为 的 属性。详细信息中还有大量其他属性 window。
如果您没有正确的解决方案,请不要回答。非常感谢。
我不确定这个问题是否与 Add new metadata properties to a file 重复。
预览:
编辑:
sldprt 扩展的注册表(供参考):
属性 window 中的详细信息选项卡填充有 metadata property handlers。元数据 属性 系统是 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 (Component Object Model) is Microsoft's attempt at a language-independent object oriented framework whose origins go all the way back to the nineties, but for the purposes of this explanation suffice it to say that a COM object is a C++ class that implements the IUnknown
interface. A property handler has to implement the 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
结构包含该 GUID 以标识 属性。 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;
}
获得后,可以在 IPropertyStore
对象上调用 GetValue
和 SetValue
来获得、更改或设置 属性 的新值。如果使用 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;
}
在 Windows 7 个 SDK 示例包中有两个完整的示例项目演示了如何做到这一点:RecipePropertyHandler and PlaylistPropertyHandler。
主要思想是实现 IPropertyStore 接口,有点像 collection/iterator:
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
调用以提供 属性 名称和值。
我喜欢做所有这些的示例项目,并附带有关如何注册 属性 处理程序的说明。
P.S。 mnistic 的回答主要讨论了一种将属性(和值)添加到某些文件系统中存在的 单个文件 的方法。此答案提供了将 属性 添加到特定文件 type.
的一般解决方案
我试着在 SO 上看这个,但所有试图回答的问题都没有提供完整的答案。
我实际上想在现有文件的详细信息选项卡中添加一个 属性。文件的扩展名为 sldprt。 property/value 必须在 Windows 资源管理器中可见。
不确定如何使用 Windows API 代码包 Shell 或 DSOFile 来完成?任何其他解决方案也可以。
我在 Windows 10.
上使用 VS、C#如果有人能提供详细的解决方案,将不胜感激
完美的解决方案是:
- 通过 dsofile、ADS 或任何可能的方式将 属性 添加到文件中。
- 编辑 Windows 注册表或 Windows 的任何部分,负责在文件属性的详细信息选项卡和 Windows 资源管理器中显示新的 属性
- 说明如何编辑 属性 的值。
这个 question 的回答没有向详细信息选项卡添加属性,也没有向 Windows 资源管理器详细视图添加属性。
我认为这是可能的,因为 SOLIDWORKS(3d 包)向所有 SOLIDWORKS 文件添加了一个名为 sw 最后保存为 的 属性。详细信息中还有大量其他属性 window。
如果您没有正确的解决方案,请不要回答。非常感谢。
我不确定这个问题是否与 Add new metadata properties to a file 重复。
预览:
编辑:
sldprt 扩展的注册表(供参考):
属性 window 中的详细信息选项卡填充有 metadata property handlers。元数据 属性 系统是 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 (Component Object Model) is Microsoft's attempt at a language-independent object oriented framework whose origins go all the way back to the nineties, but for the purposes of this explanation suffice it to say that a COM object is a C++ class that implements the IUnknown
interface. A property handler has to implement the 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
结构包含该 GUID 以标识 属性。 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;
}
获得后,可以在 IPropertyStore
对象上调用 GetValue
和 SetValue
来获得、更改或设置 属性 的新值。如果使用 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;
}
在 Windows 7 个 SDK 示例包中有两个完整的示例项目演示了如何做到这一点:RecipePropertyHandler and PlaylistPropertyHandler。
主要思想是实现 IPropertyStore 接口,有点像 collection/iterator:
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
调用以提供 属性 名称和值。
我喜欢做所有这些的示例项目,并附带有关如何注册 属性 处理程序的说明。
P.S。 mnistic 的回答主要讨论了一种将属性(和值)添加到某些文件系统中存在的 单个文件 的方法。此答案提供了将 属性 添加到特定文件 type.
的一般解决方案