2016-04-07 13 views
1

Von Beispielen im Netz habe ich dieses Skript zusammengeschustert, die ich hoffe, Word .doc Dateien als plainText speichern. Es tut nicht.Probleme mit Powershell und Word SaveAs()

Zuerst wird das Word-Fenster, wenn ich gegeben habe $ word.Visible = $ False.

Dann wird ein Dialogfenster gefragt, ob ich eine schreibgeschützte Kopie öffnen möge. Niemand hat das Dokument geöffnet. Warum fragt es?

Schließlich sagt die Fehlermeldung, dass ich eine Typkonflikt haben. Warum das?

PS H:\d2> .\wl.ps1 
Processing : H:\d2\checklists\Extract checklist_20120306.doc 
Name is now: H:\d2\checklists\Extract checklist_20120306.txt 
Exception calling "SaveAs" with "2" argument(s): "Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))" 
At H:\d2\wl.ps1:19 char:5 
+  $opendoc.SaveAs([ref]$name.Value,[ref]$saveFormat) 
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : COMException 

Hier ist der Quellcode für das Skript.

$srcfiles = Get-ChildItem -Path . -Recurse -Filter "*.doc*" 
$saveFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText 
$word = new-object -comobject word.application 
$word.Visible = $False 

ForEach ($doc in $srcfiles) { 
    Write-Host "Processing :" $doc.fullname 
    $name = Join-Path -Path $doc.DirectoryName -ChildPath $($doc.BaseName + ".txt") 
    Write-Host "Name is now:" $name 

    $opendoc = $word.documents.open($doc.FullName) 
    $opendoc.SaveAs([ref]$name.Value,[ref]$saveFormat) 
    $opendoc.Close() 

    $doc = $null 
} 

$word.quit() 

Antwort

1

Warum ist es schreibgeschützt

Sie Objekt mit dem Microsoft Word COM öffnen zu fragen, sind

COM-Objekte berüchtigt für Probleme verursachen, wenn man sie nicht richtig schließen. In Ihrem Skript wird das Aufrufen von $word.quit den Word.exe-Prozess in den meisten Fällen nicht schließen.

Sie die Fehlermeldung erhalten, dass das Dokument von einem vorherigen Skript ausgeführt werden, da ein Prozess geöffnet ist nicht geschlossen worden. Sie haben möglicherweise auf "Anhalten" geklickt, bevor das Skript auf "$word.quit()" geklickt hat.

Speichern Sie Ihre Arbeit und versuchen Get-Process WINWORD | stop-Process -force Dadurch werden alle offenen Wort Prozesse auf Ihrem Computer töten. Ich wette, es wird danach funktionieren. Aber Sie haben das Problem des Skripts nicht gelöst, das Wort Doc bleibt offen. Versuchen Sie, diese Zugabe zu dem Ende des Skripts:

$word.quit() 
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) 
Remove-Variable word 

Sein, wie ich COM-Objekt Prozesse töten und es hat nie versäumt, einen IE-COM-Objekt Prozess zu stoppen, sollte das gleiche für Word arbeiten.

Warum gibt es einen Typenkonflikt

Sie müssen die Bibliothek in Powershell geladen haben:

[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null 

Sie benötigen .SaveAs zu ändern, um den Dateipfad zu ändern, eher zu System.Object als System.string Es war eine scheinbar vorgenommene Änderung in .net 4,0

$opendoc.SaveAs([ref][system.object]$name,[ref]$saveFormat) 

die eine gefunden Swer auf den Typenkonfliktfehler HERE

+0

Vielen Dank, @Nick. Ich musste 'Get-Process WINWORD' verwenden, um es zu finden. Und ich habe immer noch die "type Mismatch" Nachricht. $ PSVersionTable meldet 4.0. Irgendwelche Ideen? – lit

+0

Ah yep es ist WINWORD, ging aus Speicher wird die Antwort aktualisieren. In deiner Frage hast du '$ name.Value', Können Sie den '.Value' entfernen, so dass die Zeile genau so ist wie in meiner Antwort? Oder hast du das? @Liturgist – Nick

+0

Entschuldigung, ich vermisste das Entfernen von '.value'. Aber, wenn ich es entferne, bekomme ich '[ref] kann nicht auf eine Variable angewendet werden, die nicht existiert. Dann, wenn ich' [ref] 'Ich bekomme' Argument: '1' sollte ein System.Management sein .Automation.PSReferenz. Verwenden Sie [ref] .' – lit

0

Nick Antwort als Antwort markiert ist. Dies ist das resultierende Skript, das in dieser Situation funktioniert hat. Der CWD muss das übergeordnete Verzeichnis aller zu konvertierenden .doc Dateien sein.

[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null 
$srcfiles = Get-ChildItem -Path . -Recurse -Filter "*.doc*" 
$saveFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText 
$word = new-object -comobject word.application 
$word.Visible = $False 

ForEach ($doc in $srcfiles) { 
    Write-Host "Processing :" $doc.fullname 
    $name = Join-Path -Path $doc.DirectoryName -ChildPath $($doc.BaseName + ".txt") 

    Write-Host "Name is now:" $name 

    $word.Visible = $False 

    $opendoc = $word.documents.open($doc.FullName) 
    $opendoc.SaveAs([ref][system.object]$name, [ref]$saveFormat) 
    $opendoc.Close() 

    $doc = $null 
} 

$word.quit() 
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null 
Remove-Variable word 
Verwandte Themen