2016-04-11 33 views
2

多くのExcelドキュメントを変換しパスワードで保護するために使用しているスクリプトがあります。古い文書はExcel 2003形式であり、変換/パスワードによる保護が可能です。より最近の文書を見ると、ファイルはExcel 2010形式であるため、パスワードで保護する必要があります。私はxlsxファイルが既にパスワードで保護されているかどうかをチェックする方法を見つけようとしているので、スキップすることができます(すでに処理されている2003ファイルになる可能性があります)。パスワードがあるファイルを開くと、visibleプロパティがfalseに設定されているにもかかわらず、excelがポップアップしてそのパスワードを要求してから続行します。チェックを自動化する方法が必要です。これは、多くの文書が通過するためです。これは私が今まで持っているコードです:Excelパスワード保護のPowershellテスト

[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() 
} 
+0

それは停止し、パスワードを要求 '$ Excel.workbooks.open'呼び出しですか? –

+0

@JoachimIsaksson:はい、ここが止まります。 – Caynadian

+0

ここでアイデアを捨ててください。ダミーのパスワードを 'open'に渡すとどうなりますか?それでもプロンプトが出るか、例外がスローされますか? –

答えて

1

私の謝罪。私がやったことは、ファイルをデータストリームとして開き、ファイルの署名(ファイルの最初の4バイト)をチェックすることです。標準2010 Officeドキュメント(.xlsx、.docxなど)は、実際にはZipファイルであり、標準のzipファイル署名を持っています。このPowerShellのコードは私にそのSIGとバイト配列を与える:一方

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

暗号化されたOfficeドキュメントが最後の5つのバージョンなどのために、すべてのOfficeドキュメントに共通の標準ファイルの署名を持っています。それは暗号化されていないのであれば、このコードスニペットは、私がチェックし、テストするために、各文書からのsigを読む方法を示しています(上記のSIGを持っている):

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

majkinetorの答えは、上記かかわらず、同様に動作します。

+0

非常にいいです。これを共有してくれてありがとう。 – majkinetor

+0

TBH、私の解決策では、実際にパスワードを入力してから実行することもできます:) – majkinetor

1

ジョブ内で変換を実行する別のスクリプトを使うことができます。 Excelがプロンプトを表示すると、プロンプトが消えるまで変換スクリプトがブロックされます。あなたは(10秒のような)しばらくの間仕事を待つことができ、それが戻ってこない場合はそれを殺すことができます。

並列で複数のジョブを同時に開始すると(Excelでこれが可能であると仮定して)、スクリプトは常に他のジョブを待っているファイルの一部を変換します。


シリアルソリューションでは、Excelプロンプトを待つ自動ホットキースクリプトも使用できます。プロンプトが表示されたら、powershellスクリプトに制御を戻すExcelを終了させることができます(このようなエラーを無視することができます)。スクリプトは、Excelが示すことを待ち、それを殺しに進み、永遠にループ内

:説明

ExcelMonitor.ahk

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

:AHKスクリプトは、次のようなわずか数行を持っているでしょう別のプロンプトを待つ。これは、あなたの大胆なスクリプトにコントロールを返します。

このahkスクリプトをpowershellスクリプトの前に実行し、変換が完了したら閉じます。また、変換する前にahkスクリプトを開始し、後でそれを閉じるためにあなたのPowerShellスクリプトを配置することもできます。 [1]

:私が来て、これを更新するのを忘れhttps://autohotkey.com/docs/commands/SetTitleMatchMode.htm#Parameters

+0

アイデアありがとう。これに伴う問題は、何千ものスプレッドシートがあり、それを並列実行しても、各ファイルのタイムアウトを待たなければならない場合、永遠にかかることです。また、スクリプトからパスワード保護されたドキュメントを開くと、Excelウィンドウが開き、表示可能なオプションがfalseの場合でもパスワードの入力が求められます。したがって、私は絶えずポップアップ画面の束を得るだろう。私はVMを使うことができると思っていますが、理想的ではありません。私は悪いパスワードの例外をキャッチすることはおそらくより良いと思う。 – Caynadian

+0

私の編集した記事を参照してください。すぐにプロンプ​​トが表示されるので、それは優秀です。正直なところ、1回の操作でどれくらい時間がかかりますか?あなたはそれを一晩か何か実行することができます。 – majkinetor

0

精度を追加するだけで、提供される回答は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 !" 
    } 
} 
関連する問題