{"id":2086,"date":"2020-07-16T09:50:27","date_gmt":"2020-07-16T07:50:27","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=2086"},"modified":"2020-07-16T13:21:17","modified_gmt":"2020-07-16T11:21:17","slug":"c-winrt-version-of-setfiletime","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/2086","title":{"rendered":"C++\/WinRT version of SetFileTime"},"content":{"rendered":"\n<p><code><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/fileapi\/nf-fileapi-setfiletime\">SetFileTime<\/a><\/code> is simple and does not deserve a blog post: you have a file handle, you have date\/time, you set it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>StorageFile File { ... };\nFILETIME DateCreatedFileTime = ...;\nwinrt::file_handle File { CreateFile(File.Path().c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) };\nwinrt::check_bool(SetFileTime(File.get(), &amp;DateCreatedFileTime, &amp;DateCreatedFileTime, &amp;DateCreatedFileTime));<\/code><\/pre>\n\n\n\n<p>C++\/WinRT and UWP make the journey much more exciting.<\/p>\n\n\n\n<p>There is <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/windows.storage.fileproperties.storageitemcontentproperties?view=winrt-19041\"><code>StorageItemContentProperties<\/code> Class<\/a> which provides access to the content-related properties of an item (like a file or folder). This includes file times which are exposed as named properties, like <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/properties\/props-system-datemodified\">&#8220;System.DateModified&#8221;<\/a>. <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/windows.storage.fileproperties.storageitemcontentproperties.savepropertiesasync?view=winrt-19041\"><code>StorageItemContentProperties.SavePropertiesAsync<\/code> Method<\/a> is to save properties associated with the item.<\/p>\n\n\n\n<p><code>SavePropertiesAsync<\/code> is asynchronous so you have to deal with this too, but it is not to worry since C++\/WinRT does not let you down with this at least.<\/p>\n\n\n\n<p>One another thing is you need a <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/windows.foundation.datetime?view=winrt-19041\"><code>Windows::Foundation::DateTime<\/code><\/a> value for the time which is something you might be not have good understanding for, as opposed to old fashioned <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/minwinbase\/ns-minwinbase-filetime\"><code>FILETIME'<\/code>s definition<\/a> of &#8220;a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC)&#8221;.<\/p>\n\n\n\n<p>In C++\/WinRT <code>Windows::Foundation::DateTime<\/code> is directly mapped to <code>std::chrono::time_point<\/code> and there is also <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/cpp-ref-for-winrt\/clock\"><code>winrt::clock<\/code><\/a> as well, and conversion helpers which are easy to use but you have to be aware of them.<\/p>\n\n\n\n<p>Moving on? With <a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/windows.foundation.datetime?view=winrt-19041\"><code>Windows::Foundation::DateTime<\/code><\/a> value on hands you need to put it into a key-value collection of properties to save. However, since values, in general, might be of different types you need to convert the time to <s>variant<\/s> <code>IInspectable<\/code>. That is, to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/uwp\/cpp-and-winrt-apis\/boxing\">&#8220;box&#8221;<\/a> it. Luckily, C++\/WinRT has it all for you already:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/uwp\/cpp-and-winrt-apis\/intro-to-using-cpp-with-winrt\">C++\/WinRT<\/a>&nbsp;provides the&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/cpp-ref-for-winrt\/box-value\"><strong>winrt::box_value<\/strong><\/a>&nbsp;function, which takes a scalar value and returns the value boxed into an&nbsp;<strong>IInspectable<\/strong>. For unboxing an&nbsp;<strong>IInspectable<\/strong>&nbsp;back into a scalar value, there are the&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/cpp-ref-for-winrt\/unbox-value\"><strong>winrt::unbox_value<\/strong><\/a>&nbsp;and&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/cpp-ref-for-winrt\/unbox-value-or\"><strong>winrt::unbox_value_or<\/strong><\/a>&nbsp;functions.<\/p><\/blockquote>\n\n\n\n<p>Now we reached a hard one. <code>SavePropertiesAsync<\/code> signature is this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...SavePropertiesAsync(param::async_iterable&lt;Windows::Foundation::Collections::IKeyValuePair&lt;hstring, Windows::Foundation::IInspectable>> const&amp; propertiesToSave) const\n{\n  ...\n}<\/code><\/pre>\n\n\n\n<p>So <code>IInspectable<\/code> there is the boxed value. This needs to be taken into something convertible to <code>Windows::Foundation::Collections::IKeyValuePair<\/code> which is already a bit scary. But the truth is the real bastard is <code>param::async_iterable<\/code>.<\/p>\n\n\n\n<p>I have to admit MSDN documentation for C++\/WinRT is awesome. There are so many things already mentioned there, including, for example, this article: <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/uwp\/cpp-and-winrt-apis\/std-cpp-data-types\">Standard C++ data types and C++\/WinRT<\/a>, which is relevant and helpful. C++\/WinRT is awesome too. <\/p>\n\n\n\n<p>So you might think you could just have a std::map and it will be converted to <code>Windows::Foundation::Collections::IKeyValuePair<\/code> automagically and then it would be picked up by <code>param::async_iterable<\/code> as an argument? No. <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[...]\nerror C2664: 'winrt::Windows::Foundation::IAsyncAction winrt::impl::consume_Windows_Storage_FileProperties_IStorageItemExtraProperties::SavePropertiesAsync(void) const': cannot convert argument 1 from 'std::map,std::allocator&gt;&gt;' to 'const winrt::param::async_iterable&gt; &amp;'\n[...]\nReason: cannot convert from 'std::map,std::allocator&gt;&gt;' to 'const winrt::param::async_iterable&gt;'\n[...]\nNo user-defined-conversion operator available that can perform this conversion, or the operator cannot be called<\/pre>\n\n\n\n<p>The thing is, and it&#8217;s mentioned <a href=\"https:\/\/github.com\/microsoft\/cppwinrt\/issues\/341#issuecomment-378781256\">here<\/a>, for example, that <code>async_iterable<\/code> need to acquire ownership of the collection when it takes it as an argument in a thin and lightweight way. So you have got to <code>std::move<\/code> it there before the code starts building.<\/p>\n\n\n\n<p>What do we got? Thing do build and call UWP API correctly. Everything is important here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>StorageFile File { ... };\nFILETIME DateCreatedFileTime = ...;\nstd::map&lt;winrt::hstring, winrt::Windows::Foundation::IInspectable> PropertyMap;\nPropertyMap.emplace(L\"System.DateModified\", winrt::box_value(winrt::clock::from_file_time(DateCreatedFileTime)));\nFile.Properties().SavePropertiesAsync(std::move(PropertyMap)).get();<\/code><\/pre>\n\n\n\n<p>Now the problem is that runtime behavior is this: <code>E_INVALIDARG<\/code> 0x80070057 : &#8216;Cannot write to the specified property (System.DateModified). The property is read-only.&#8217;.<\/p>\n\n\n\n<p>That is, <a href=\"https:\/\/social.msdn.microsoft.com\/Forums\/windowsapps\/en-US\/4e8571b8-10ce-41a7-aea8-3f7705a75cd7\/uwphow-to-set-creation-and-modification-time-of-a-file-from-a-uwp-app\">you don&#8217;t change\/save this property from UWP<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>SetFileTime is simple and does not deserve a blog post: you have a file handle, you have date\/time, you set it. C++\/WinRT and UWP make the journey much more exciting. There is StorageItemContentProperties Class which provides access to the content-related properties of an item (like a file or folder). This includes file times which are&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/2086\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[588,581],"class_list":["post-2086","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c-winrt","tag-winapi-2"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/2086","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=2086"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/2086\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=2086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=2086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=2086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}