Pages

Tuesday, February 16, 2021

Attempting to use itextsharp.dll throws the error: "Could not load file or assembly 'BouncyCastle.Crypto, Version=1.8.6.0, Culture=neutral, PublicKeyToken=0e99375e54769942'..."

Problem

Those who are looking for a PowerShell script to batch password protect PDF documents will quickly come across the following post as returned by Google:

Password Protect PDF document using windows Powershell script
https://efcomputer.net.au/blog/password-protect-pdf-document/

The author provides the following PowerShell script that uses the itextsharp.dll:

[System.Reflection.Assembly]::LoadFrom("itextsharp.dll")

function PSUsing {

param (

[System.IDisposable] $inputObject = $(throw "The parameter -inputObject is required."),

[ScriptBlock] $scriptBlock = $(throw "The parameter -scriptBlock is required.")

)

Try {

&$scriptBlock

}

Finally {

if ($inputObject.psbase -eq $null) {

$inputObject.Dispose()

} else {

$inputObject.psbase.Dispose()

}

}

}

$xlCellTypeLastCell = 11

$startRow,$col=2,1

$excel=new-object -com excel.application

$wb=$excel.workbooks.open("c:\temp\PDFList.xlsx")

for ($i=1; $i -le $wb.sheets.count; $i++)

{

$j=0;

$sh=$wb.Sheets.Item($i)

$endRow=$sh.UsedRange.SpecialCells($xlCellTypeLastCell).Row

$rangeAddress=$sh.Cells.Item($startRow+1,$col).Address() + ":" +$sh.Cells.Item($endRow+1,$col).Address()

$sh.Range($rangeAddress).Value2 | foreach {

$contract=$sh.Cells.Item($startRow + $j,$col).Value2

$filesource = $sh.Cells.Item($startRow + $j,$col+1).Value2

$filedest = $sh.Cells.Item($startRow + $j,$col+2).Value2

$dob=$sh.Cells.Item($startRow + $j,$col+3).Value2

New-Object PSObject -Property @{Contract=$contract;Dob=$dob}

$file = New-Object System.IO.FileInfo $filesource

$fileWithPassword = New-Object System.IO.FileInfo $filedest

$password = $dob

PSUsing ( $fileStreamIn = $file.OpenRead() ) {

PSUsing ( $fileStreamOut = New-Object System.IO.FileStream($fileWithPassword.FullName,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write,[System.IO.FileShare]::None) ) {

PSUsing ( $reader = New-Object iTextSharp.text.pdf.PdfReader $fileStreamIn ) {

[iTextSharp.text.pdf.PdfEncryptor]::Encrypt($reader, $fileStreamOut, $true, $password, $password, [iTextSharp.text.pdf.PdfWriter]::ALLOW_PRINTING)

}

}

}

$j++

}

}

$excel.Workbooks.Close()

At the time of this writing in Feb 2021, clicking on the link provided by the author brings us https://sourceforge.net/projects/itextsharp/files/ which no longer provides a download to the file.

Googling the for “itextsharp” returns a link to iTextSharp 5.5.13.2 located here https://www.nuget.org/packages/iTextSharp/ with the description that version 7 has replaced it but still available to be downloaded (along with security patches in the future):

image

With the package extracted, we proceed replicate the spreadsheet as shown in the post:

image

Then while placing the itextsharp.dll file into the same directory as the PowerShell script, we execute it but receive the following error:

New-Object : Could not load file or assembly 'BouncyCastle.Crypto, Version=1.8.6.0, Culture=neutral, PublicKeyToken=0e99375e54769942' or one of its

dependencies. The system cannot find the file specified.

At C:\itextsharp.5.5.13.2\lib\PasswordProtectPDF.ps1:46 char:22

+ ... ( $reader = New-Object iTextSharp.text.pdf.PdfReader $fileStreamIn ) ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : NotSpecified: (:) [New-Object], FileNotFoundException

+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.NewObjectCommand

image

Solution

The reason why the error above is presented is because the BouncyCastle.Crypto assembly is also needed for the PowerShell script. In addition to downloading:

iTextSharp 5.5.13.2
https://www.nuget.org/packages/iTextSharp/

We should also download the following BouncyCastle:

BouncyCastle 1.8.6.1
https://www.nuget.org/packages/BouncyCastle/1.8.6.1

image

**Note that the latest version 1.8.9 at the time of this writing does not work.

With the two packages downloaded, rename the extension .nupkg to .zip and unpack them into folders.

Place the following files into same directory:

  1. BouncyCastle.Crypto.dll
  2. itextsharp.dll
  3. PasswordProtectPDF.ps1 (this is the script provided by the author above)
image

Before executing the PowerShell script, make sure the following line is added to the beginning so that the BouncyCastle.Crypto.dll is loaded:

Add-Type -Path "C:\itextsharp.5.5.13.2\lib\BouncyCastle.Crypto.dll"

image

Proceeding to run the PowerShell script will now complete successfully:

image

If you prefer not to work in the ISE environment then the line can either be added directly into the PS1, or run the Add-Type -Path "C:\itextsharp.5.5.13.2\lib\BouncyCastle.Crypto.dll" separately:

image

The PDFs with the a password configured should now be present in the destination folder:

image

I found that the script the author provided didn’t really match the formatting I wanted for the PowerShell output and spreadsheet (my use case had nothing to do with contract numbers and date of birth) so I’ll be making modifications to it and writing another blog post for it.

6 comments:

Anonymous said...

thank you. right on point.

Anonymous said...

Thank you for documenting this challenge. My issue was slightly different but your documentation helped me find a solution. In my case the he version of bouncycastle.crypto. was to new. I changed it to 1.8.6.1 and everything I wrote is working.
Thanks again!

Eric said...

Good solution, many thanks.

Sabyasachi said...

It was helpful...was struggling with the same issue

Anonymous said...

Thank you!!!! you saved my life! good work!

kazi said...

Thans for help.