{"id":8471,"date":"2012-08-04T00:01:00","date_gmt":"2012-08-04T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/08\/04\/weekend-scripter-use-powershell-to-set-word-document-time-stamps\/"},"modified":"2012-08-04T00:01:00","modified_gmt":"2012-08-04T00:01:00","slug":"weekend-scripter-use-powershell-to-set-word-document-time-stamps","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-use-powershell-to-set-word-document-time-stamps\/","title":{"rendered":"Weekend Scripter: Use PowerShell to Set Word Document Time Stamps"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to set the time stamps on Microsoft Word document files.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. It is Saturday here in Charlotte, and the sunshine continues to make its presence known. It seems that the sun gets up rather early during the summer, and retires in the evening rather late. It is just around 6:00 in the morning, and I am sitting on the lanai drinking a cup of English breakfast tea with a cinnamon stick and about a half spoonful of hibiscus flower in the tea. The hibiscus flower gives the tea a nice citrus flavor without all the carbs. I have one of my Windows 8 laptops with me in the swing and am checking my email. I really love Windows 8, and I cannot wait until I can buy the Scripting Wife a Microsoft Surface. She has been begging for one since she saw one at the Atlanta TechStravaganza. (<a href=\"http:\/\/www.ftc.gov\/opa\/2009\/10\/endortest.shtm\" target=\"_blank\">United States FTC Disclaimer<\/a>: I work for the Microsoft Corporation, and Microsoft provides me my laptop and the Windows 8 bits for my laptop. They did not build my lanai, nor do they provide me with English breakfast tea at home. However, when I am in the Microsoft office, they do provide me with English breakfast tea.)<\/p>\n<h2>The problem with file time stamps<\/h2>\n<p>A few months ago, I wrote a <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/06\/01\/use-powershell-to-modify-file-access-time-stamps.aspx\" target=\"_blank\">function that uses Windows PowerShell to modify file access time stamps<\/a>. In the Hey, Scripting Guy! Blog where I discussed this technique, I envisioned creating a single <b>DateTime<\/b> object and using that to set all three of the file access time stamps. I even discussed my use case scenario, which was to use the technique as a sort of cheap versioning system while I was working on the Windows 7 Resource Kit.<\/p>\n<p>This week, however, as I began working with the Word documents stored on my computer for all of the Hey Scripting Guy! Blogs I have written, I came up with another use for the function&minus;to correct time stamps that are modified through various means (such as backup and restore from a network SAN and modifications created to Microsoft Word built-in properties). Luckily, all of my Hey, Scripting Guy! Blogs have a file name based on the date in which the blog appears. For example, the file for today&rsquo;s Weekend Scripter is: WES-8-4-12.docx. I am assured the file names are consistent because I have a Windows PowerShell script that creates all of the 365 files I need each year (the script also creates folders for each week of the year, and folders for each year.<\/p>\n<p>With a file name of WES-8-4-12 or HSG-8-2-12, it is really easy to find the date portion of the file name. All I need to do is to retrieve the item (by using <b>Get-Item<\/b> or <b>Get-ChildItem<\/b>). WhenI have the <b>FileInfo<\/b><i> <\/i>object, I use the <b>BaseName<\/b><i> <\/i>property to obtain only the file name without the path or the file extension. Therefore, in my example, HSG-7-23-12 returns the following.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a = Get-Item C:\\fso\\HSG-7-23-12.docx<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a.basename<\/p>\n<p style=\"padding-left: 30px\">HSG-7-23-12<\/p>\n<p>When I have a value such as HSG-7-23-12, I can easily convert that value to provide me with a <b>DateTime<\/b><i> <\/i>object. To do this, I first remove the <i>HSG-<\/i> portion of the filename. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a = Get-Item C:\\fso\\HSG-7-23-12.docx<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a.basename<\/p>\n<p style=\"padding-left: 30px\">HSG-7-23-12<\/p>\n<p style=\"padding-left: 60px\">PS C:\\&gt; $a.BaseName.Substring(4)<\/p>\n<p style=\"padding-left: 60px\">7-23-12<\/p>\n<p>Now, all I need to do is to cast that value to a <i>datetime <\/i>object and I am finished. This appears here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a = Get-Item C:\\fso\\HSG-7-23-12.docx<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a.basename<\/p>\n<p style=\"padding-left: 30px\">HSG-7-23-12<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $a.BaseName.Substring(4)<\/p>\n<p style=\"padding-left: 30px\">7-23-12<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; [datetime]$a.BaseName.Substring(4)<\/p>\n<p style=\"padding-left: 30px\">Monday, July 23, 2012 12:00:00 AM<\/p>\n<p>The commands and the output associated with the commands are shown in the figure that follows.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4747.wes-8-4-12-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4747.wes-8-4-12-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Interestingly enough, it is possible to do this all on a single line. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; [datetime](Get-Item C:\\fso\\HSG-7-23-12.docx).basename.substring(4)<\/p>\n<p style=\"padding-left: 30px\">Monday, July 23, 2012 12:00:00 AM<\/p>\n<h2>Expanding the technique a bit<\/h2>\n<p>Now that I know I can create a <b>DateTime<\/b><i> <\/i>object from the base file name, it is a simple matter of replacing <b>Get-ChildItem<\/b> for <b>Get-Item<\/b>, and looping through the returned files. I talked about <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/07\/30\/use-powershell-to-explore-nested-directories-and-files.aspx\" target=\"_blank\">filtering files on Monday<\/a> of this week and on <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/07\/31\/use-powershell-to-help-find-all-of-your-images.aspx\" target=\"_blank\">Tuesday of the week<\/a>.<\/p>\n<p>Because Microsoft Word changed the file extension during the four years that I have been writing the Hey, Scripting Guy! Blog, I decided to use a wild card character in the <b>extension<\/b> property. To see how many of each type of files I have, I used the following command where I group by the extension. The command and the output associated with the command are shown here (<b>gci<\/b> is an alias for the <b>Get-ChildItem<\/b> cmdlet).<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-ChildItem -Recurse -Path C:\\data\\ScriptingGuys -Include HSG*.doc*,WES*.doc* | group<\/p>\n<p style=\"padding-left: 30px\">&nbsp;extension<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Count Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Group<\/p>\n<p style=\"padding-left: 30px\">&#8212;&#8211; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 731 .docx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;{C:\\data\\ScriptingGuys\\2008\\hsg_11_17_08\\HSG_QHF_&#8230;<\/p>\n<p style=\"padding-left: 30px\">&nbsp; 359 .Doc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {C:\\data\\ScriptingGuys\\2009\\HSG_10_12_09\\HSG-10-1&#8230;<\/p>\n<p>To pick up the date from the file names as they cross the pipeline, I use the <b>Foreach-Object<\/b> cmdlet and a version of the command I derived earlier in this blog. The command is shown here.<\/p>\n<p style=\"padding-left: 30px\">Get-ChildItem -Recurse -Path C:\\data\\ScriptingGuys -Include HSG*.doc*,WES*.doc* &nbsp;|<\/p>\n<p style=\"padding-left: 30px\">foreach-object {[datetime]$_.basename.substring(4)}<\/p>\n<h2>Adding in the function and changing all the time stamps<\/h2>\n<p>I decided to make a few changes to the <b>Set-FileTimeStamps<\/b> function from the previous blog posting. There are two reasons. The first is that I want to pass a <b>System.Io.FileInfo<\/b> object to the function instead of a path. Secondly, the <b>Path<\/b><i> <\/i>parameter in the original function uses a string, and passing a <b>FileInfo<\/b> object to the function automatically casts the object to a string. When this happens, the <b>$doc<\/b> variable no longer contains a <b>FileInfo<\/b> object, but rather it contains a string. This generates an error stating that the object does not contain a property named <b>CreationTime<\/b> or any of the other properties. The modified <b>Set-FIleTimeStamps<\/b> function is shown here.<\/p>\n<p style=\"padding-left: 30px\"><strong>Function Set-FileTimeStamps<\/strong><\/p>\n<p style=\"padding-left: 30px\">{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;Param (<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; [Parameter(mandatory=$true)]<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; [system.io.fileinfo]$doc,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; [datetime]$date = (Get-Date))<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; ForEach-Object {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $doc.CreationTime = $date<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $doc.LastAccessTime = $date<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; $doc.LastWriteTime = $date }<\/p>\n<p style=\"padding-left: 30px\">} #end function Set-FileTimeStamps<\/p>\n<p>&nbsp;<\/p>\n<p>The script parameters must reside at the top of the script. The parameters section has not changed from any of the other scripts used this week. It is shown here.<\/p>\n<p style=\"padding-left: 30px\">Param(<\/p>\n<p style=\"padding-left: 30px\">&nbsp; $path = &#8220;C:\\fso&#8221;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp; [array]$include = @(&#8220;HSG*.docx&#8221;,&#8221;WES*.docx&#8221;))<\/p>\n<p>The entry point to the script, accepts the command line parameters, and uses <b>Get-ChildItem<\/b> to find all of the files. It then walks through the collection of <b>FileInfo<\/b> objects, creates the time stamp from the file name, and calls the <b>Set-FileTimeStamps<\/b> function. This is shown here.<\/p>\n<p style=\"padding-left: 30px\">## entry point to script<\/p>\n<p style=\"padding-left: 30px\">$docs = Get-childitem -path $Path -Recurse -Include $include<\/p>\n<p style=\"padding-left: 30px\">Foreach($doc in $docs)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;{<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Try<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $date = [datetime]$doc.BaseName.Substring(4)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set-FileTimeStamps -Doc $doc -date $date<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"padding-left: 30px\">&nbsp; Catch [System.Exception] {&#8220;Error occurred setting date for $doc&#8221;}<\/p>\n<p style=\"padding-left: 30px\">&nbsp;}<\/p>\n<p>When the script runs, it finds all of the appropriate files and makes the requisite changes to the file time stamps. One such file is shown in the image that follows.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4405.wes-8-4-12-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4405.wes-8-4-12-02.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>I uploaded <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Set-file-time-stamps-using-e7044069\" target=\"_blank\">the complete script<\/a> to the Scripting Guys Script Repository.<\/p>\n<p>Well, that is all for today. Join me tomorrow when I have a new PowerTip and I introduce the &ldquo;love-o-matic.&rdquo; It is cool, and is the latest Scripting Guys &ldquo;o-matic&rdquo; tool.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to set the time stamps on Microsoft Word document files. Microsoft Scripting Guy, Ed Wilson, is here. It is Saturday here in Charlotte, and the sunshine continues to make its presence known. It seems that the sun gets up rather early during the summer, [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[38,3,12,61,45],"class_list":["post-8471","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-scripting-guy","tag-storage","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to set the time stamps on Microsoft Word document files. Microsoft Scripting Guy, Ed Wilson, is here. It is Saturday here in Charlotte, and the sunshine continues to make its presence known. It seems that the sun gets up rather early during the summer, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/8471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=8471"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/8471\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=8471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=8471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=8471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}