-
Posts
56 -
Joined
-
Last visited
Everything posted by Homes32
-
Env does not respond to WM_SETTINGCHANGE
Homes32 replied to Homes32's topic in AutoIt General Help and Support
Thank you all for the replies. Since my script that needs to listen ENV updates from external applications and is the parent process for other applications restarting it is not an option (it's a shell loader), I ended up just listening for WM_SETTINGCHANGE myself and querying the registry directly in order to perform a EnvSet() and EnvUpate() to update the "Local process" environment and push down any Env changes to @TempDir and to child processes as well. GUIRegisterMsg($WM_SETTINGCHANGE, "WindowProc") Func WindowProc($hWnd, $iMsg, $wParam, $lParam) Switch $iMsg Case $WM_SETTINGCHANGE If $lParam <> 0 Then $ilParamStringLen = _WinAPI_StrLen($lParam) $lParamString = DllStructCreate("wchar[" & $ilParamStringLen & "]", $lParam) $sString = DllStructGetData($lParamString, 1) If $sString = "Environment" Then Local $sTmpDir = RegRead("HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment", "TMP") Local $sTempDir = RegRead("HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment", "TEMP") EnvSet("TMP", $sTmpDir) EnvSet("TEMP", $sTempDir) EnvUpdate() ConsoleWrite("Env Change: Temp=" & @TempDir) EndIf EndIf EndSwitch EndFunc -
Env does not respond to WM_SETTINGCHANGE
Homes32 replied to Homes32's topic in AutoIt General Help and Support
Not quite. the question was specifically regarding updating the RUNNING script, not sub scripts. EnvUpdate() only updates child applications with the parent processes ENV, and in this case the PARENT is the ENV that needs to listen for Broadcasts from other applications. -
For example, when a program Run by the script changed %TEMP% and calls SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment") EnvGet() and @TempDir do not update to the new value, causing the next couple programs Run by the script to receive the wrong environment. According to the help docs and forum searches @TempDir is determined by GetTempPath(). Clearly EnvGet() is also not actually querying the event vars each time it is called, and just uses the value as of script start. Is there a method/option to force a running script to update EnvVars when a WM_SETTINGCHANGE message is received other then registering the WM_SETTINGCHANGE message and directly reading the registry and maintaining my own $TempDir variable? (Remember EnvGet() returns the old value as well)? Thanks! Homes32
-
download link is broken.
-
very nice tool. thanks for sharing!
- 12 replies
-
- registry
- group policy
-
(and 1 more)
Tagged with:
-
its very similar to capture.I have updated the example code in the first post with a basic Apply function.
-
3.07w to update replace upx.exe in C:\Program Files (x86)\AutoIt3\Aut2Exe\ or on x64 OS C:\Program Files (x86)\AutoIt3\Aut2Exe\ with the new version.
-
the orange text looks nice but I think the old black was easier to read on the white background.
-
forgot to upload v3 with fixed _WIM_GetImageInformation thanks JFX for helping figure this out!
-
sorry. but currently the limitations of Autoit's callback implementation prevent this from working correctly. I'm sure it also doesn't help that the apply functions of wimgapi.dll are multi-threaded. as far as I know nobody has every gotten the progress to work with /apply
-
Hi LaCastiglione, thanks for replying. I tried something like this already. the Crash actually occurs During DllStructGetData($xml, 1) so local_free($xml) will never be called. oops. my bad. just add $Percent as Global at the top. I also updated the sample code to fix this. thanks. Homes32
-
* updated above post to hopefully provide more information for anybody willing to help figure this out. *
-
I've run into an issue with getting info from a wim image. Autoit will crash and the windows event log will always show Exception code: 0xc0000005 which is a Access Violation error. tracing the _WIM_GetImageInformation func it always crashes at this line Func _WIM_GetImageInformation($hImage) Local $aReturn[2] ; array to hold the return data Local $ppvImageInfo = DllStructCreate("ptr") ; Buffer for XML Data Local $pcbImageInfo = DllStructCreate("int") ; Size of buffer in bytes Local $aResult = DllCall($ghwimgapi, "bool", "WIMGetImageInformation", _ "handle", $hImage, _ "ptr", DllStructGetPtr($ppvImageInfo), _ "ptr", DllStructGetPtr($pcbImageInfo)) If @error Then Return SetError(@error, @extended, 0) ; create a struct so we have access to the buffer where the XML data is stored Local $xml = DllStructCreate("wchar [" & DllStructGetData($pcbImageInfo, 1) & "]", DllStructGetData($ppvImageInfo, 1)) $aReturn[0] = $aResult[0] $aReturn[1] = DllStructGetData($xml, 1) ; <-- ***CRASH OCCURES HERE*** Return SetError(@error, _WinAPI_GetLastError(), $aReturn) EndFunc ;==>_WIM_GetImageInformation according to the return codes the structs get created correctly and the size of $xml is always correct, yet quite regularly reading data from $xml fails miserably. this doesn't happen every time the command is run but you can always reproduce by running the script several times in a row. the frequency seems random. can anyone give me some insite as to what may be going wrong here? some code to get everything up and running for anyone wanting to take a crack at this. make sure to download the UDF from the above link. thanks. Homes32 Steps to Reproduce If required change the path to the WIM file. In my tests the crashes were not specific to any particular WIM file. Run the following code several times in a row using F5 from SCITE or compile the code and use a cmd/bat to run several times in a row. It doesn't matter if you compile or use x68 vs x64, autoit will always have a hard crash at a seemingly random interval. Test code: #include <Wimgapi.au3> ; functions for WIM Global $swimfile, $hWim, $hImage, $filepath, $rTime, $pCallBack Global $gsWimDLL = @SystemDir & "\wimgapi.dll" ; path to wimgapi.dll $ProgramName = "WIM Demo" ; Fire up wimgapi.dll $aResult = _WIM_Startup() If @error = 2 Then MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.") Exit (2) ElseIf @error = 1 Then MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)") Exit (254) EndIf GetInfo("C:\Images\Win7_32_EN_DVD\SOURCES\BOOT.WIM") ; Change this path to your WIM file ; GetInfo ;----------------------------- Func GetInfo($sWimFile) ; load .wim file with read access $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0) If $hWim = 0 Then MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")") Cleanup() Exit (252) EndIf ; set our temp path $aResult = _WIM_SetTemporaryPath($hWim, @TempDir) ; read wim attributes $aWimAttribs = _WIM_GetImageAttributes($hWim) ; read info from the image $aXML = _WIM_GetImageInformation($hWim) ; Cleanup any open handles Cleanup() ; make our output pretty Switch $aWimAttribs[4] Case $WIM_COMPRESS_NONE $aWimAttribs[4] = "NONE" Case $WIM_COMPRESS_XPRESS $aWimAttribs[4] = "XPRESS" Case $WIM_COMPRESS_LZX $aWimAttribs[4] = "LZX" EndSwitch Local $outFile = @ScriptDir & "\wiminfo.txt" If FileExists($outFile) Then FileDelete($outFile) FileWrite($outFile, @CRLF & $ProgramName & @CRLF & @CRLF & @CRLF & @CRLF & _ "WIM Information:" & @CRLF & _ "----------------" & @CRLF & _ "Wim Path: : " & $aWimAttribs[1] & @CRLF & _ "GUID : " & $aWimAttribs[2] & @CRLF & _ "Image Count: " & $aWimAttribs[3] & @CRLF & _ "Compression: " & $aWimAttribs[4] & @CRLF & _ "Part Number: " & $aWimAttribs[5] & "/" & $aWimAttribs[6] & @CRLF & _ "Boot Index : " & $aWimAttribs[7] & @CRLF & _ "Attributes : " & $aWimAttribs[8] & @CRLF & @CRLF & @CRLF & _ "Available Image Choices:" & @CRLF & _ "------------------------" & @CRLF & _ $aXML[1]) EndFunc ;==>GetInfo Func Cleanup() ; Cleanup any open handles If $hImage Then _WIM_CloseHandle($hImage) If $hWim Then _WIM_CloseHandle($hWim) If $pCallBack Then ; Cleanup our callbacks $aResult = _WIM_UnregisterMessageCallback(0, DllCallbackGetPtr($pCallBack)) DllCallbackFree($pCallBack) EndIf _WIM_Shutdown() ; shutdown wimgapi.dll EndFunc ;==>Cleanup
-
thanks for keeping this great UDF up!
-
Glad you find it useful. its always nice to be able to give something back to a community that has been so helpful. UDF updated to v2. see 1st post.
-
correct. for xp you will still need to download the AIK from Microsoft.
-
yep #458 got me straightened out. thanks taietel!
-
using the demo script from the 1st post I can't get _GetResourceAsString to retrieve the contents of an embedded txt file. to work with a x64 bit compile. it works fine with 32bit. the problem seems to be in _ResourceGet() any ideas?
-
A UDF for manipulating Windows Image Files (.wim) without ImageX.exe This UDF allows you to use the Windows Imaging API directly (wimgapi.dll) so you don't have to use a command line program such as ImageX. Benefits are wimgapi.dll is shipped with windows 7 so users don't have to download the 1gb+ AIK to manage wim files. The UDF also allows you to utilize callback functions so you can show detailed progress info to your users. wimfltr.sys/wimmount.sys required for mount/unmount only. working with both 32 and 64 bit builds. its pretty well documented but you should still read the MS Imaging API documentation and be familiar how wimgapi.dll works to get the most out of this UDF. functions marked with an (*) are only available with newer versions of wimgapi.dll Functions Included: _WIM_ApplyImage _WIM_CaptureImage _WIM_CloseHandle _WIM_CreateFile _WIM_DeleteImage _WIM_DeleteImageMounts * _WIM_ExportImage _WIM_ExtractImagePath * _WIM_GetImageAttributes _WIM_GetImageCount _WIM_GetImageInformation _WIM_LoadImage _WIM_MountImage _WIM_RegisterLogFile * _WIM_RegisterMessageCallback _WIM_RemountImage * _WIM_SetBootImage _WIM_SetImageInformation _WIM_SetReferenceFile _WIM_SetTemporaryPath _WIM_Shutdown _WIM_Startup _WIM_UnMountImage _WIM_UnRegisterLogFile * _WIM_UnregisterMessageCallback have fun! Homes32 Sample Usage #include <Wimgapi.au3> ; functions for WIM Global $swimfile, $hWim, $hImage, $filepath, $Percent, $rTime, $pCallBack Global $gsWimDLL = @SystemDir & "wimgapi.dll" ; path to wimgapi.dll $ProgramName = "WIM Demo" ; Fire up wimgapi.dll $aResult = _WIM_Startup() If @error = 2 Then MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.") Exit (2) ElseIf @error = 1 Then MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)") Exit (254) EndIf ; your code here ; ex. ; Capture("C:toolz", "c:test.wim", "My Test IMG", "Test Desc", 1) ; Cleanup() ; Apply ;----------------------------- Func Apply($sWimFile, $iImageIndex, $sTarget) ProgressOn('Apply', '', '', -1, -1, 19) ; Register callbacks so we get progress information for the capture process. ; WARNING: This does not work very well with Apply do to the way autoit handles callbacks. ; See the following post for more info: ; http://www.autoitscript.com/forum/topic/127075-wimgapi-udf/page__view__findpost__p__917049 $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword') _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0) ; load .wim file with read access $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0) If $hWim = 0 Then MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")") Cleanup() Exit (252) EndIf ; set our temp path $aResult = _WIM_SetTemporaryPath($hWim, $sTarget) ; load the image index $hImage = _WIM_LoadImage($hWim, $iImageIndex) ; Apply the image $aResult = _WIM_ApplyImage($hImage, $sTarget) If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to apply image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")") Cleanup() ProgressOff() EndFunc ; Mount ;----------------------------- Func Mount($sMountPath, $sWimFile, $iImageIndex, $RW) $aResult = _WIM_MountImage($sMountPath, $sWimFile, $iImageIndex, $RW) If $aResult = 0 Then MsgBox(48, $ProgramName, "Mount Error: (" & $aResult & "," & @error & "," & @extended & ")") Cleanup() Exit (253) ; mount error EndIf Cleanup() EndFunc ; UnMount ;----------------------------- Func UnMount($sMountPath, $iCommit) $aResult = _WIM_UnMountImage($sMountPath, 0, 0, $iCommit) If $aResult = 0 Then MsgBox(48, $ProgramName, "UnMount Error: (" & $aResult & "," & @error & "," & @extended & ")") Cleanup() Exit (254) ; Unmount error EndIf Cleanup() EndFunc ; GetInfo ;----------------------------- Func GetInfo($sWimFile) ; load .wim file with read access $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0) If $hWim = 0 Then MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")") Cleanup() Exit (252) EndIf ; set our temp path $aResult = _WIM_SetTemporaryPath($hWim, @TempDir) ; read wim attributes $aWimAttribs = _WIM_GetImageAttributes($hWim) ; read info from the image $aXML = _WIM_GetImageInformation($hWim) ; Cleanup any open handles Cleanup() ; make our output pretty Switch $aWimAttribs[4] Case $WIM_COMPRESS_NONE $aWimAttribs[4] = "NONE" Case $WIM_COMPRESS_XPRESS $aWimAttribs[4] = "XPRESS" Case $WIM_COMPRESS_LZX $aWimAttribs[4] = "LZX" EndSwitch Local $outFile = @ScriptDir & "wiminfo.txt" If FileExists($outFile) Then FileDelete($outFile) FileWrite($outFile, @CRLF & $ProgramName & @CRLF & @CRLF & @CRLF & @CRLF & _ "WIM Information:" & @CRLF & _ "----------------" & @CRLF & _ "Wim Path: : " & $aWimAttribs[1] & @CRLF & _ "GUID : " & $aWimAttribs[2] & @CRLF & _ "Image Count: " & $aWimAttribs[3] & @CRLF & _ "Compression: " & $aWimAttribs[4] & @CRLF & _ "Part Number: " & $aWimAttribs[5] & "/" & $aWimAttribs[6] & @CRLF & _ "Boot Index : " & $aWimAttribs[7] & @CRLF & _ "Attributes : " & $aWimAttribs[8] & @CRLF & @CRLF & @CRLF & _ "Available Image Choices:" & @CRLF & _ "------------------------" & @CRLF & _ $aXML[1]) EndFunc ;==>GetInfo ; Extract ;----------------------------- Func Extract($sWimFile, $iImageIndex, $sFilePath, $sExtractTo) ; load .wim file with read access $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0) If $hWim = 0 Then MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")") Cleanup() Exit (252) EndIf ; set our temp path $aResult = _WIM_SetTemporaryPath($hWim, @TempDir) ; load the image index $hImage = _WIM_LoadImage($hWim, $iImageIndex) ; extract the file $aResult = _WIM_ExtractImagePath($hImage, $sFilePath, $sExtractTo) If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to extract from image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")") Cleanup() EndFunc ; Capture ;----------------------------- Func Capture($Path, $sWimFile, $sImageName, $sImageDesc, $Compress) ProgressOn('Capture', '', '', -1, -1, 19) ; Register callbacks so we get progress information for the capture process. $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword') _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0) ; first we need to create a blank .wim file with write access and our compression options $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_WRITE, $WIM_CREATE_ALWAYS, 0, $Compress, 0) If $hWim = 0 Then MsgBox(48, $ProgramName, "Error: Failed to create image. (" & $hWim & "," & @error & "," & @extended & ")") Cleanup() Exit (252) ; image create failed EndIf ; set our temp path $aResult = _WIM_SetTemporaryPath($hWim, @TempDir) ; start the image capture!!! $hImage = _WIM_CaptureImage($hWim, $Path, 0) If $hImage = 0 Then MsgBox(48, $ProgramName, "Error: Failed to capture image. (" & $hImage & "," & @error & "," & @extended & ")") Cleanup() Exit (251) ; image capture failed EndIf ; add our name and description to the XML data - ChrW(65279) is the BOM $sXML = ChrW(65279) & "<IMAGE><NAME>" & $sImageName & "</NAME><DESCRIPTION>" & $sImageDesc & "</DESCRIPTION></IMAGE>" _WIM_SetImageInformation($hImage, $sXML) _WIM_SetBootImage($hWim, 1) Cleanup() ; free resources ProgressOff() EndFunc ;==>Capture ; ================================================================================================================== ; Function: CallBack ; Description: Very Basic Sample Callback function for capture progress ; Usage: CallBack($msgId, $param1, $param2, $b) ; Author: Homes32 ; ================================================================================================================== Func CallBack($msgId, $param1, $param2, $unused) Switch $msgId Case $WIM_MSG_PROGRESS ; get progress % and time remaining $Percent = $param1 If $param2 = 0 Then $rTime = "" Else $rTime = StringFormat('Remaining: %i sec.', $param2 / 1000) EndIf Case $WIM_MSG_PROCESS ; get the file name being processed $Struct = DllStructCreate("ushort[1024]", $param1) $sFilePath = "" $i = 1 While 1 $Tmp = DllStructGetData($Struct, 1, $i) If $Tmp = 0 Then ExitLoop $sFilePath &= ChrW($Tmp) $i += 1 WEnd EndSwitch ProgressSet($Percent, StringFormat('%3i%% completed. %snn %s', $Percent, $rTime, $filePath), 'Capture ' & $sWimFile) Return $WIM_MSG_SUCCESS EndFunc ;==>CallBack Func Cleanup() ; Cleanup any open handles If $hImage Then _WIM_CloseHandle($hImage) If $hWim Then _WIM_CloseHandle($hWim) If $pCallBack Then ; Cleanup our callbacks $aResult = _WIM_UnregisterMessageCallback(0, DllCallbackGetPtr($pCallBack)) DllCallbackFree($pCallBack) EndIf _WIM_Shutdown() ; shutdown wimgapi.dll EndFunc ;==>Cleanup History v1 3-30-2011 * 1st release v2 4-4-2011 * cleaned up the documention * added the following functions _WIM_DeleteImage _WIM_DeleteImageMounts _WIM_ExportImage _WIM_RemountImage _WIM_SetReferenceFile v3 9-19-2011 * Fixed Access Violation crash in _WIM_GetImageInformation Previous Downloads: 312 WimgapiUDF.zip
-
[Solved] Dll call writing data to struct.
Homes32 replied to Homes32's topic in AutoIt General Help and Support
that was my problem! thanks for pointing it out! Cheers! Homes32 -
[Solved] Dll call writing data to struct.
Homes32 replied to Homes32's topic in AutoIt General Help and Support
thanks for the replys. I took out the array stuff but that and changing the data type makes no difference. (I tried before posting and tried your examples again just to be sure.) any other thoughts? Func _WIM_GetImageAttributes($hWim) Local $pWimInfo = DllStructCreate($tagWIM_INFO) if @error Then MsgBox(0,"","Error in DllStructCreate: " & @error); $aReturn = DllCall($ghwimgapi, "bool", "WIMGetAttributes", _ "handle", $hWim, _ "ptr", DllStructGetPtr($pWimInfo), _ "dword", DllStructGetSize($pWimInfo)) If @error Then Return SetError(@error, @extended, $aReturn) Return SetError(@error, _WinAPI_GetLastError(), $aReturn[0]) EndFunc ;==>_WIM_GetAttributes -
hello all, I'm working on trying to get Attributes from a .wim file and have hit a wall. calling the WIMGetAttributes function from wimgapi.dll always returns false for me and GetLastError() returns 87 ERROR_INVALID_PARAMETER as far as I can tell I have all the parameters correct. and I can confirm that I get the correct handle for $hWim and that the struct is created successfully with a size of: 552 I've been looking at this for so long its hard for me to tell if I have something screwed up. has anybody had success calling this function with autoit? please let me know if there is any information I forgot to give. thanks. Homes32 Func _WIM_GetImageAttributes($hWim) Local $aReturn[2] ; array to hold the return data Local $hWimInfo = DllStructCreate($tagWIM_INFO) if @error Then MsgBox(0,"","Error in DllStructCreate: " & @error); $aReturn[0] = DllCall($ghwimgapi, "int", "WIMGetAttributes", _ "ptr", $hWim, _ "ptr", DllStructGetPtr($hWimInfo), _ "int", DllStructGetSize($hWimInfo)) If @error Then Return SetError(@error, @extended, $aReturn) ;$aReturn[0] = DllCall return value Return SetError(@error, _WinAPI_GetLastError(), $aReturn[0]) EndFunc ;==>_WIM_GetAttributes Global Const $tagWIM_INFO = "wchar WimPath[256];byte Guid[16];dword ImageCount;dword CompressionType;ushort PartNumber;" & _ "ushort TotalParts;dword BootIndex;dword WimAttributes;dword WimFlagsAndAttr"[/autoit]function prototype and struct definition BOOL WINAPI WIMGetAttributes( IN HANDLE hWim, OUT LPWIM_INFO lpWimInfo, IN DWORD cbWimInfo ); typedef struct _WIM_INFO { WCHAR WimPath[MAX_PATH]; GUID Guid; DWORD ImageCount; DWORD CompressionType; USHORT PartNumber; USHORT TotalParts; DWORD BootIndex; DWORD WimAttributes; } WIM_INFO, *PWIM_INFO, *LPWIM_INFO;
-
thats an interesting thought...I'll have to play around with the idea.