2

I've tried to write a commandlet for getting meta information from an epub file. I would like to use the commandlet like this:

Get-ChildItem '*.epub' | Get-EpubMetaInfo | %{ Rename-Item $_.File "$($_.Author) - $($_.Title).epub" } 

So Get-EpubMetaInfo should

  1. open the epub file (which is actually a simple a zip archive)
  2. read meta info from it
  3. close the opened stream
  4. passthru the meta infos

Here is the relevant part of the process block:

process
{
  ...
#
# 1. Open ZipArchive to get a DeflateStream reference
#
  $Stream = $ZipEntry.Open() 
  try
  {
#
# 2. Read meta-info
#
    $Reader = [System.Xml.XmlReader]::create($Stream)
    [System.Xml.XmlDocument] $opf = New-Object System.Xml.XmlDocument
    $opf.Load($Reader)
    $title = Get-MetaText $opf.package.metadata.title
    ...
  }
  catch [System.Exception]
  {
    Write-Error "Couldn't read meta-info $ZipEntry.Name from $EpubFile : $_.Message"
  }
#
# 3. Close opened stream
#
  finally
  {
    $Stream.Close()
    $ZipEntry.Archive.Dispose()
    # $ZipEntry doesn't have Close() or Dispose() method :(
  }
  $obj = New-Object –typename PSObject
#
# 4. passthru the infos
#
  $obj | Add-Member –membertype NoteProperty –name File –value ($EpubFile) –passthru |
  ...
}

This works fine if I don't pipe it into the Rename-Item. With Rename-Item I get the following error:

Rename-Item : The process cannot access the file because it is being used by another process.

What should I do, to close the zip properly?

The whole code can be examined here https://github.com/mattia72/powershell

Update:

If I call $Reader.Close() after $Stream.Close() then the first rename is ok, the second fails again, and so on...

It may be an asynchronous reader issue?

4

0 回答 0