Recently I have been playing around with Windows PowerShell. I had this desire to synchronize the date modified field between identical files in two directories. Awhile back I had created a repository with the copied code and during the copy the date modified had been set on all of the files to the current date. Since I am working on “other people’s code†the date the code was last modified is a helpful clue in troubleshooting. Now I wanted the repository to show the correct “old†date and this looked like a good way to write my first PowerShell script. The script objective is pretty simple. For every file in my source directory I wanted to update the date modified field in my target directory with the date modified if the date modified field in the target directory is less than my cut off date. The cut off date is the date I created the repository. So if a file has not been changed since the cut off date I wanted to set it to the original date modified. After a few fumbles I got it to work. Now I can change the date modified back to the original value for the unchanged files in the directory.
Then I started thinking about comparing directories and MD5 hash files. I knew my source and target directories were good matches since WinMerge told me but I was curious whether PowerShell natively supported MD5 hashes. After a little searching I found this Bart’s post about creating a file hasher cmdlet. This was interesting and looked like a very short task so I tried to create my first cmdlet. The instructions were simple but I fumbled over a lot of minor issues.
- You need to set the execution policy. I set my code signing to RemoteSigned.
- You need to compile the cmdlet.
- You need to create/modify your profile.ps1 so you can use it every time you get into PowerShell.
The hardest one of these tasks was the second task. Trying to find the System.Management.Automation.dll took me on a wild goose chase. I knew it was probably on my machine but I could not find it. When I gave up looking for it and tried to download the Windows SDK 2008, the download barfed on me. Finally I found Raj’s post about viewing the GAC. This confirmed that the System.Management.Automation.dll was in the GAC on my machine. To make things very simple I copied the file to my PowerShell default directory and compiled the cmdlet. Later I found this recommendation by Oisin Grehan in a Vista forum in which he says since it is in the GAC, the compiler will find it without any fancy path statements.
csc.exe cmdlet.cs … /r:System.Management.Automation.dll
Re: System.Management.Automation.dll missing? – Vista Forums
I tried it and it did not work. I was able to compile using a reference to the actual GAC location. So if we combine this all together we get something like this. You execute these statements inside PowerShell.
$ref = "$env:windir\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" $compiler = "$env:windir/Microsoft.NET/Framework/v2.0.50727/csc" &$compiler /target:library /r:$ref hashcmdlet.cs
I had to install the plugin outside of PowerShell with:
%windir%\Microsoft.NET\Framework\v2.0.50727\installutil -i hashcmdlet.dll
Finally I had to create a profile.ps1 in the PowerShell directory to load the snap-in and extend type system every time you get into PowerShell. This post was a great help. This is so Unix it makes me chuckle! I have not figured out what I am going to do with this new found knowledge but I learned a lot about creating custom cmdlets and it was fun!