Jump to content

Progress bar when applying WIM image file


Recommended Posts

I hope I'm posting this in the right place as I am a general noob who is just asking for advice.

I've searched the forums and researched different sources about using or controlling Imagex.exe with Autoit. One of the drawbacks I and many others have had is getting callback or feedback information from it in order to properly display progress (ie. ProgressBar) in a script. Especially if you are trying to apply an image to a drive because of the multi-threading issue. Sure, we could run Imagex and let the user see the text progress from an unhidden command window, but where's the fun in that?

Below is some code I've been tinkering with that might be a solution:

CODE
$NeededSpace = (428876393)

ProgressOn("Progress Meter", "Increments every second", "0 percent")

$RunImagex = Run("imagex.exe /Apply c:\temp\winpe.wim 1 c:\temp2", "c:\temp")

While 1

Sleep (1000)

$CurDirSize = DirGetSize("c:\temp2")

$Size = (($CurDirSize/$NeededSpace)*100)

$Perc = (Round ($Size, 0))

ProgressSet ($Perc, $Perc & " percent")

If $CurDirSize >= $NeededSpace Then

ExitLoop

EndIf

If ProcessExists ("Imagex.exe") = 0 Then ExitLoop

WEnd

ProgressOff()

msgbox(0,"", "Return code: " & $RunImagex & @CRLF & "Current Folder Size: " & $CurDirSize & @CRLF & "Size That Was Needed: " & $NeededSpace)

Please excuse my sloppy code as this is just for demonstration purposes.

I have two folders on the root of C: named TEMP and TEMP2 (yeah, I know, real imaginative). This script resides in TEMP along with the WIM file I'll be using and TEMP2 is empty. Also, Imagex.exe is in my path and Wimfltr.sys is applied as I am running XP. (Not that I need it for this demonstration). The WIM file is simply a PE 2.0 image that I extracted from the MS WAIK for testing purposes. As it stands now this script works very effectively and gives me a nice clean progress bar. My only drawback is $NeededSpace is a given in the beginning. This does not trouble me too much because if you run Imagex against your WIM file with the /INFO switch you can glean through the XML output the TotalBytes that the uncompressed image will require.

In this example I am polling DirGetSize every second to compare the current folder size of TEMP2 against $NeededSpace. More or less when they are equal then my progress bar should read 100%. If you were applying the image to a drive letter you could use DriveSpaceFree and DriveSpaceTotal to get the same results I would imagine (more testing to come). In case the operation errors out or Imagex blows up I use ProcessExists to see if Imagex.exe is still running and if it isn't then I exit the loop.

So, basically I have two questions for you fine folk:

1. Has anyone else already tried this approach? If so, would you be so kind as to point me in the right direction where I might find examples?

2. Does anyone know the exit or return codes from Imagex.exe? You'll notice if you try the above script that you'll get differing results for $RunImagex each time you successfully run it. Knowing what Imagex returns would be a great help in knowing if the apply operation was successful or not.

Of course, the only drawback to this method is that your target folder or drive must be empty when you start. What I want to use this for is a template script that I can burn on a PE 2.0 DVD with any WIM file I choose and be able to get the same clean results. One use for this would be, if you were a system builder, you could create a clean image of an install, place it on a DVD with this script and give the user an instant recovery disk.

At any rate, any help I could get would be appreciated. Thanks.

Edit: Disregard the return code from $RunImagex. I am such a noob that I assumed since RunWait returns exit codes that Run does as well. Doh! RTFM!

Edited by Catdaddy
Link to comment
Share on other sites

Also there is a DLL... WIMGAPI.dll if you want to research the API and learn how to use a callback to get progress info.

Lar.

From my unsuccessfull attempts using wimgapi.dll I can only say it's not possible (or I didnt dig in far enough) to read the progress while applying. I get the callbacks while capturing, but for some reason the whole thing gets blocked when I apply the image. As soon as the image is completely applied I get the whole callbacks in one bunch. (not very useful I guess)

All I could gather from the MSDN forums was that it has something to do with MS enabling multithreading in the "apply" function. So the callbacks never reach my AutoIt instance. (given I understood it right)

