RvdH Posted January 7, 2011 Share Posted January 7, 2011 Hello, It has been a while last time i was here, nice to see everything is still up and running like it was in the time i joined here.Anyone can help me out, i like to read DISM StdoutRead and display a custom progress bar using AutoItI have found some partial scripts here, but none seems to work with DISMIn the code below the idea was to read out the increasing '=' signs as shown in the pics above#RequireAdmin Opt("MustDeclareVars", 0) ; Script Start - Add your code below here ; Set the max number of = signs to expect $maxTicks = 52 ;26 = signs both left and right from the percentage indicator ; Run the child process, connecting to its STDOUT pipe $process = Run(@COMSPEC & ' /k dism /mount-wim /wimfile:' & @ScriptDir & '/boot.wim /index:1 /mountDir:C:\Mount', @ScriptDir, @SW_HIDE, 2) ; Show the progress bar ProgressOn("= Count", "Counting...") ; Read from the child's STDOUT While 1 $readTicks = StdoutRead($process) ; if StdoutRead sets @error to -1 we're at EOF, so exit If @error = -1 Then ExitLoop StringReplace($readTicks, "=", "0") ; StringReplace keeps a count of chars it replaces in @extended $totalTicks += @extended ; Adjust the progress bar ProgressSet(($totalTicks / $maxTicks) * 100) WEnd ; Hide the progress bar ProgressOff() MsgBox(0, "Debug", "Done.") ; FinishedAnyone got an idea how to make this work?RvdH Link to comment Share on other sites More sharing options...
jvanegmond Posted January 7, 2011 Share Posted January 7, 2011 Hey, I am getting a undeclared variable error from this line: $totalTicks += @extended. I added the $totalTicks = 0 at the beginning of the script but then I realized that it doesn't make sense to add the new number of "=" to the old number of "=". So I simply changed that to: StringReplace($readTicks, "=", "0") ; StringReplace keeps a count of chars it replaces in @extended ; Adjust the progress bar ProgressSet((@extended / $maxTicks) * 100) In the end, I wrote a "unit test" for your script since I can't test DISM like you can. And it shows that the code works: expandcollapse popup; Script Start - Add your code below here ; Set the max number of = signs to expect $maxTicks = 52 ;26 = signs both left and right from the percentage indicator ; Run the child process, connecting to its STDOUT pipe $process = 0;Run(@COMSPEC & ' /k dism /mount-wim /wimfile:' & @ScriptDir & '/boot.wim /index:1 /mountDir:C:\Mount', @ScriptDir, @SW_HIDE, 2) ; Show the progress bar ProgressOn("= Count", "Counting...") ; Read from the child's STDOUT While 1 $readTicks = _StdoutRead($process) ; if StdoutRead sets @error to -1 we're at EOF, so exit If @error = -1 Then ExitLoop StringReplace($readTicks, "=", "0") ; StringReplace keeps a count of chars it replaces in @extended ; Adjust the progress bar ProgressSet((@extended / $maxTicks) * 100) WEnd ; Hide the progress bar ProgressOff() MsgBox(0, "Debug", "Done.") ; Finished Func _StdoutRead($ignoreMe) Static $i = 0 Switch $i Case 0 Return "====" Case 1 Return "===========" Case 2 Return "==================" Case 3 Return "=============================" Case 4 Return "====================================================" Case Else Return SetError(1) EndSwitch $i += 1 EndFunc If this still doesn't fix your problem, then I don't think AutoIt is reading the output of the progress from console. ($readTicks is always an empty line) github.com/jvanegmond Link to comment Share on other sites More sharing options...
Mat Posted January 7, 2011 Share Posted January 7, 2011 (edited) I think Manadar is right in that you can't read that progress bar all that easily... I think you need to use ReadConsoleOutput to read a specific block, and unfortunately it's one of the functions I haven't implemented you in my console udf.Edit: Can't you just read the percentage value? Edited January 7, 2011 by Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
RvdH Posted January 7, 2011 Author Share Posted January 7, 2011 (edited) @Manadar Thx for the prompt reply Looks like you are right, progress indicator just hangs. So it seems like you said AutoIt is not reading the dynamic changing values in a line... damn, another way to accomplish that? Edited January 7, 2011 by RvdH Link to comment Share on other sites More sharing options...
RvdH Posted January 7, 2011 Author Share Posted January 7, 2011 (edited) @Mat Reading percentage value, how do i accomplish that? Don't i have the exact same issue as above using that technique? Edited January 8, 2011 by RvdH Link to comment Share on other sites More sharing options...
Mat Posted January 7, 2011 Share Posted January 7, 2011 (edited) Read the start of my reply. I gave you the method I know of Edit: Just to clarify, the reason I said to use the percentage is because I thought it might be easier to read a smaller block and end up with a more accurate number. Edited January 7, 2011 by Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
jvanegmond Posted January 7, 2011 Share Posted January 7, 2011 RvdH, unless someone else comes along, I think solving this problem at hand is going to be more work than it is worth. github.com/jvanegmond Link to comment Share on other sites More sharing options...
sdgsdgsdgsdg Posted January 8, 2011 Share Posted January 8, 2011 Hi, I have the same problem, except I try to do it in .NET. I tried to send an email to the developers of gimagex and imagex/dism (Microsoft), but they didn't answered... There is a solution for sure, because gimagex have a progress bar... but what is the solution !? Thanks ! Link to comment Share on other sites More sharing options...
Mat Posted January 8, 2011 Share Posted January 8, 2011 I did tell you. ReadConsoleOutput it allows you to copy a block of characters from one buffer to another. For an example look here AutoIt Project Listing Link to comment Share on other sites More sharing options...
RvdH Posted January 8, 2011 Author Share Posted January 8, 2011 (edited) @Manadar Thx, guess you are right @Mat, To be honest, your suggestion for me is way out of my (AutoIt) programming skills. With other words i have no clue of where to start from. Maybe you could add it to your "TODO" list for your console udf? Edited January 8, 2011 by RvdH Link to comment Share on other sites More sharing options...
MvGulik Posted January 8, 2011 Share Posted January 8, 2011 Mmm, any known alternative to using DISM to test on. (if DISM is not using some special MS-trick here of course.) "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ... Link to comment Share on other sites More sharing options...
Mat Posted January 8, 2011 Share Posted January 8, 2011 I want to get the full list, the only problem is that it uses extensive structures... Such as needing an array of a particular structure. You should be ok making a workaround using just one CHAR_INFO struct and calling the function 4 times to get the percentage, or write it in C in which case it gets easier (but other bit's will get harder ) AutoIt Project Listing Link to comment Share on other sites More sharing options...
Mat Posted January 8, 2011 Share Posted January 8, 2011 Mmm, any known alternative to using DISM to test on. (if DISM is not using some special MS-trick here of course.) Yes. Before you look at the code, this is NOT a good example, and I would never want it used for anything other than testing on. The correct would be making a second buffer and using WriteConsoleOutput, making the cursor jump everywhere is not the way to do this. #include <Console.au3> _Console_Alloc() ; The width of the dism progress is 60 chars, 2 chars are brackets so 58 possible = signs. ; The percentage starts at 27 chars, and is right aligned in 6 chars (Always to 1dp). Local $tScreenBufferInfo = _Console_GetScreenBufferInfo() Local $iWidth = DllStructGetData($tScreenBufferInfo, "SizeX") Local $iY = DllStructGetData($tScreenBufferInfo, "CursorPositionY") _Console_FillOutputCharacter(-1, " ", $iWidth, 0, $iY) _Console_FillOutputCharacter(-1, "[", 1, 0, $iY) _Console_FillOutputCharacter(-1, "]", 1, 59, $iY) _Console_SetCursorPosition(-1, 1, $iY) Local $iPercent For $i = 1 To 58 $sPercent = StringFormat("%.1f%%", Round(($i / 58) * 100, 1)) _Console_SetCursorPosition(-1, 33 - StringLen($sPercent), $iY) _Console_Write($sPercent) If $i < 33 - StringLen($sPercent) Or $i >= 33 Then _Console_SetCursorPosition(-1, $i, $iY) _Console_Write("=") EndIf _Console_SetCursorPosition(-1, 0, $iY + 1) Sleep(100) Next Sleep(2000) _Console_Free() AutoIt Project Listing Link to comment Share on other sites More sharing options...
Mat Posted January 8, 2011 Share Posted January 8, 2011 (edited) Ok, a few updates. You can use the ReadConsoleOutputCharacter function rather than the ReadConsoleOutput one. I don't see any reason why I can't implement it soon it looks like it's easy enough.Also, another better example (in C++ as I haven't implemented the function in AutoIt yet):expandcollapse popup#include "stdafx.h" #include <windows.h> // The width of the dism progress is 60 chars, 2 chars are brackets so 58 possible = signs. // The percentage starts at char 27, and is right aligned in 6 chars (Always to 1dp). int _tmain(int argc, _TCHAR* argv[]) { char sBar[60]; FillMemory(sBar, 60, ' '); float nPercent; char sPercent[6]; HANDLE hConsole; COORD dwTarget; DWORD dwWritten; CONSOLE_CURSOR_INFO tCCI; hConsole = GetStdHandle(STD_OUTPUT_HANDLE); dwTarget.X = 0; dwTarget.Y = 0; GetConsoleCursorInfo(hConsole, &tCCI); tCCI.bVisible = false; SetConsoleCursorInfo(hConsole, &tCCI); // Add knowns: sBar[0] = '['; sBar[59] = ']'; sBar[32] = '%'; for (int i = 1; i <= 58; i++) { nPercent = (float)i / 58 * 100; sprintf(sPercent, "%5.1f", nPercent); if (i < 30 || i > 32) sBar[i] = '='; for (int n = 0; n <= 4; n++) { if (sPercent[n] == ' ') continue; sBar[27 + n] = sPercent[n]; } WriteConsoleOutputCharacterA(hConsole, &sBar[0], 60, dwTarget, &dwWritten); Sleep(100); } dwTarget.X = 0; dwTarget.Y = 1; SetConsoleCursorPosition(hConsole, dwTarget); tCCI.bVisible = true; SetConsoleCursorInfo(hConsole, &tCCI); getchar(); return 0; }ProgressExample.exeEdit: And finally the solution. It runs slightly behind, and eats a lot of cpu - but it works It needs the ProgressExample.exe I wrote from above.expandcollapse popup#include <Console.au3> $__gvKernel32 = DllOpen("kernel32.dll") Local $iPid = Run("ProgressExample.exe", @ScriptDir) ProcessWait($iPid) _Console_Attach($iPid) ; The width of the dism progress is 60 chars, 2 chars are brackets so 58 possible = signs. ; The percentage starts at 27 chars, and is right aligned in 6 chars (Always to 1dp). Local $hStdOut = _Console_GetStdHandle($STD_OUTPUT_HANDLE) Local $tScreenBufferInfo = _Console_GetScreenBufferInfo($hStdOut) Local $iY = DllStructGetData($tScreenBufferInfo, "CursorPositionY") ProgressOn("ProgressExample.exe", "...") While ProcessExists($iPid) $s = _Console_ReadConsoleOutputCharacter($hStdOut, 5, 27, $iY) ProgressSet(Execute(StringReplace($s, "=", ""))) WEnd ProgressOff() _Console_Free() Exit Func _Console_ReadConsoleOutputCharacter($hConsoleOutput, $nNumberOfCharsToRead, $iX, $iY, $fUnicode = Default, $hDll = -1) Local $tCoord, $tBuffer, $aResult If $fUnicode = Default Then $fUnicode = $__gfUnicode If $hDll = -1 Then $hDll = $__gvKernel32 If $hConsoleOutput = -1 Then $hConsoleOutput = _Console_GetStdHandle($STD_OUTPUT_HANDLE, $hDll) $tCoord = BitShift($iY, -16) + $iX If $fUnicode Then $tBuffer = DllStructCreate("wchar[" & ($nNumberOfCharsToRead + 1) & "]") $aResult = DllCall($hDll, "bool", "ReadConsoleOutputCharacterW", _ "handle", $hConsoleOutput, _ "ptr", DllStructGetPtr($tBuffer), _ "dword", $nNumberOfCharsToRead, _ "dword", $tCoord, _ "dword*", 0) Else $tBuffer = DllStructCreate("char[" & ($nNumberOfCharsToRead + 1) & "]") $aResult = DllCall($hDll, "bool", "ReadConsoleOutputCharacterA", _ "handle", $hConsoleOutput, _ "ptr", DllStructGetPtr($tBuffer), _ "dword", $nNumberOfCharsToRead, _ "dword", $tCoord, _ "dword*", 0) EndIf If @error Or (Not $aResult[0]) Then Return SetError(@error, @extended, "") Return SetExtended($aResult[4], DllStructGetData($tBuffer, 1)) EndFunc ;==>_Console_ReadConsoleOutputCharacter Edited January 8, 2011 by Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
RvdH Posted January 10, 2011 Author Share Posted January 10, 2011 Wow, Mat that's fantastic Just tried to port it to the actual DISM console window, Local $iY = DllStructGetData($tScreenBufferInfo, "CursorPositionY") seems off, it doesn't display the progress. Once changed to '5' it functions correctly. Link to comment Share on other sites More sharing options...
Mat Posted January 10, 2011 Share Posted January 10, 2011 (edited) Ah right ok, I was assuming the cursor would be on the same line as the progress, but that doesn't have to be the case with WriteConsoleOutputCharacter. Thanks for reminding me as well, I've added those two functions to the library now. Up to 85 With the latest version: #include <Console.au3> $__gvKernel32 = DllOpen("kernel32.dll") Local $iPid = Run("ProgressExample.exe", @ScriptDir) ProcessWait($iPid) _Console_Attach($iPid) ; The width of the dism progress is 60 chars, 2 chars are brackets so 58 possible = signs. ; The percentage starts at 27 chars, and is right aligned in 6 chars (Always to 1dp). ProgressOn("ProgressExample.exe", "...") While ProcessExists($iPid) $s = _Console_ReadOutputCharacter(-1, 5, 27, 5) ProgressSet(Execute(StringReplace($s, "=", ""))) WEnd ProgressOff() _Console_Free() Exit Edited January 10, 2011 by Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
FreeBeing Posted November 7, 2013 Share Posted November 7, 2013 Thank you for your script and Console UDF, it works perfectly with Windows PE 5 and DISM Link to comment Share on other sites More sharing options...
SmokieBlahBlah Posted February 15, 2014 Share Posted February 15, 2014 (edited) ProgressExample.exe unavailable. Give me it please. Thanks :3 Edited February 15, 2014 by SmokieBlahBlah Link to comment Share on other sites More sharing options...
this-is-me Posted February 16, 2014 Share Posted February 16, 2014 ProgressExample.exe unavailable. Give me it please. Thanks :3 !!!??? I need please document example code before give ProgressExample.exe. Do not delay or file deleted in few minutes! Who else would I be? Link to comment Share on other sites More sharing options...
tarvr Posted August 9, 2015 Share Posted August 9, 2015 (edited) Hello,I tried to modify this script for deploying a WIM image via DISM.The WIM deployment is working, but not the progress bar.Any idea to get this working?ThanksPS: console.au3 Ver 0.0.0.27expandcollapse popup#include <Console.au3> _DeployWim() Func _DeployWim() ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; Apply Wim Image with GUI Bar ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;Variables $ApplicationSource = @ScriptDir $WIMPACKAGE_NAME = "Win10-Prof-64bit-EN.wim" $IMAGEX_PATH = $ApplicationSource & "\Imagex32\Dism.exe" ; <Path to imagex.exe> $PACKAGE_NAME = $ApplicationSource & "\WimFiles\" & $WIMPACKAGE_NAME ; <Path to your WIM package> $DRIVE_DEST = "w:\" ; <Drive Destination (i.e.: C:)> $SPLASH_TITLE = "Applying image ..." ; example "My Company Imaging" $__gvKernel32 = DllOpen("kernel32.dll") Local $iPid = Run($IMAGEX_PATH & " /Apply-Image /ImageFile:" & $PACKAGE_NAME & " /index:1 /ApplyDir:" & $DRIVE_DEST, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) ProcessWait($iPid) _Console_Attach($iPid) ; The width of the dism progress is 60 chars, 2 chars are brackets so 58 possible = signs. ; The percentage starts at 27 chars, and is right aligned in 6 chars (Always to 1dp). ProgressOn("Dism.exe", "...") While ProcessExists($iPid) $s = _Console_ReadOutputCharacter(-1, 5, 27, 5) ProgressSet(Execute(StringReplace($s, "=", ""))) WEnd ProgressOff() _Console_Free() Exit EndFunc Func _Console_ReadConsoleOutputCharacter($hConsoleOutput, $nNumberOfCharsToRead, $iX, $iY, $fUnicode = Default, $hDll = -1) Local $tCoord, $tBuffer, $aResult If $fUnicode = Default Then $fUnicode = $__gfUnicode If $hDll = -1 Then $hDll = $__gvKernel32 If $hConsoleOutput = -1 Then $hConsoleOutput = _Console_GetStdHandle($STD_OUTPUT_HANDLE, $hDll) $tCoord = BitShift($iY, -16) + $iX If $fUnicode Then $tBuffer = DllStructCreate("wchar[" & ($nNumberOfCharsToRead + 1) & "]") $aResult = DllCall($hDll, "bool", "ReadConsoleOutputCharacterW", _ "handle", $hConsoleOutput, _ "ptr", DllStructGetPtr($tBuffer), _ "dword", $nNumberOfCharsToRead, _ "dword", $tCoord, _ "dword*", 0) Else $tBuffer = DllStructCreate("char[" & ($nNumberOfCharsToRead + 1) & "]") $aResult = DllCall($hDll, "bool", "ReadConsoleOutputCharacterA", _ "handle", $hConsoleOutput, _ "ptr", DllStructGetPtr($tBuffer), _ "dword", $nNumberOfCharsToRead, _ "dword", $tCoord, _ "dword*", 0) EndIf If @error Or (Not $aResult[0]) Then Return SetError(@error, @extended, "") Return SetExtended($aResult[4], DllStructGetData($tBuffer, 1)) EndFunc ;==>_Console_ReadConsoleOutputCharacter Edited August 9, 2015 by tarvr Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now