2014-05-22 3 views
1

나는 WIM이 진행 적용 추적 할 수있는 스크립트를 작성하려고 해요 - 지금까지, 나는이 WIMGAPI 래퍼 예제를 활용하여 왔습니다을 :.NET과 Powershell에서 콜백이 다른 결과를 표시하는 이유는 무엇입니까?

Add-Type -Path "Microsoft.Wim.dll" 

# Open a handle to the .wim file 
$wimHandle = [Microsoft.Wim.WimgApi]::CreateFile("G:\sources\boot.wim", ` 
    [Microsoft.Wim.WimFileAccess]::Read,[Microsoft.Wim.WimCreationDisposition]::OpenExisting, ` 
    [Microsoft.Wim.WimCreateFileOptions]::None, [Microsoft.Wim.WimCompressionType]::None) 

# Always set temporary path 
[Microsoft.Wim.WimgApi]::SetTemporaryPath($wimHandle, $env:temp) | Out-Null 

# Build & register a callback method for actions which are performed by WIMGAPI for this .wim file 
$callback = [Microsoft.Wim.WimMessageCallback]{ 
    param (
     [Microsoft.Wim.WimMessageType] $messageType, 
     [System.Object] $message, 
     [System.Object] $userData 
    ) 

    if($messageType -eq [Microsoft.Wim.WimMessageType]::Progress) 
    { 
     $progressMessage = ($message -as [Microsoft.Wim.WimMessageProgress]) 
     Write-Host "Percent Complete: $($progressMessage.PercentComplete)" 
    } 

    return [Microsoft.Wim.WimMessageResult]::Success 
} 

[Microsoft.Wim.WimgApi]::RegisterMessageCallback($wimHandle, $callback) | Out-Null 

try 
{ 
    # Get a handle to the first image in the .wim file 
    $imageHandle = [Microsoft.Wim.WimgAPI]::LoadImage($wimHandle, 1) 
    # Apply the contents to C:\Apply 
    [Microsoft.Wim.WimgApi]::ApplyImage($imageHandle, "C:\Apply", [Microsoft.Wim.WimApplyImageOptions]::None) 
    Read-Host 
} 
catch 
{ 
    Write-Host $_.Exception 
} 
finally 
{ 
    [Microsoft.Wim.WimgApi]::UnregisterMessageCallback($wimHandle, $callback) | Out-Null 
} 

: 나는 파워 쉘로 변환 한 https://managedwimgapi.codeplex.com/wikipage?title=Using%20the%20message%20callback%20functionality%20for%20recieving%20progress%20and%20other%20information&referringTitle=Documentation

코드는 성공적으로 실행하고, WIM이 적용됩니다,하지만 불행히도 나는 단지과 같이 두 번 실행 콜백을보고 있어요 :

는 C# 응용 프로그램을 실행할 때, 나는 0에서 모든 백분율 값을 참조 비록
Percent Complete: 0 
Percent Complete: 100 

100.

사실, ApplyImage가 블로킹 호출이고 콜백을 실행하지 못하도록 차단할 수 있다고 생각합니다. 그러나이 문제를 해결할 방법이 없다고 생각합니다.

모든 의견을 크게 기뻐할 것입니다. 감사!

+0

해결 했습니까? – Dennis

+0

불행히도 나는하지 않았다. 코드는 동일하지만 여전히 일치하지 않는 결과가 나타납니다. Powershell에는 실제로 쓰레딩의 개념이 없다는 사실과 관련이 있다고 생각합니다. – slashp

+1

답장을 보내 주셔서 감사합니다. 그것은 작동하지 않는 것은 불행한 일입니다. WIM 이미지를 적용하는 데 몇 분이 걸리므로이 작업을 수행하는 것이 좋을 것처럼 깊숙이 파고들 것입니다. – Dennis

답변

1

C#으로 CmdLet을 작성했습니다. *.wim 이미지를 위치에 적용한 다음 GitHub으로 푸시하고 Nuget 패키지를 만들었습니다.

https://github.com/dennisroche/Microsoft.Wim.Powershell

나는 처음에 내가 했다 콘솔에 진행 %를 기록하는 빠른 C#을 데모 성공적으로 cmdlet을 쓰기 시작하고 (나는 cmdlet을 쓴 적이없는 cmdlet을 해결책이 될 수 있다는 생각 전에).

CmdLet을 작성하면서 쓰기를 시도 할 때 PowerShell이 ​​InvalidOperationException을 던지고 있다는 것을 알았습니다 (예 : Write-Host, Write-Progress). MSDN에있어서 상대와 I는 다음과 같은 발견

이 방법은 입력 처리 방법의 구현에서 호출 (BeginProcessing, ProcessRecordEndProcessing) 할 수 있고, 해당 스레드에서. 호출이 이러한 구현 외부의 에서 발생하거나 InvalidOperationException 예외가 발생합니다.

이것은 Powershell에서 직접 호출 할 때 작동하지 않는 이유를 설명합니다. 콜백은 다른 스레드에서 발생했으며 Pipeline Execution Thread에서 다시 호출해야했습니다. 어떤 이유로 든 첫 번째 및 마지막 진행 이벤트는 Pipeline Execution Thread에 있었으므로 우리가 한 결과물을 보았습니다.

Pipeline Execution Thread에서 AsyncOperationManager, WindowsFormsSynchronizationContextApplication.DoEvents()을 사용하여 업데이트 진행률 메시지를 호출하는 흥미로운 해결책을 찾았습니다. 위의 오류 메시지를 검색 한 답을 찾은 경우 GitHub의 코드를 살펴보십시오.

+1

잘 했어 데니스! 이 하나 주셔서 감사합니다, 그것은 정말로 나를 곤란하게 만들었습니다! – slashp

+0

감사합니다. @slashp. 유용하다고 생각하길 바랍니다. 관심이 있으시면이 솔루션을 다른 프로젝트의 일부로 사용하고 있습니다. https://github.com/dennisroche/Repave – Dennis

+0

CmdLet을 사용해보십시오. 문제가 있는지 알려주세요. 관심이 있다면 더 많은 용도를 위해 확장하라는 요청을 엽니 다 (예 : 정보를 추출하거나, 특정 이미지 이름을 적용합니다. (완료되었습니다.) – Dennis

관련 문제