2017-12-15 29 views
0

Powershell 내에서 Shell-Application 네임 스페이스의 CopyHere 메서드는 비동기입니다. 나의 주요 목표는 KML 파일을 KMZ 파일로 변환하는 것입니다. 이렇게하는 과정은 같은 이름의 ZIP 파일을 만들고 KML을 KMZ로 복사 한 다음 (파일을 압축 한 다음) ZIP의 이름을 KMZ로 변경하는 것입니다. 안타깝게도 비동기식이면 CopyHere 메서드가 완료되기 전에 이름 바꾸기 함수가 호출됩니다. 나는 이것을 해결하는 많은 예를 발견했다. 내가 발견 한 가장 깨끗한 사람은 다음과 같습니다 :Powershell ZIP 복사 비동기 동작을 반하는

$kmlPath = $global:directoryPath + "Test.kml" 
$zip = $global:directoryPath + "Test.zip" 
New-Item $zip -ItemType file 
$shellApplication = new-object -com shell.application 
$zipPackage = $shellApplication.NameSpace($zip) 
$zipPackage.CopyHere($kmlPath, 16) 

while($zipPackage.Items().Item($zip.Name) -Eq $null) 
{ 
    start-sleep -seconds 1 
    write-host "." -nonewline 
} 
write-host "." 
Rename-Item -Path $zip -NewName $([System.IO.Path]::ChangeExtension($zip, ".kmz")) 

이 다음과 같은 오류로 응답

Exception calling "Item" with "1" argument(s): "Not implemented (Exception from HRESULT: 0x80004001 (E_NOTIMPL))" + while($zipPackage.Items().Item($zip.Name) -Eq $null) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ComMethodTargetInvocation

내가이 특정 패키지에 대한 항목 방법을 오용하고 있습니까? 내가 깔끔하게 끝내기 위해 "나타나는"것이 작동하지 않는 이유를 혼란스럽게 생각합니다. 나는 또한 Here 코드의 스 니펫을 시도했다. 또한이 특정 상황에서 .Item 메서드에 대해 불평합니다.

답변

1

내가 겪었던 문제는 우편 번호 상태를 확인하기 위해 찾아 내려고하는 것이 었습니다.

대신에 나는 방아쇠를 당겼습니다. 화재가 날 것입니다 ... Zipfile이 열려 있고 File name이 안에 있다면.

function kml_to_kmz([string]$kmlPath){ 
    [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') 
    $kmlInfo = Get-ChildItem -Path $kmlPath 
    $zipLocation = ($kmlInfo.Directory.FullName + '\' + $kmlInfo.Name.Remove($kmlInfo.Name.LastIndexOf('.')) + '.zip') 
    New-item $zipLocation 
    ((new-object -com shell.application).NameSpace($zipLocation)).CopyHere($kmlPath, 16) 
    $trigger = $false 
    while ($trigger -eq $false){ 
     try{ 
      $zip = [IO.Compression.ZipFile]::OpenRead($zipLocation) 
      If(($zip.Entries | %{$_.Name}) -contains $kmlInfo.Name){ 
       $zip.Dispose(); 
       $trigger = $true 
       break; 
      } 

     }catch{} 
     start-sleep -seconds 1 
     write-host "." -nonewline 
    } 
    [IO.Compression.ZipFile]::OpenRead($zipLocation).Dispose() 
    Rename-Item -Path $zipLocation -NewName $([System.IO.Path]::ChangeExtension($zipLocation, '.kmz')) 
} 

kml_to_kmz -kmlPath "C:\Users\Default\Desktop\Test.kml" 
+0

이것은 실제로 완벽하게 작동했습니다. 새 아이템 인스턴스화에 "-ItemType file"을 추가해야했지만, 빠른 픽스였습니다 (그렇지 않으면 타입을 입력하라는 메시지가 나타납니다). 나는 ISE의 ​​출력이 이제 일련의 글로벌 구성 (CodeBase, FullName, EntryPoint, DefinedTypes 및 기타 40 개)을 뱉어 내고 있음을 확인했습니다. 나는 코드의 어떤 부분이 그 출력을 모두 뱉어 내지는 모르겠다. 그러나 그것은 확실히 혼란 스럽다. 어떤 아이디어? –

+0

'[Reflection.Assembly] :: LoadWithPartialName ('System.IO.Compression.FileSystem ')'줄은 어셈블리 매개 변수 출력을 콘솔에 덤프합니다. 나는 '| Out-Null '을 사용하여 출력을 마스크합니다. 모든 것이 완벽하게 작동합니다. –

+0

다행 당신을 위해 일하고 :) – ArcSet