KaFu Posted October 7, 2010 Share Posted October 7, 2010 (edited) Hiho,trying to figure out how to get my example Retrieve Unicode results from Console working on x64 I took a look at the $tagSTARTUPINFO. Seems to work fine on x86.This is the current definition:Global Const $tagSTARTUPINFO = "int Size;ptr Reserved1;ptr Desktop;ptr Title;int X;int Y;int XSize;int YSize;int XCountChars;" & _ "int YCountChars;int FillAttribute;int Flags;short ShowWindow;short Reserved2;ptr Reserved3;int StdInput;" & _ "int StdOutput;int StdError"MSDN defines the last three elements as handles. This clearly busts the current definition (int).typedef struct _STARTUPINFO { DWORD cb; LPTSTR lpReserved; LPTSTR lpDesktop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError;} STARTUPINFO, *LPSTARTUPINFO;LPTSTR equals ptr? I don't know . Anyone willing to take a look. Here's my current suggestion:Global Const $tagSTARTUPINFO = "int Size;ptr Reserved1;ptr Desktop;ptr Title;int X;int Y;int XSize;int YSize;int XCountChars;" & _ "int YCountChars;int FillAttribute;int Flags;short ShowWindow;short Reserved2;ptr Reserved3;handle StdInput;" & _ "handle StdOutput;handle StdError" Edited October 7, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
trancexx Posted October 7, 2010 Share Posted October 7, 2010 This is the current definition:No, it's not. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 According to the UDF help-file... which is not up-to-date... ... The current StructureConstants.au3 defines it as: Global Const $tagSTARTUPINFO = "dword Size;ptr Reserved1;ptr Desktop;ptr Title;dword X;dword Y;dword XSize;dword YSize;dword XCountChars;" & _ "dword YCountChars;dword FillAttribute;dword Flags;word ShowWindow;word Reserved2;ptr Reserved3;handle StdInput;" & _ "handle StdOutput;handle StdError" LPTSTR = ptr? LPBYTE = ptr? OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
jaberwacky Posted October 7, 2010 Share Posted October 7, 2010 (edited) MSDN says the following about LPTSTR: "The letter "T" in a type definition, for example, TCHAR or LPTSTR, designates a generic type that can be compiled for either Windows code pages or Unicode." Also has this to say: "An LPWSTR if UNICODE is defined, an LPSTR otherwise." So maybe a wstr* or just a wstr? Edited October 7, 2010 by jaberwocky6669 Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 (edited) Replacing LPTSTR = ptr with LPTSTR = wstr or LPTSTR = wstr* makes the function fail on x86 too. Thanks for the link to MSDN Windows Data Types definitions, something to bookmark , knew it, but didn't remembered it . Edit: Here's a working x86 example, fails on x64. expandcollapse popup#AutoIt3Wrapper_UseX64=n #include <NamedPipes.au3> #include <WinAPI.au3> Global Const $tagSTARTUPINFO_New = "dword Size;ptr Reserved1;ptr Desktop;ptr Title;dword X;dword Y;dword XSize;dword YSize;dword XCountChars;" & _ "dword YCountChars;dword FillAttribute;dword Flags;word ShowWindow;word Reserved2;ptr Reserved3;handle StdInput;" & _ "handle StdOutput;handle StdError" ; Example Start #include <array.au3> ; for example only $timer = TimerInit() $aFiles = _FileListToArrayEx(@ProgramFilesDir, "*.*", 0, -1, True, True) ConsoleWrite(TimerDiff($timer) & @CRLF & $aFiles[0] & " files read" & @CRLF) _ArrayDisplay($aFiles) ; Example End ;=============================================================================== ; ; Description: lists all or preferred files and or folders in a specified path (Similar to using Dir with the /B Switch) ; Syntax: _FileListToArrayEx($sPath, $sFilter = '*.*', $iFlag = 0, $sExclude = '') ; Parameter(s): $sPath = Path to generate filelist for ; $sFilter = The filter to use. Search the Autoit3 manual for the word "WildCards" For details, support now for multiple searches ; Example *.exe; *.txt will find all .exe and .txt files ; $iFlag = determines weather to return file or folders or both. ; $sExclude = exclude a file from the list by all or part of its name ; Example: Unins* will remove all files/folders that start with Unins ; $iFlag=0(Default) Return both files and folders ; $iFlag=1 Return files Only ; $iFlag=2 Return Folders Only ; ; Requirement(s): None ; Return Value(s): On Success - Returns an array containing the list of files and folders in the specified path ; On Failure - Returns the an empty string "" if no files are found and sets @Error on errors ; @Error or @extended = 1 Path not found or invalid ; @Error or @extended = 2 Invalid $sFilter or Invalid $sExclude ; @Error or @extended = 3 Invalid $iFlag ; @Error or @extended = 4 No File(s) Found ; ; Author(s): SmOke_N, modified by mfecteau, Ascend4nt & KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=33930&view=findpost&p=799369 ; Note(s): The array returned is one-dimensional and is made up as follows: ; $array[0] = Number of Files\Folders returned ; $array[1] = 1st File\Folder ; $array[2] = 2nd File\Folder ; $array[3] = 3rd File\Folder ; $array[n] = nth File\Folder ; ; All files are written to a "reserved" .tmp file (Thanks to gafrost) for the example ; The Reserved file is then read into an array, then deleted ;=============================================================================== Func _FileListToArrayEx($s_path, $s_mask = "*.*", $i_flag = 0, $s_exclude = -1, $f_recurse = False, $f_full_path = False) If FileExists($s_path) = 0 Then Return SetError(1, 1, 0) ; Strip trailing backslash, and add one after to make sure there's only one $s_path = StringRegExpReplace($s_path, "[\\/]+\z", "") & "\" ; Set all defaults If $s_mask = -1 Or $s_mask = Default Then $s_mask = "*.*" If $i_flag = -1 Or $i_flag = Default Then $i_flag = 0 If $s_exclude = -1 Or $s_exclude = Default Then $s_exclude = "" ; Look for bad chars If StringRegExp($s_mask, "[/:><\|]") Or StringRegExp($s_exclude, "[/:><\|]") Then Return SetError(2, 2, 0) EndIf ; Strip leading spaces between semi colon delimiter $s_mask = StringRegExpReplace($s_mask, "\s*;\s*", ";") If $s_exclude Then $s_exclude = StringRegExpReplace($s_exclude, "\s*;\s*", ";") ; Confirm mask has something in it If StringStripWS($s_mask, 8) = "" Then Return SetError(2, 2, 0) If $i_flag < 0 Or $i_flag > 2 Then Return SetError(3, 3, 0) ; Validate and create path + mask params Local $a_split = StringSplit($s_mask, ";"), $s_hold_split = "" For $i = 1 To $a_split[0] If StringStripWS($a_split[$i], 8) = "" Then ContinueLoop If StringRegExp($a_split[$i], "^\..*?\..*?\z") Then $a_split[$i] &= "*" & $a_split[$i] EndIf $s_hold_split &= '"' & $s_path & $a_split[$i] & '" ' Next $s_hold_split = StringTrimRight($s_hold_split, 1) If $s_hold_split = "" Then $s_hold_split = '"' & $s_path & '*.*"' Local $i_pid, $s_stdout, $s_hold_out, $s_dir_file_only = "", $s_recurse = "/s " If $i_flag = 1 Then $s_dir_file_only = ":-d" If $i_flag = 2 Then $s_dir_file_only = ":D" If Not $f_recurse Then $s_recurse = "" $command = @ComSpec & " /u /c dir /b " & $s_recurse & "/a" & $s_dir_file_only & " " & $s_hold_split $s_hold_out = _RunWaitStdOut($command, "", @SW_HIDE) ; ConsoleWrite($command & @crlf & $s_hold_out & @crlf & @extended & @crlf) $s_hold_out = StringRegExpReplace($s_hold_out, "\v+\z", "") If Not $s_hold_out Then Return SetError(4, 4, 0) ; Parse data and find matches based on flags Local $a_fsplit = StringSplit(StringStripCR($s_hold_out), @LF), $s_hold_ret $s_hold_out = "" If $s_exclude Then $s_exclude = StringReplace(StringReplace($s_exclude, "*", ".*?"), ";", "|") For $i = 1 To $a_fsplit[0] If $s_exclude And StringRegExp(StringRegExpReplace( _ $a_fsplit[$i], "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\Q" & $s_exclude & "\E") Then ContinueLoop If StringRegExp($a_fsplit[$i], "^\w:[\\/]+") = 0 Then $a_fsplit[$i] = $s_path & $a_fsplit[$i] If $f_full_path Then $s_hold_ret &= $a_fsplit[$i] & Chr(1) Else $s_hold_ret &= StringRegExpReplace($a_fsplit[$i], "((?:.*?[\\/]+)*)(.*?\z)", "$2") & Chr(1) EndIf Next $s_hold_ret = StringTrimRight($s_hold_ret, 1) If $s_hold_ret = "" Then Return SetError(5, 5, 0) Return StringSplit($s_hold_ret, Chr(1)) EndFunc ;==>_FileListToArrayEx ; ==================================================================================================== ; Execute a command and display the results ; ==================================================================================================== ; Paul Campbell (PaulIA), ProgAndy, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=76607&view=findpost&p=555091 Func _RunWaitStdOut($sCmd, $sWorkingDir = "", $state = @SW_SHOW) Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup Local $STILL_ACTIVE = 0x103 Local Const $STARTF_USESHOWWINDOW = 0x1 Local Const $STARTF_USESTDHANDLES = 0x100 ; Set up security attributes $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT _NamedPipes_CreatePipe($hReadPipe, $hWritePipe, $tSecurity) ; Create child process $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO_New) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) DllStructSetData($tStartup, "ShowWindow", $state) _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, $sWorkingDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Local $handle = DllStructGetData($tProcess, "hProcess"), $exitCode _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) Do $exitCode = DllCall("kernel32.dll", "long", "GetExitCodeProcess", "hwnd", $handle, "dword*", 0) Until $exitCode[0] <> $STILL_ACTIVE $exitCode = $exitCode[2] ; Close the write end of the pipe before reading from the read end of the pipe _WinAPI_CloseHandle($handle) _WinAPI_CloseHandle($hWritePipe) ; Read data from the child process $tBuffer = DllStructCreate("wchar Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) While 1 _WinAPI_ReadFile($hReadPipe,$pBuffer , 4096, $iBytes) If $iBytes = 0 Then ExitLoop $sData &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes / 2) WEnd _WinAPI_CloseHandle($hReadPipe) SetExtended($exitCode) Return $sData EndFunc ;==>_RunWaitStdOut $tagSECURITY_ATTRIBUTES or $tagPROCESS_INFORMATION might be another reason why the function fails, but those look quite simple (and correct imho) compared to $tagSTARTUPINFO. Edited October 7, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
trancexx Posted October 7, 2010 Share Posted October 7, 2010 Replacing LPTSTR = ptr with LPTSTR = wstr or LPTSTR = wstr* makes the function fail on x86 too. Thanks for the link to MSDN Windows Data Types definitions, something to bookmark , knew it, but didn't remembered it . Edit: Here's a working x86 example, fails on x64. expandcollapse popup#AutoIt3Wrapper_UseX64=n #include <NamedPipes.au3> #include <WinAPI.au3> Global Const $tagSTARTUPINFO_New = "dword Size;ptr Reserved1;ptr Desktop;ptr Title;dword X;dword Y;dword XSize;dword YSize;dword XCountChars;" & _ "dword YCountChars;dword FillAttribute;dword Flags;word ShowWindow;word Reserved2;ptr Reserved3;handle StdInput;" & _ "handle StdOutput;handle StdError" ; Example Start #include <array.au3> ; for example only $timer = TimerInit() $aFiles = _FileListToArrayEx(@ProgramFilesDir, "*.*", 0, -1, True, True) ConsoleWrite(TimerDiff($timer) & @CRLF & $aFiles[0] & " files read" & @CRLF) ;_ArrayDisplay($aFiles) ; Example End Func _FileListToArrayEx($s_path, $s_mask = "*.*", $i_flag = 0, $s_exclude = -1, $f_recurse = False, $f_full_path = False) ; By mfecteau & Ascend4nt, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=33930&st=60&p=799369&#entry799369 If FileExists($s_path) = 0 Then Return SetError(1, 1, 0) ; Strip trailing backslash, and add one after to make sure there's only one $s_path = StringRegExpReplace($s_path, "[\\/]+\z", "") & "\" ; Set all defaults If $s_mask = -1 Or $s_mask = Default Then $s_mask = "*.*" If $i_flag = -1 Or $i_flag = Default Then $i_flag = 0 If $s_exclude = -1 Or $s_exclude = Default Then $s_exclude = "" ; Look for bad chars If StringRegExp($s_mask, "[/:><\|]") Or StringRegExp($s_exclude, "[/:><\|]") Then Return SetError(2, 2, 0) EndIf ; Strip leading spaces between semi colon delimiter $s_mask = StringRegExpReplace($s_mask, "\s*;\s*", ";") If $s_exclude Then $s_exclude = StringRegExpReplace($s_exclude, "\s*;\s*", ";") ; Confirm mask has something in it If StringStripWS($s_mask, 8) = "" Then Return SetError(2, 2, 0) If $i_flag < 0 Or $i_flag > 2 Then Return SetError(3, 3, 0) ; Validate and create path + mask params Local $a_split = StringSplit($s_mask, ";"), $s_hold_split = "" For $i = 1 To $a_split[0] If StringStripWS($a_split[$i], 8) = "" Then ContinueLoop If StringRegExp($a_split[$i], "^\..*?\..*?\z") Then $a_split[$i] &= "*" & $a_split[$i] EndIf $s_hold_split &= '"' & $s_path & $a_split[$i] & '" ' Next $s_hold_split = StringTrimRight($s_hold_split, 1) If $s_hold_split = "" Then $s_hold_split = '"' & $s_path & '*.*"' Local $i_pid, $s_stdout, $s_hold_out, $s_dir_file_only = "", $s_recurse = "/s " If $i_flag = 1 Then $s_dir_file_only = ":-d" If $i_flag = 2 Then $s_dir_file_only = ":D" If Not $f_recurse Then $s_recurse = "" $command = @ComSpec & " /u /c dir /b " & $s_recurse & "/a" & $s_dir_file_only & " " & $s_hold_split $s_hold_out = _RunWaitStdOut($command, "", @SW_HIDE) ; ConsoleWrite($command & @crlf & $s_hold_out & @crlf & @extended & @crlf) $s_hold_out = StringRegExpReplace($s_hold_out, "\v+\z", "") If Not $s_hold_out Then Return SetError(4, 4, 0) ; Parse data and find matches based on flags Local $a_fsplit = StringSplit(StringStripCR($s_hold_out), @LF), $s_hold_ret $s_hold_out = "" If $s_exclude Then $s_exclude = StringReplace(StringReplace($s_exclude, "*", ".*?"), ";", "|") For $i = 1 To $a_fsplit[0] If $s_exclude And StringRegExp(StringRegExpReplace( _ $a_fsplit[$i], "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\Q" & $s_exclude & "\E") Then ContinueLoop If StringRegExp($a_fsplit[$i], "^\w:[\\/]+") = 0 Then $a_fsplit[$i] = $s_path & $a_fsplit[$i] If $f_full_path Then $s_hold_ret &= $a_fsplit[$i] & Chr(1) Else $s_hold_ret &= StringRegExpReplace($a_fsplit[$i], "((?:.*?[\\/]+)*)(.*?\z)", "$2") & Chr(1) EndIf Next $s_hold_ret = StringTrimRight($s_hold_ret, 1) If $s_hold_ret = "" Then Return SetError(5, 5, 0) Return StringSplit($s_hold_ret, Chr(1)) EndFunc ;==>_FileListToArrayEx ; ==================================================================================================== ; Execute a command and display the results ; ==================================================================================================== ; Paul Campbell (PaulIA), ProgAndy, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=76607&view=findpost&p=555091 Func _RunWaitStdOut($sCmd, $sWorkingDir = "", $state = @SW_SHOW) Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup Local $STILL_ACTIVE = 0x103 Local Const $STARTF_USESHOWWINDOW = 0x1 Local Const $STARTF_USESTDHANDLES = 0x100 ; Set up security attributes $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT _NamedPipes_CreatePipe($hReadPipe, $hWritePipe, $tSecurity) $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO_New) ;ConsoleWrite(DllStructGetSize($tStartup) & @crlf) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) DllStructSetData($tStartup, "ShowWindow", $state) _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, $sWorkingDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Local $handle = DllStructGetData($tProcess, "hProcess"), $exitCode _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) Do $exitCode = DllCall("kernel32.dll", "long", "GetExitCodeProcess", "hwnd", $handle, "dword*", 0) Until $exitCode[0] <> $STILL_ACTIVE $exitCode = $exitCode[2] ; Close the write end of the pipe before reading from the read end of the pipe _WinAPI_CloseHandle($handle) _WinAPI_CloseHandle($hWritePipe) ; Read data from the child process $tBuffer = DllStructCreate("wchar Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) While 1 _WinAPI_ReadFile($hReadPipe, $pBuffer, 4096, $iBytes) If $iBytes = 0 Then ExitLoop $sData &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes / 2) WEnd _WinAPI_CloseHandle($hReadPipe) SetExtended($exitCode) Return $sData EndFunc ;==>_RunWaitStdOut $tagSECURITY_ATTRIBUTES or $tagPROCESS_INFORMATION might be another reason why the function fails, but those look quite simple (and correct imho) compared to $tagSTARTUPINFO. Well, what's the difference between yours $tagSTARTUPINFO_New and original $tagSTARTUPINFO? There is absolutely nothing wrong with $tagSTARTUPINFO. That's not the reason your code doesn't work. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 Well, what's the difference between yours $tagSTARTUPINFO_New and original $tagSTARTUPINFO? There is absolutely nothing wrong with $tagSTARTUPINFO. That's not the reason your code doesn't work.No difference, it's a spoon-feed testing example. Well, you said ReadFile fails. Never experienced that that before on x64. My assumption is, that the CreateProcess somehow does not work as intended (pipe contains no data). Looking at the involved structures tagSTARTUPINFO seems to be the most complex, and additionally contains some definitions which I can not match to the MSDN documentation at the moment. So, where else to start? OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
trancexx Posted October 7, 2010 Share Posted October 7, 2010 (edited) No difference, it's a spoon-feed testing example. Well, you said ReadFile fails. Never experienced that that before on x64. My assumption is, that the CreateProcess somehow does not work as intended (pipe contains no data). Looking at the involved structures tagSTARTUPINFO seems to be the most complex, and additionally contains some definitions which I can not match to the MSDN documentation at the moment. So, where else to start?I didn't say ReadFile fails. I said your code fails there. Why? I don't know. Try making $hReadPipe not inheritable.http://msdn.microsoft.com/en-us/library/ms682499(v=VS.85).aspx Edited October 7, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Valik Posted October 7, 2010 Share Posted October 7, 2010 Any type definition that starts with "LP" is a pointer type. LPTSTR, LPSTR, LPWSTR are all pointers. Anyway, what's the point of this? The last time I checked AutoIt allowed STDIO redirection so why are you re-inventing the wheel? Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 (edited) I didn't say ReadFile fails. I said your code fails there. Why? I don't know. I know, that's why I was looking at the CreateProcess call.Try making $hReadPipe not inheritable.http://msdn.microsoft.com/en-us/library/ms682499(v=VS.85).aspxWill do so, thanks for the hint .Edit:Setting thisDllStructSetData($tSecurity, "InheritHandle", False)makes the function fail even on x86, no win there.Any type definition that starts with "LP" is a pointer type. LPTSTR, LPSTR, LPWSTR are all pointers.Thanks for the Info. Then it seems that the structure is correct, there has to be another reason why the function fails on x64.Anyway, what's the point of this? The last time I checked AutoIt allowed STDIO redirection so why are you re-inventing the wheel?Well, I took this statement "AutoIt doesn't support Unicode from the console" for granted, I think I tested it some time ago (not sure though). And I want the unicode STDOUT. Edited October 7, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Valik Posted October 7, 2010 Share Posted October 7, 2010 Facepalm. No, Picard Facepalm. AutoIt doesn't support it because the console doesn't support it. That should be rather obvious if you spent three seconds thinking about it since why would I arbitrarily limit a UNICODE application to ANSI if I didn't absolutely have to? Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 Because you didn't know of the undocumented cmd.exe /u switch? Give the example in the first post a try, works fine on x86... btw, I think I found a hint, might have to do with x64 redirection, CreateProcess says it can't find the file (cmd.exe)... OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Valik Posted October 7, 2010 Share Posted October 7, 2010 Because you didn't know of the undocumented cmd.exe /u switch?Terminology failure on my part. The API's don't support it. Okay, so cmd.exe has an undocumented option that sends UNICODE bytes through a byte stream on the off chance the program reading the stream knows to interpret it that way. Fair enough. Perhaps you should have said similar from the start.Not sure why this matters. Pretty sure file listing functions can be implemented natively in AutoIt. At least they could the last time I checked. Unless this is one of those silly "Let's jump through a bunch of hoops because AutoIt is too slow" type of things. Link to comment Share on other sites More sharing options...
trancexx Posted October 7, 2010 Share Posted October 7, 2010 (edited) btw, I think I found a hint, might have to do with x64 redirection, CreateProcess says it can't find the file (cmd.exe)... That's not it either. Your script from the above slightly modified to show that CreateProcess is ok:expandcollapse popup;#AutoIt3Wrapper_UseX64=n #include <NamedPipes.au3> #include <WinAPI.au3> ; Example Start #include <array.au3> ; for example only $timer = TimerInit() $aFiles = _FileListToArrayEx(@ProgramFilesDir, "*.*", 0, -1, True, True) ConsoleWrite(TimerDiff($timer) & @CRLF & $aFiles[0] & " files read" & @CRLF) ;_ArrayDisplay($aFiles) ; Example End Func _FileListToArrayEx($s_path, $s_mask = "*.*", $i_flag = 0, $s_exclude = -1, $f_recurse = False, $f_full_path = False) ; By mfecteau & Ascend4nt, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=33930&st=60&p=799369&#entry799369 If FileExists($s_path) = 0 Then Return SetError(1, 1, 0) ; Strip trailing backslash, and add one after to make sure there's only one $s_path = StringRegExpReplace($s_path, "[\\/]+\z", "") & "\" ; Set all defaults If $s_mask = -1 Or $s_mask = Default Then $s_mask = "*.*" If $i_flag = -1 Or $i_flag = Default Then $i_flag = 0 If $s_exclude = -1 Or $s_exclude = Default Then $s_exclude = "" ; Look for bad chars If StringRegExp($s_mask, "[/:><\|]") Or StringRegExp($s_exclude, "[/:><\|]") Then Return SetError(2, 2, 0) EndIf ; Strip leading spaces between semi colon delimiter $s_mask = StringRegExpReplace($s_mask, "\s*;\s*", ";") If $s_exclude Then $s_exclude = StringRegExpReplace($s_exclude, "\s*;\s*", ";") ; Confirm mask has something in it If StringStripWS($s_mask, 8) = "" Then Return SetError(2, 2, 0) If $i_flag < 0 Or $i_flag > 2 Then Return SetError(3, 3, 0) ; Validate and create path + mask params Local $a_split = StringSplit($s_mask, ";"), $s_hold_split = "" For $i = 1 To $a_split[0] If StringStripWS($a_split[$i], 8) = "" Then ContinueLoop If StringRegExp($a_split[$i], "^\..*?\..*?\z") Then $a_split[$i] &= "*" & $a_split[$i] EndIf $s_hold_split &= '"' & $s_path & $a_split[$i] & '" ' Next $s_hold_split = StringTrimRight($s_hold_split, 1) If $s_hold_split = "" Then $s_hold_split = '"' & $s_path & '*.*"' Local $i_pid, $s_stdout, $s_hold_out, $s_dir_file_only = "", $s_recurse = "/s " If $i_flag = 1 Then $s_dir_file_only = ":-d" If $i_flag = 2 Then $s_dir_file_only = ":D" If Not $f_recurse Then $s_recurse = "" $command = @ComSpec & " /u /c dir /b " & $s_recurse & "/a" & $s_dir_file_only & " " & $s_hold_split $s_hold_out = _RunWaitStdOut($command, "", @SW_HIDE) ; ConsoleWrite($command & @crlf & $s_hold_out & @crlf & @extended & @crlf) $s_hold_out = StringRegExpReplace($s_hold_out, "\v+\z", "") If Not $s_hold_out Then Return SetError(4, 4, 0) ; Parse data and find matches based on flags Local $a_fsplit = StringSplit(StringStripCR($s_hold_out), @LF), $s_hold_ret $s_hold_out = "" If $s_exclude Then $s_exclude = StringReplace(StringReplace($s_exclude, "*", ".*?"), ";", "|") For $i = 1 To $a_fsplit[0] If $s_exclude And StringRegExp(StringRegExpReplace( _ $a_fsplit[$i], "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\Q" & $s_exclude & "\E") Then ContinueLoop If StringRegExp($a_fsplit[$i], "^\w:[\\/]+") = 0 Then $a_fsplit[$i] = $s_path & $a_fsplit[$i] If $f_full_path Then $s_hold_ret &= $a_fsplit[$i] & Chr(1) Else $s_hold_ret &= StringRegExpReplace($a_fsplit[$i], "((?:.*?[\\/]+)*)(.*?\z)", "$2") & Chr(1) EndIf Next $s_hold_ret = StringTrimRight($s_hold_ret, 1) If $s_hold_ret = "" Then Return SetError(5, 5, 0) Return StringSplit($s_hold_ret, Chr(1)) EndFunc ;==>_FileListToArrayEx ; ==================================================================================================== ; Execute a command and display the results ; ==================================================================================================== ; Paul Campbell (PaulIA), ProgAndy, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=76607&view=findpost&p=555091 Func _RunWaitStdOut($sCmd, $sWorkingDir = "", $state = @SW_SHOW) Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup Local $STILL_ACTIVE = 0x103 Local Const $STARTF_USESHOWWINDOW = 0x1 Local Const $STARTF_USESTDHANDLES = 0x100 ; Set up security attributes $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT _NamedPipes_CreatePipe($hReadPipe, $hWritePipe, $tSecurity) $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) ;DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) ;<-!!! Here, to see DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) DllStructSetData($tStartup, "ShowWindow", $state) _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, $sWorkingDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Exit ; The End for this demo Local $handle = DllStructGetData($tProcess, "hProcess"), $exitCode _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) Do $exitCode = DllCall("kernel32.dll", "long", "GetExitCodeProcess", "hwnd", $handle, "dword*", 0) Until $exitCode[0] <> $STILL_ACTIVE $exitCode = $exitCode[2] ; Close the write end of the pipe before reading from the read end of the pipe _WinAPI_CloseHandle($handle) _WinAPI_CloseHandle($hWritePipe) ; Read data from the child process $tBuffer = DllStructCreate("wchar Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) While 1 _WinAPI_ReadFile($hReadPipe, $pBuffer, 4096, $iBytes) If $iBytes = 0 Then ExitLoop $sData &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes / 2) WEnd _WinAPI_CloseHandle($hReadPipe) SetExtended($exitCode) Return $sData EndFunc ;==>_RunWaitStdOut edit: since you didn't listen to me... let me fix it for you: expandcollapse popup;#AutoIt3Wrapper_UseX64=n #include <NamedPipes.au3> #include <WinAPI.au3> ; Example Start #include <array.au3> ; for example only $timer = TimerInit() $aFiles = _FileListToArrayEx(@ProgramFilesDir, "*.*", 0, -1, True, True) ConsoleWrite(TimerDiff($timer) & @CRLF & $aFiles[0] & " files read" & @CRLF) _ArrayDisplay($aFiles) ; Example End ;=============================================================================== ; ; Description: lists all or preferred files and or folders in a specified path (Similar to using Dir with the /B Switch) ; Syntax: _FileListToArrayEx($sPath, $sFilter = '*.*', $iFlag = 0, $sExclude = '') ; Parameter(s): $sPath = Path to generate filelist for ; $sFilter = The filter to use. Search the Autoit3 manual for the word "WildCards" For details, support now for multiple searches ; Example *.exe; *.txt will find all .exe and .txt files ; $iFlag = determines weather to return file or folders or both. ; $sExclude = exclude a file from the list by all or part of its name ; Example: Unins* will remove all files/folders that start with Unins ; $iFlag=0(Default) Return both files and folders ; $iFlag=1 Return files Only ; $iFlag=2 Return Folders Only ; ; Requirement(s): None ; Return Value(s): On Success - Returns an array containing the list of files and folders in the specified path ; On Failure - Returns the an empty string "" if no files are found and sets @Error on errors ; @Error or @extended = 1 Path not found or invalid ; @Error or @extended = 2 Invalid $sFilter or Invalid $sExclude ; @Error or @extended = 3 Invalid $iFlag ; @Error or @extended = 4 No File(s) Found ; ; Author(s): SmOke_N, modified by mfecteau, Ascend4nt & KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=33930&view=findpost&p=799369 ; Note(s): The array returned is one-dimensional and is made up as follows: ; $array[0] = Number of Files\Folders returned ; $array[1] = 1st File\Folder ; $array[2] = 2nd File\Folder ; $array[3] = 3rd File\Folder ; $array[n] = nth File\Folder ; ; All files are written to a "reserved" .tmp file (Thanks to gafrost) for the example ; The Reserved file is then read into an array, then deleted ;=============================================================================== Func _FileListToArrayEx($s_path, $s_mask = "*.*", $i_flag = 0, $s_exclude = -1, $f_recurse = False, $f_full_path = False) If FileExists($s_path) = 0 Then Return SetError(1, 1, 0) ; Strip trailing backslash, and add one after to make sure there's only one $s_path = StringRegExpReplace($s_path, "[\\/]+\z", "") & "\" ; Set all defaults If $s_mask = -1 Or $s_mask = Default Then $s_mask = "*.*" If $i_flag = -1 Or $i_flag = Default Then $i_flag = 0 If $s_exclude = -1 Or $s_exclude = Default Then $s_exclude = "" ; Look for bad chars If StringRegExp($s_mask, "[/:><\|]") Or StringRegExp($s_exclude, "[/:><\|]") Then Return SetError(2, 2, 0) EndIf ; Strip leading spaces between semi colon delimiter $s_mask = StringRegExpReplace($s_mask, "\s*;\s*", ";") If $s_exclude Then $s_exclude = StringRegExpReplace($s_exclude, "\s*;\s*", ";") ; Confirm mask has something in it If StringStripWS($s_mask, 8) = "" Then Return SetError(2, 2, 0) If $i_flag < 0 Or $i_flag > 2 Then Return SetError(3, 3, 0) ; Validate and create path + mask params Local $a_split = StringSplit($s_mask, ";"), $s_hold_split = "" For $i = 1 To $a_split[0] If StringStripWS($a_split[$i], 8) = "" Then ContinueLoop If StringRegExp($a_split[$i], "^\..*?\..*?\z") Then $a_split[$i] &= "*" & $a_split[$i] EndIf $s_hold_split &= '"' & $s_path & $a_split[$i] & '" ' Next $s_hold_split = StringTrimRight($s_hold_split, 1) If $s_hold_split = "" Then $s_hold_split = '"' & $s_path & '*.*"' Local $i_pid, $s_stdout, $s_hold_out, $s_dir_file_only = "", $s_recurse = "/s " If $i_flag = 1 Then $s_dir_file_only = ":-d" If $i_flag = 2 Then $s_dir_file_only = ":D" If Not $f_recurse Then $s_recurse = "" $command = @ComSpec & " /u /c dir /b " & $s_recurse & "/a" & $s_dir_file_only & " " & $s_hold_split $s_hold_out = _RunWaitStdOut($command, "", @SW_HIDE) ; ConsoleWrite($command & @crlf & $s_hold_out & @crlf & @extended & @crlf) $s_hold_out = StringRegExpReplace($s_hold_out, "\v+\z", "") If Not $s_hold_out Then Return SetError(4, 4, 0) ; Parse data and find matches based on flags Local $a_fsplit = StringSplit(StringStripCR($s_hold_out), @LF), $s_hold_ret $s_hold_out = "" If $s_exclude Then $s_exclude = StringReplace(StringReplace($s_exclude, "*", ".*?"), ";", "|") For $i = 1 To $a_fsplit[0] If $s_exclude And StringRegExp(StringRegExpReplace( _ $a_fsplit[$i], "(.*?[\\/]+)*(.*?\z)", "\2"), "(?i)\Q" & $s_exclude & "\E") Then ContinueLoop If StringRegExp($a_fsplit[$i], "^\w:[\\/]+") = 0 Then $a_fsplit[$i] = $s_path & $a_fsplit[$i] If $f_full_path Then $s_hold_ret &= $a_fsplit[$i] & Chr(1) Else $s_hold_ret &= StringRegExpReplace($a_fsplit[$i], "((?:.*?[\\/]+)*)(.*?\z)", "$2") & Chr(1) EndIf Next $s_hold_ret = StringTrimRight($s_hold_ret, 1) If $s_hold_ret = "" Then Return SetError(5, 5, 0) Return StringSplit($s_hold_ret, Chr(1)) EndFunc ;==>_FileListToArrayEx ; ==================================================================================================== ; Execute a command and display the results ; ==================================================================================================== ; Paul Campbell (PaulIA), ProgAndy, modified by KaFu ; http://www.autoitscript.com/forum/index.php?showtopic=76607&view=findpost&p=555091 Func _RunWaitStdOut($sCmd, $sWorkingDir = "", $state = @SW_SHOW) Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup Local $STILL_ACTIVE = 0x103 Local Const $STARTF_USESHOWWINDOW = 0x1 Local Const $STARTF_USESTDHANDLES = 0x100 ; Set up security attributes ;~ $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) ;~ DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) ;~ DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT _NamedPipes_CreatePipe($hReadPipe, $hWritePipe);, $tSecurity) ;************** _WinAPI_SetHandleInformation($hReadPipe, 1, 0) ; redundant in this new situation _WinAPI_SetHandleInformation($hWritePipe, 1, 1) ;************** ; Create child process $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) DllStructSetData($tStartup, "ShowWindow", $state) _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, $sWorkingDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Local $handle = DllStructGetData($tProcess, "hProcess"), $exitCode _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) Do $exitCode = DllCall("kernel32.dll", "long", "GetExitCodeProcess", "hwnd", $handle, "dword*", 0) Until $exitCode[0] <> $STILL_ACTIVE $exitCode = $exitCode[2] ; Close the write end of the pipe before reading from the read end of the pipe _WinAPI_CloseHandle($handle) _WinAPI_CloseHandle($hWritePipe) ; Read data from the child process $tBuffer = DllStructCreate("wchar Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) While 1 _WinAPI_ReadFile($hReadPipe, $pBuffer, 4096, $iBytes) If $iBytes = 0 Then ExitLoop $sData &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes / 2) WEnd _WinAPI_CloseHandle($hReadPipe) SetExtended($exitCode) Return $sData EndFunc ;==>_RunWaitStdOut Edited October 7, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Ascend4nt Posted October 7, 2010 Share Posted October 7, 2010 Just so everyone is clear, the '/u' switch is documented, and has been in effect since Windows 2000. If you need assistance in using it, here's the command-line help output:/U Causes the output of internal commands to a pipe or file to be Unicode My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code) Link to comment Share on other sites More sharing options...
KaFu Posted October 7, 2010 Author Share Posted October 7, 2010 (edited) since you didn't listen to me... let me fix it for youNice , thanks a lot, seems to work fine now ...Just so everyone is clear, the '/u' switch is documented, and has been in effect since Windows 2000.Upsa, overlooked that, good to know m8 Edited October 7, 2010 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) 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