Edit: I guess I should have read the OP to the end. The problem with the callbacks and multithreading was already mentioned there.

Edited by Björn Kaiser

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

Thanks, Larry and Bjorn Kaiser. I followed the link above but I'm afraid it did not help me. I think what I'm going to try is creating an XML file with the /INFO switch in Imagex and then save it to the X: drive while in PE 2.0 (the RAM drive should be able to hold a small KB file I would imagine). Then I will attempt to use the XMLDom wrapper written by Stephen Podhajecki to get all of the variables I need from the XML output. (I'll freely admit I'm XML illiterate so this will be a learning experience).

Bjorn,

I researched the forums some time ago and found this: http://www.autoitscript.com/forum/index.ph...;hl=wimgapi.dll

but it appears they ran into the same problem. I also prefer Valik's explanation as to why it does not work:

"Quite simply, Microsoft, as is typical, are idiots. They never call fflush() on the stream. The output builds up and is not flushed until the program closes. AutoIt shows you the output the instant it sees it, but during the entire run of the program, the ouput is buffered in imagex. By the way, you can confirm that it's not AutoIt's fault by using the command line and re-directing output to a file when using the /scroll argument. Even doing that will leave an empty file (IIRC, there is some output, but not the progress percentage). Then when the program is done, poof, magically all the data is there. Without using the /scroll argument, data is written directly to the screenbuffer and not to stdout."

For the time being though, I still have Jon's excellent Gimagex found here: http://www.autoitscript.com/gimagex/ to fall back on.

Link to comment
Share on other sites

...

For the time being though, I still have Jon's excellent Gimagex found here: http://www.autoitscript.com/gimagex/ to fall back on.

Did you ever try to integrate that into a script, not using the GUI? IIRC the last time I tried it, which is honestly like 8 weeks ago or so, I got the same problem as with the wimgapi.dll itself when it came to the status callbacks.

I guess the only thing we could do would be complain to MS about that. But how are the chances they care for that or would even want to allow scripting the wimgapi with anything other than VBS?

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

Did you ever try to integrate that into a script, not using the GUI? IIRC the last time I tried it, which is honestly like 8 weeks ago or so, I got the same problem as with the wimgapi.dll itself when it came to the status callbacks.

I guess the only thing we could do would be complain to MS about that. But how are the chances they care for that or would even want to allow scripting the wimgapi with anything other than VBS?

Ironically, I just went to the above site today and noticed an update was posted on July 4 for Gimagex. No, I've never tried implementing Jon's COM object into a script. I'll admit I'm still quite the novice with these things.

You're right. MS probably has bigger fish to fry than worrying about a silly console program like this. Many people have told me to not worry about it and just use the CLI. But you don't know if something can be done until you try, right?

Link to comment
Share on other sites

Ironically, I just went to the above site today and noticed an update was posted on July 4 for Gimagex. No, I've never tried implementing Jon's COM object into a script. I'll admit I'm still quite the novice with these things.

If you want to try, I could give you the last version of my gimagex_com.au3. However, _much_ undocumented code there. Since I'm not really a programmer I tend to do my scripts the "trial and error" way. function comes first. documentation? oh well, maybe later. muttley

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

If you want to try, I could give you the last version of my gimagex_com.au3. However, _much_ undocumented code there. Since I'm not really a programmer I tend to do my scripts the "trial and error" way. function comes first. documentation? oh well, maybe later. muttley

HeeHee, I'm the same way. Sure, I would love to see what you got.

On a side note, I just discovered that 7Zip now handles WIM files as straight archives. I think I might fool around with that for a bit. Wouldn't that be interesting? To do away with the WIM format completely? I remember in the old days (Windows 3.11/95) when I worked in a repair depot for a laptop manufacturer, all of our OS images were pure and simple ZIP files! Of course we had to script FDISK and FORMAT with a BAT file. As long as the archive retained all of the original file and folder attributes, why couldn't RAR or 7ZIP be used to capture and apply an image? Heck, you could even password protect the archive.

