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):
With the package extracted, we proceed replicate the spreadsheet as shown in the post:
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
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
**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:
- BouncyCastle.Crypto.dll
- itextsharp.dll
- PasswordProtectPDF.ps1 (this is the script provided by the author above)
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"
Proceeding to run the PowerShell script will now complete successfully:
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:
The PDFs with the a password configured should now be present in the destination folder:
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:
thank you. right on point.
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!
Good solution, many thanks.
It was helpful...was struggling with the same issue
Thank you!!!! you saved my life! good work!
Thans for help.
Post a Comment