0

I have a powershell script that I schedule to check the previous ten days's dated "transaction" files and sorts by LastWriteTime because the year-to-date data is always growing. There are no changes over the weekend, and if there are none during the week I know the process on the server didn't run.

The resulting table has columns "Name", "Size (KB)" (converted "Length" from bytes to KB), and LastWriteTime. I'd like to add an "MD5" column. I have an md5sum.exe command on my computer. I'd like to construct the hash table such that it calls the external command within the expression field using the $_.FullName property.

I found how to calculate the MD5 checksum using PS natively from this post and I've integrated it as a one-liner into the expression value for the new column. I'd still like to know if it's possible to call an external command inside a hash table though.

Here's the original code:

$LOOKBACKXDAYS=( Get-Date ).AddDays(-10)
$SrcMachine='TheServerInQuestion'

if( -not ( Test-Path -Path \\$SrcMachine\C$ ) ) { net use \\$SrcMachine\C$ /user:mydomain\administrator }

Get-ChildItem -Path \\$SrcMachine\C$\temp transactions*.tab | `
    Where-Object {$_.LastWriteTime -ge $LOOKBACKXDAYS } | `
        Select-Object `
            -Property `
                Name , `
                @{name='Size (KB)'; expression={[string]([math]::ceiling($_.Length / [math]::pow(2, 10)))}} , `
                LastWriteTime | `
            Sort-Object `
                -Property `
                    'Size (KB)', `
                    LastWriteTime, `
                    Name | `
                Out-Host
Write-Host -ForegroundColor Green "`n`nAll Done!`n`n"
pause

and it produces output that looks like this:

Name                          Size (KB) LastWriteTime
----                          --------- -------------
transactions for 12172018.tab 13783     2018-12-17 12:05:04
transactions for 12182018.tab 13824     2018-12-18 12:05:06
transactions for 12192018.tab 13869     2018-12-19 12:05:16
transactions for 12202018.tab 13901     2018-12-20 12:05:14
transactions for 12212018.tab 13901     2018-12-21 12:05:12
transactions for 12222018.tab 13931     2018-12-22 12:05:16
transactions for 12232018.tab 13931     2018-12-23 12:05:12
transactions for 12242018.tab 13954     2018-12-24 12:05:14
transactions for 12252018.tab 13954     2018-12-25 12:05:16
transactions for 12262018.tab 14001     2018-12-26 12:05:26

This is the modified code that produces lower case, hyphen removed MD5 checksums, and I added a column that shows a 'Y' if the day of the week is a weekend so I can ignore an identical file. I changed some other stuff too.

$LOOKBACKXDAYS=( Get-Date ).AddDays(-10)
$SrcMachine='TheServerInQuestion'

if( -not ( Test-Path -Path TabFiles:\temp ) ) {
    New-PSDrive `
        -PSProvider FileSystem `
        -Name TabFiles `
        -Root \\TheServerInQuestion\C$ `
        -Credential mydomain\administrator
}