Now, having said that, I have never attempted to create a 4GB RAR file. Depending on the compression level chosen, I would imagine the capture time would be anywhere between 45 minutes to 7 hours :)

Link to comment
Share on other sites

HeeHee, I'm the same way. Sure, I would love to see what you got.

On a side note, I just discovered that 7Zip now handles WIM files as straight archives. I think I might fool around with that for a bit. Wouldn't that be interesting? ...

Now, having said that, I have never attempted to create a 4GB RAR file. Depending on the compression level chosen, I would imagine the capture time would be anywhere between 45 minutes to 7 hours muttley

I think one has to try that out. But my guess would be that 7zip loses the ACL and a lot more. (if you unpack a WIM with it.) There is one way to circumvent this though, regardless of the archive type used. I have seen commandline tools on SF.net and I guess you can export existent ACL lists to a text/settings file and import that file with another option onto a directory tree restored from an archive.

But why the hassle (given wimgapi/imagex would work nicely)?

and for the times:

what if we just use this numbers as an orientation:

http://www.codinghorror.com/blog/archives/000799.html

ok, on second thought a VHD isnt just the same as a bunch of small files. Just trying to think it through a bit.

as for the gimagex 'UDF' I'll see what I can do at work tomorrow.

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

  • 3 months later...

ok, digging out old topics.

But after reading the "wimgapi freezes VB6 UI" thread at MSDN again I have come to the idea, to just put wimgapi into its own process. Meaning, I'll write a windows service in AutoIt that is only there to read/write to a named pipe and execute wimgapi functions. So I can send commands to it through the named pipe and the service can write the progress and other status back to the named pipe. On the other side of the pipe I would have my client in AutoIt3 that handles the progress/log window.

I guess that should work. Anyone got better ideas before I start working on this?

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

But after reading the "wimgapi freezes VB6 UI" thread at MSDN again I have come to the idea, to just put wimgapi into its own process.

You can also put wimgapi into a thread and pass events through a hidden window. I do a bit of work on an ActiveX control called SmartWIM (which is free for personal use and $29 for business use) and we've been able to stop GUI blocking through that technique.

I've had good luck using AutoIT and SmartWIM together as well. If you like, I can wrangle up some scripts to illustrate.

Link to comment
Share on other sites

Okay, here's a simple one with SmartWIM using the ProgressOn, ProgressSet, ProgressOff.

http://autoit.pastebin.com/f3ecfe1f4

And another showing how to use it with the full GUI.

http://autoit.pastebin.com/f3242f14f

I highlighted the .Async = 1 option on each of these examples, because that's a setting that's specifically there for AutoIT. People who use VBScript or .NET often are okay with the capture or apply not returning until it's done, so Async isn't turned on by default.

But what it does is spawn a thread with the capture or apply or split (or whatever) running in the background and it'll call the Progress and AsyncCompleted events when it's done. Anyway, you can download a pre-release of SmartWIM 2.0 from here and try the examples for yourself.

I don't know, I hope that helps.

Link to comment
Share on other sites

  • 2 months later...

yeah, old topic. however, seems MS modified imagex.exe and maybe wimgapi.dll with the advent of Windows 7. imagex got some new options (/logfile for one) and it seems the screen buffers are flushed now.

I'll take a look at it as soon as I have some time.

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

  • 3 months later...

ok, it took some time, but I finally got around to test my old code with a new version of WIMGAPI.dll.

Test environment:

Virtualbox 2.2 VM with one guest CPU on Ubuntu 9.04

OS: Windows 7, Build 7100 (RC)

wimgapi.dll version 6.1.7100.0 (Windows 7 WAIK RC)

with that setup I got progress callbacks in both cases, capturing and applying the image.

Just for those still interested in working with wimgapi.dll from autoit.

btw, here is my code:

my wimgapi.wrapper

http://autoit.pastebin.com/f9857fa3

my test script

http://autoit.pastebin.com/f7002099b

Edited by Björn Kaiser

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

  • 5 months later...

Thanks Björn, this code has been very helpful to me :)

