Excel密码保护的PowerShelltesting

我有一个脚本,我正在使用转换和密码保护一些Excel文件。 旧的文件是在Excel 2003格式,我可以转换/密码保护他们罚款。 当我得到更新的文件,文件是在Excel 2010格式,因此只需要密码保护。 我试图find一种方法来检查一个xlsx文件是否已经被密码保护,因此可以跳过(可能是一个已经处理的2003年文件)。 如果我打开文件,因为它有一个密码,然后Excel将popup并要求密码继续之前,即使我有可见的属性设置为false。 我需要一种自动化检查的方法,因为有很多文件要通过。 这是迄今为止的代码:

[cmdletbinding()] param ( [parameter(mandatory=$true)][string]$Path, [parameter(mandatory=$false)][switch]$Visible, [parameter(mandatory=$false)][string]$ToFolder, [parameter(mandatory=$false)][string]$Password, [parameter(mandatory=$false)][switch]$Force ) begin { Add-Type -AssemblyName Microsoft.Office.Interop.Excel $xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault Write-Verbose 'Opening Excel COM object.' $Excel = New-Object -ComObject excel.application if ($Visible -eq $true) { $Excel.visible = $true } else { $Excel.visible = $false $Excel.DisplayAlerts = $false $Excel.ScreenUpdating = $false $Excel.UserControl = $false $Excel.Interactive = $false } $filetype = "*xls" } process { if (Test-Path -Path $Path) { Get-ChildItem -Path $Path -Include '*.xls' -recurse | ForEach-Object { Write-Verbose "Processing $($_.Basename)" if ($ToFolder -ne '') { $FilePath = Join-Path $ToFolder $_.BaseName $FilePath += ".xlsx" } else { $FilePath = ($_.fullname).substring(0, ($_.FullName).lastindexOf(".")) $FilePath += ".xlsx" } if (!(Test-Path $FilePath) -Or $Force) { Write-Verbose "Opening $($_.Basename)" $WorkBook = $Excel.workbooks.open($_.fullname) Write-Verbose "Saving $($_.Basename) to $FilePath with password $Password" $WorkBook.saveas($FilePath, $xlFixedFormat, $Password) Write-Verbose "Closing $($_.Basename)" $WorkBook.close() } else { Write-Verbose "$($_.Basename) already converted." } } } else { return 'No path provided or access has been denied.' } } end { Write-Verbose 'Closing Excel' $Excel.Quit() $Excel = $null [gc]::collect() [gc]::WaitForPendingFinalizers() } 

您可以使用另一个脚本来执行作业中的转换。 如果Excel提示转换脚本将阻塞,直到提示消失。 你可以等待一段时间的工作(如10秒),如果它不返回杀死它。

如果您同时启动多个作业(假设这可以通过Excel进行),那么脚本将始终转换某些文件,而不是等待其他文件。


串行解决scheme也可以使用等待Excel提示的Autohotkey脚本。 当提示显示你可以杀死将返回到powershell脚本的控制(你可以忽略任何错误,这种方式上升),然后可以继续迭代的Excel。 AHK脚本将只有几行,如:

ExcelMonitor.ahk

 SetTitleMatchMode, 2 # see [1] Loop { WinWaitActive, <Set Excel Prompt Window Title Here> Run, taskkill /IM excel.exe /f } 

说明

在永久循环内,脚本等待Excel显示并杀死它,并继续等待另一个提示。 这将把控制权返回到你的豪华版脚本。

在PowerShell脚本之前运行这个ahk脚本,并在转换完成后closures它。 你也可以让你的powershell脚本在转换之前启动ahk脚本,然后closures它。

[1]: https : //autohotkey.com/docs/commands/SetTitleMatchMode.htm#Parameters

我很抱歉,我忘了来更新这个。 对于任何未来看我最终做的是打开文件作为数据stream,并检查文件签名(文件的前4个字节)。 标准的2010 Office文档(.xlsx,.docx等)是真正的Zip文件,并具有标准的zip文件签名。 这Powershell代码给了我一个字符数组与这个sig:

 $sig = [Byte[]] (0x50,0x4b,0x03,0x04) 

另一方面,encryption的Office文档具有与所有Office文档相同的标准文件签名,就像过去的5个版本一样。 所以,这个代码片段展示了如何从每个文档读取sig来检查,然后testing它是否未encryption(具有上面的sig):

 $bytes = get-content $_.fullname -encoding byte -total 4 if (@(compare-object $sig $bytes -sync 0).length -eq 0) { # process unencrypted file } 

majkinetor上面的答案也可以。

只是为了增加精度,提供的答案只适用于2007+文件。 为了实现97-2003文件,你可以试试这个:

 # Look for 97-2003 files If ($excelSheet.Extension.Length -eq 4) { # Get Excel sheet file header $header = Get-Content $excelSheet.FullName -Encoding Unicode -Total 1 # Check if Excel file is password protected If (($header -ne $null) -and ($header -notmatch "Microsoft Enhanced Cryptographic Provider")) { Write-Host = "Excel sheet : $excelSheet is unencrypted." } Else { Write-Host "Excel sheet : $excelSheet is password protected !" } }