Get-ChildItem -Path TabFiles:\temp transactions*.tab | `
    Where-Object {$_.LastWriteTime -ge $LOOKBACKXDAYS } | `
        Select-Object `
            -Property `
                Name , `
                @{name='Size (KB)'; expression={[string]([math]::ceiling($_.Length / [math]::pow(2, 10)))}} , `
                @{name='MD5'; expression={ [System.BitConverter]::ToString($(New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash([System.IO.File]::ReadAllBytes($_.FullName))).replace('-','').ToLower() }}, `
                @{name='Is Weekend'; expression={ $( if ($_.LastWriteTime.dayofweek -match 'Saturday|Sunday'){return 'Y'} else{return ''} ) } }, `
                LastWriteTime | `
            Sort-Object `
                -Property `
                    'Size (KB)', `
                    LastWriteTime, `
                    Name | `
                Format-Table
Write-Host -ForegroundColor Green "`n`nAll Done!`n`n"
pause

This is the output for the script above:

Name                          Size (KB) MD5                              Is Weekend LastWriteTime
----                          --------- ---                              ---------- -------------
transactions for 12172018.tab 13783     e825b1a58954203da9f8a16c454d9441            2018-12-17 12:05:04
transactions for 12182018.tab 13824     4de56734ceacd02db11bdd8a3dcdc628            2018-12-18 12:05:06
transactions for 12192018.tab 13869     1e4401afd2734004da372bfcf1e90395            2018-12-19 12:05:16
transactions for 12202018.tab 13901     49b1c5e29ea4da7e8a7a72bf610cecd6            2018-12-20 12:05:14
transactions for 12212018.tab 13901     49b1c5e29ea4da7e8a7a72bf610cecd6            2018-12-21 12:05:12
transactions for 12222018.tab 13931     36e40a546c6049e550b0feac9aa7adc7 Y          2018-12-22 12:05:16
transactions for 12232018.tab 13931     36e40a546c6049e550b0feac9aa7adc7 Y          2018-12-23 12:05:12
transactions for 12242018.tab 13954     9c97ccf81ce4cbb583fff348a739cc66            2018-12-24 12:05:14
transactions for 12252018.tab 13954     9c97ccf81ce4cbb583fff348a739cc66            2018-12-25 12:05:16
transactions for 12262018.tab 14001     ad18d544c8dea1d3d9cf1512c4a772e4            2018-12-26 12:05:26

There's ignorable duplicate data over the weekend and from Christmas Eve to Christmas, but there was inexcusable duplicate data from the 20th and 21st.

user208145
  • 369
  • 4
  • 13
  • 2
    I am not exactly sure of what is the question exactly so forgive me if I miss the point. You can call to an external command if you want in the calculated properties expression field. The expression field is a scriptblock, so you can do what you want, including calling an external utility. – Sage Pourpre Dec 27 '18 at 05:56
  • I kinda buried it toward the beginning. I found how to calculate a file's MD5 checksum in PS natively, but say I didn't. "I'd still like to know if it's possible to call an external command inside a hash table though." I tried several different ways of calling the md5sum.exe, including `expression={ & c:\windows\md5sum.exe $_.FullName }`, `expression={ & ( c:\windows\md5sum.exe $_.FullName ) }`, `expression={ & $( c:\windows\md5sum.exe $_.FullName ) }`, etc. – user208145 Dec 27 '18 at 06:57
  • Not sure why it doesn't work for you. I've tried this `$h=@{name='aa'; expression=md5sum.exe .\file}` And it worked perfectly – montonero Dec 27 '18 at 08:56
  • Provided **your** md5sum version outputs the md5 sum and the file name delimited with space(s) use `@{Name='MD5';Expression={(md5sum.exe $_.Fullname).split(' ')[0]}}` –  Dec 27 '18 at 09:32
  • 1
    From PSv4+ you can also use `@{Name='MD5';Expression={(Get-FileHash -Algorithm md5 $_.FullName).Hash}}` –  Dec 27 '18 at 09:39
  • I've been upgrading to PS5.1 wherever possible in my domain, so `Get-FileHash` will come in useful. Thanks. – user208145 Dec 27 '18 at 20:01

1 Answers1

1

To answer your question, it is possible to call executable from the calculated property expression field as this correspond to a standard scriptblock.

The following should work

$md5exepath = "C:\Program Files\Git\usr\bin\md5sum.exe"
#Make sure you have a few png on your desktop or change the get-childitem so it matches something.
$Items = get-childitem -Path "$($Env:USERPROFILE)\desktop" -Filter '*.png' | Select -First 5

$Items | Select Name,
        @{n='md5';e={(& $md5exepath $_.FullName).split(' ')[0]}},
        @{n='test';e={(& 'cmd' "/c echo test")}}   

Assuming you can see the test" from the echo command, then it confirms the external call works for you too.

Regarding md5sum.exe, validate the following.

  • Make sure to use the correct path to your md5sum.exe.
  • Try running from the windows command line : "c:\windows\md5sum.exe" "C:\windows\system32\notepad.exe" and make sure it produces the desired output and do not throw any error.
  • Try running the script as an administrator

I copied md5sum.exe to the Windows folder and had empty results too. As I found out, since Powershell did not produce any errors, while I copied the tool, I did not copy its dependencies and it was failing for that reason.

Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39