I only have one slight problem with it. I am displaying the status on a label.

Somehow the modified text is put *on top* of the old one, after a few seconds of updates you can't really read the seconds.

Instead of the ProgressSet(...) in _Progress, i'm using GuiCtrlSetData($label, "Remaining " & Int($3 / 1000) & " seconds"))

Any suggestions on what could be wrong here?

Thanks!

Edit:

Well kind-of- solved it by deleting the label and re-creating it every time there's a new text. Not really optimal though :)

Edited by Sypher
Link to comment
Share on other sites

  • 1 year later...

Björn Kaiser,

I just tried your test script modifying it slightly for a different WIM file and a different destination directory and while the progress window does appear, neither the progress indicator moves nor does the any seconds appear other than zero. It does appears to apply the image to my destination directory, but after about 10-20 seconds I'll get a not-responding for the AutoIt script.

I did find out my DLL is 6.1.7600.16385

Here's the script I was using:

Opt("MustDeclareVars", 1)
#include <wimgapi.au3>
;~ #include <DllCallback.au3>

Dim $fhandle, $vhandle, $imageinfo, $i, $pProgress
$pProgress = DllCallBackRegister ("_Progress", "int", "dword;lparam;wparam;ptr")
ConsoleWriteError("DllCallBack error: " & @error & @CRLF & "_DllCallBack rc: " & $pProgress & @CRLF)
$pProgress = DllCallbackGetPtr($pProgress)
ProgressOn("Wimgapi.dll","Applying image ...")
Apply("c:\PanasonicBootWim\boot.wim", "c:\test\")
;Apply("d:\distribution\Images\XP\GWPXP82.wim", "c:\test")
;~ ProgressOn("Wimgapi.dll","Capturing image ...")
;~ Capture("c:\temp\test.wim", "C:\temp\1\")
DllCallBackFree($pProgress)
ProgressOff()

Func _Progress($1,$2,$3,$4)
        If $1 = 38008 Then
                ProgressSet($2,"Remaining time : " & Int($3 / 1000) & " seconds")
        EndIf
;~ If $1 = 38008 Then
        ConsoleWrite("_Progress: " & @CRLF & $1 & @CRLF & $2 & @CRLF & $3 & @CRLF & $4 & @CRLF)
;~ EndIf

Return $wim_msg_success
;~ Return 0
EndFunc

Func Apply($wim,$sPath)
Local $rc_apply, $rc_close, $rc_shutdown, $lhandle, $rc_temppath
        $fhandle = _wim_createfile ($wim, $wim_generic_read)
;~      ConsoleWrite("_wim_createfile : " & $fhandle & @CRLF)
        $rc_temppath = _wim_settemporarypath($fhandle,@TempDir)
;~      ConsoleWrite("_wim_settemporarypath : " & $rc_temppath & @CRLF)
        $lhandle = _wim_loadimage ($fhandle,1)
;~      ConsoleWrite("_wim_loadimage : " & $lhandle & @CRLF)
        _wim_registermessagecallback($fhandle,$pProgress)
        $rc_apply = _wim_applyimage ($lhandle, $sPath)
;~      ConsoleWrite("_wim_applyimage : " & $rc_apply & @CRLF)
        _wim_unregistermessagecallback($fhandle,$pProgress)
        $rc_close = _wim_closehandle ($lhandle)
;~      ConsoleWrite("_wim_closehandle : " & $rc_close & @CRLF)
        $rc_close = _wim_closehandle ($fhandle)
;~      ConsoleWrite("_wim_closehandle : " & $rc_close & @CRLF)
        $rc_shutdown = _wim_shutdown ()
;~      ConsoleWrite("_wim_shutdown : " & $rc_shutdown & @CRLF)
EndFunc   ;==>Apply

Func Capture($wim,$sPath)
        $fhandle = _wim_createfile ($wim,$wim_generic_write,$wim_create_always,$wim_flag_verify,$wim_compress_xpress)

;~ $imageinfo = _wim_getimageinformation ($fhandle)

;~ ConsoleWrite("-- ImageInfo createFile" & @CRLF & UBound($imageinfo) & @CRLF)
;~ For $i = 0 To UBound($imageinfo) - 1
;~      ConsoleWrite("$imageinfo[" & $i & "]: " & $imageinfo[$i] & @CRLF)
;~ Next
;~ _wim_setimageinformation ($fhandle, $imageinfo[3], $imageinfo[1])
        _wim_registermessagecallback($fhandle,$pProgress)
        $vhandle = _wim_captureimage ($fhandle, $sPath)
        _wim_unregistermessagecallback($fhandle,$pProgress)
;~ $imageinfo = _wim_getimageinformation ($vhandle)
;~ ConsoleWrite("-- ImageInfo catureImage" & @CRLF & UBound($imageinfo) & @CRLF)
;~ For $i = 0 To UBound($imageinfo) - 1
;~      ConsoleWrite("$imageinfo[" & $i & "]: " & $imageinfo[$i] & @CRLF)
;~ Next
;~ _wim_setimageinformation ($vhandle, $imageinfo[3], $imageinfo[1])

        _wim_closehandle ($vhandle)
        _wim_closehandle ($fhandle)
        _wim_shutdown ()
EndFunc   ;==>Capture

Here's a snippit of the output I was getting in the console:

>"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "E:\ImageXProgressTest.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams    
+>11:56:10 Starting AutoIt3Wrapper v.2.0.1.24    Environment(Language:0409  Keyboard:00000409  OS:WIN_7/  CPU:X64 OS:X86)
>Running AU3Check (1.54.19.0)  from:C:\Program Files\AutoIt3
+>11:56:10 AU3Check ended.rc:0
>Running:(3.3.6.1):C:\Program Files\AutoIt3\autoit3.exe "E:\ImageXProgressTest.au3"    
_WIM_Startup rc: 1
DllCallBack error: 0
_DllCallBack rc: 1
_WIM_CreateFile rc: 7035896
UBound $create: 7
_WIM_SetTemporaryPath rc: 1
_WIM_LoadImage rc: 7039752
_WIM_RegisterMessageCallback rc: 0
_Progress: 
38009
10518488
4908908
0x00000000
_Progress: 
38009
7710040
4908804
0x00000000
_Progress: 
38009
8883400
4908700
0x00000000
_Progress: 
38009
10788600
4908596
0x00000000
_Progress: 
38009
9747864
4908492
0x00000000
_Progress: 
38009
8897008
4908700
0x00000000
_Progress: 
38009
8892208
4908596
0x00000000
_Progress: 
38009
8883512
4908492
0x00000000
_Progress: 
38009
8892312
4908596
0x00000000
_Progress: 
38009
8887544
4908492
0x00000000
_Progress: 
38009
8883288
4908596
0x00000000
_Progress: 
38009
8887664
4908492
0x00000000
_Progress: 
38009
8870928
4908804
0x00000000
_Progress: 
38009
10772328
4908908
0x00000000
_Progress: 
38009
7520536
4908804
0x00000000
_Progress: 
38009
8871016
4908700
0x00000000
_Progress: 
38009
8897104
4908596
0x00000000
_Progress: 
38009
8887424
4908492
0x00000000

I'm assuming by looking at your code that $2 is the actual percentage correct? Looking at the output, one of the 2nd set of numbers is 8897104

, a little high for a percentage :graduated:

Thoughts?

Link to comment
Share on other sites

i haven't worked on this script for quite some time, but all I know that the MsgId of the "ProgressMessage" from wimgapi.dll is 38008, thats why the if... 38008 then ... set progress is there.

And from the output you got, it looks like you never receive a progress message. For all I know, that is a threading problem of the dll (look at MSDN, some vbscript users ran into the same problem). somehow the DLL works different between applying and creating a WIM. if you are capturing a WIM, you get the progress message, if you apply a WIM, you dont get it.

Right now I dont understand why I posted in the past that the issue vanished. %)

"I teleported home one nightWith Ron and Sid and Meg.Ron stole Meggie's heart awayAnd I got Sidney's leg."- A poem about matter transference beams.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...