patternshellMinor
Remove known Excel passwords with PowerShell
Viewed 0 times
excelwithpowershellpasswordsremoveknown
Problem
I have this PowerShell code that loops through Excel files in a specified directory; references a list of known passwords to find the correct one; and then opens, decrypts, and saves that file to a new directory. This currently processes ~40 workbooks in roughly 5 minutes, which is still longer than I'd like (but better than the initial 40 minute runtime).
Note that I previously posted under the same title here, but now I am looking for a review after solving a rather obvious error.
``
write-host "
# Excel xlsx
if ($file.Extension -like ".xls") {
# Loop through password cache
$arrPasswords | % {
$passwd = $_
# Attempt to open file
$Workbook = $ExcelObj.Workbooks.Open($file.fullname,1,$false,5,$passwd)
$Workbook.Activate()
# if password is correct save decrypted file to $decrypted_Path
if ($Workbook.Worksheets.count -ne 0 )
{
$Workbook.Password=$
Note that I previously posted under the same title here, but now I am looking for a review after solving a rather obvious error.
``
# Get Current EXCEL Process ID's so they are not affected but the scripts cleanup
# SilentlyContinue in case there are no active Excels
$currentExcelProcessIDs = (Get-Process excel -ErrorAction SilentlyContinue).Id
$a = Get-Date
$ErrorActionPreference = "SilentlyContinue"
CLS
# Paths
$encrypted_path = "C:\PoShTest\Encrypted"
$decrypted_Path = "C:\PoShTest\Decrypted\"
$processed_Path = "C:\PoShTest\Processed\"
$password_Path = "C:\PoShTest\Passwords\Passwords.txt"
# Load Password Cache
$arrPasswords = Get-Content -Path $password_Path
# Load File List
$arrFiles = Get-ChildItem $encrypted_path
# Create counter to display progress
[int] $count = ($arrfiles.count -1)
# New Excel Object
$ExcelObj = $null
$ExcelObj = New-Object -ComObject Excel.Application
$ExcelObj.Visible = $false
# Loop through each file
$arrFiles| % {
$file = get-item -path $_.fullname
# Display current file
write-host "n Processing" $file.name -f "DarkYellow"write-host "
n Items remaining: " $count n# Excel xlsx
if ($file.Extension -like ".xls") {
# Loop through password cache
$arrPasswords | % {
$passwd = $_
# Attempt to open file
$Workbook = $ExcelObj.Workbooks.Open($file.fullname,1,$false,5,$passwd)
$Workbook.Activate()
# if password is correct save decrypted file to $decrypted_Path
if ($Workbook.Worksheets.count -ne 0 )
{
$Workbook.Password=$
Solution
Once you've found the right password and moved the file, then there is no need to try the rest of the passwords on it. You can break out of the loop with a
(You have to change the pipeline
That may or may not speed things up.
Otherwise, I haven't tried them but I understand that there are .NET Excel libraries that you can use to manipulate Excel files without having to use Excel itself. COM automation is pretty slow, so using one of these libraries might be faster.
break command.(You have to change the pipeline
% into a foreach ( in ) because otherwise the break would break out of the outer pipeline too. Thanks to Lieven in the comments for that.)foreach ($passwd in $arrPasswords)
{
# ...
# if password is correct save decrypted file to $decrypted_Path
if ($Workbook.Worksheets.count -ne 0 )
{
# ...
break;
}
# ...
}That may or may not speed things up.
Otherwise, I haven't tried them but I understand that there are .NET Excel libraries that you can use to manipulate Excel files without having to use Excel itself. COM automation is pretty slow, so using one of these libraries might be faster.
Code Snippets
foreach ($passwd in $arrPasswords)
{
# ...
# if password is correct save decrypted file to $decrypted_Path
if ($Workbook.Worksheets.count -ne 0 )
{
# ...
break;
}
# ...
}Context
StackExchange Code Review Q#158259, answer score: 8
Revisions (0)
No revisions yet.