64bit -> 32bit Problem bei Zugriff auf externe SysListview? Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Frosti
Posts: 353
Joined: 27 Oct 2017, 14:30
GitHub: Ixiko

64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by Frosti » 02 Aug 2020, 11:02

Ich habe die LV_ExtListview Bibliothek von cyrus benutzt um im Druckdialog von Sumatra Zugriff auf das SysListview321-Steuerlement zu erhalten.
Das funktioniert soweit gut, solange ich eine 32bit Variante einer Autohotkey.exe (AHK-L in meinem Fall AHK-H) verwende. Ansonsten wird der Fehlercode: 87 ausgeworfen (ERROR_INVALID_PARAMETER - The parameter is incorrect).
Die Bibliothek kann lt. Beschreibung mit 32/64bit ANSI oder Unicode umgehen. Achtung in meinem Fall habe ich die Zeile NumPut( (bSelect) ? 0x0003 : 0x0000, LVITEM, 12, "UInt" ) geändert (focused and selected).

Code: Select all

Error in #include file "M:\Praxis\Skripte\Skripte Neu\Addendum für AlbisOnWindows\lib\LV_ExtListView.ahk":
     objLV.pwritebuf: error writing memory

Specifically: LastError: 87

	Line#
	092: VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )  
	093: NumPut( 0x0008,                        LVITEM, 0, 	"UInt")  
	094: NumPut( nItem,                         LVITEM, 4, 	"Int" )  
	095: NumPut( 0,                             LVITEM, 8, 	"Int" )  
	096: NumPut( (bSelect) ? 0x0003 : 0x0000,	LVITEM, 12, "UInt")  
	097: NumPut( 0x0003,                        LVITEM, 16, "UInt")  
	099: if ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf, UInt,0 ) )  
--->	100: Throw,Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
	101: SendMessage,0x102B,nItem,objLV.pwritebuf,,"ahk_id " objLV.hlv
	103: Return,ErrorLevel
	104: }
	106: {
	111: PROCESS_ALL_ACCESS := 0x001F0FFF
	112: INVALID_HANDLE_VALUE := 0xFFFFFFFF
	113: PAGE_READWRITE := 4

The current thread will exit.
Für's Testen mein Code (Druckdialog muss geöffnet sein!).

Code: Select all

SetTitleMatchMode, RegEx        

sumatraprint := "i)[(Print)|(Drucken)] ahk_class i)#32770 ahk_exe i)SumatraPDF.exe"
StandardA4 := "Microsoft Print to PDF"

rxPrinter:= StrReplace(Trim(StandardA4), " ", "\s")
rxPrinter:= StrReplace(rxPrinter, "(", "\(")
rxPrinter:= StrReplace(rxPrinter, ")", "\)")

hSumatra := WinExist("ahk_class SUMATRA_PDF_FRAME")
hSumatraprint  	:= GetHex(WinExist(sumatraprint))                          
; Handle der SysListview321 (Druckerliste)  
ControlGet, hLV, Hwnd,, SysListview321, % "ahk_id " hSumatraprint   
; Auslesen der vorhandenen Drucker
ControlGet, Items	, List  , Col1 	,, % "ahk_id " hLV                      

  
; Listview Position des Standarddrucker suchen
ItemNr := 0                                                   
Loop, Parse, Items, `n                                                                      
    If RegExMatch(A_LoopField, "i)" rxPrinter) {                                  
        ItemNr := A_Index                                                                  
        break
    }

 ; Drucker in der externen Listview auswählen
If ItemNr {                                                                                       
     objLV := ExtListView_Initialize(sumatraprint)
     ControlFocus,, % "ahk_id " objLV.hlv
     err := ExtListView_ToggleSelection(objLV, 1, ItemNr - 1)
     ExtListView_DeInitialize(objLV)
}
else {                                                                                               
	MsgBox, % "Drucker: " StandardA4 "`nkonnte nicht gefunden werden."
}
Ich hoffe jemand kann mir da weiterhelfen.
Anmerkung:
Ich kann das Dokument nicht per cli-Aufruf ausdrucken, da die Dokumente in meiner Verwaltungssoftware hinterlegt sind. Die Software startet je nach Arbeitsplatzeinstellung entweder Sumatra oder der FoxitReader.
Sinn des Ganzen ist ein automatisierter Druck eines Dokumentes. Das bietet meine Software leider nicht.

just me
Posts: 7291
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by just me » 03 Aug 2020, 05:30

Moin Frosti,

da kann da wirklich Probleme geben. Mir kommen schon mal die reservierten Speichergrößen für LVITEM spanisch vor.

Code: Select all

typedef struct tagLVITEMA {
  UINT   mask;
  int    iItem;
  int    iSubItem;
  UINT   state;
  UINT   stateMask;
  LPSTR  pszText;
  int    cchTextMax;
  int    iImage;
  LPARAM lParam;
  int    iIndent;
  int    iGroupId;
  UINT   cColumns;
  PUINT  puColumns;
  int    *piColFmt;
  int    iGroup;
} LVITEMA, *LPLVITEMA;
Die 28 Bytes für 32-Bit und 36 Bytes für 64-Bit reichen man gerade bis zum Element cchTextMax.

Ist das der erste Zugriff auf ListView-Elemente?
Kannst Du Dir mal die Werte in objLV.pwritebuf bzw. objLV.preadbuf ausgeben lassen?

User avatar
Frosti
Posts: 353
Joined: 27 Oct 2017, 14:30
GitHub: Ixiko

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by Frosti » 03 Aug 2020, 12:18

Oh, ich habe nicht die richtige Quelle in den Link gelegt. Die Bibliothek habe ich aus einem Post aus dem Forum ----> hier.

Code: Select all

64bit
pwritebuf: 	-505741312 (0xffffffffe1db0000)
preadbuf: 	-504496128 (0xffffffffe1ee0000)

32bit
pwritebuf:	531759104 (0x1fb20000)
preadbuf: 	531824640 (0x1fb30000)
Die Zahlen verschieben sich mit jedem Aufruf jeweils um 0x1000. Wird da irgendwas nicht geschlossen?

just me
Posts: 7291
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by just me » 04 Aug 2020, 03:29

Moin,

mit 64 Bit liefert Dein Beispiel negative Pointer. Ich glaube nicht, dass damit weiter gearbeitet werden kann.

Es kann daran liegen, dass der Standardrückgabewert bei DllCall() ein 32-Bit Integerwert ist (das Vorzeichenbit wird geprüft). Versuch mal, __ExtListView_AllocateMemory() wie folgt zu ändern:

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
    ; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
    If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
                                                       , UInt,0x4, "UPtr" )) ) ; <<<<<<<<<<
        Return 0
    If ( !(objLV.preadbuf  := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf,  UInt,0x1000
                                                       , UInt,0x4, "UPtr" )) ) ; <<<<<<<<<<
        Return 0
    Return 1
}


User avatar
Frosti
Posts: 353
Joined: 27 Oct 2017, 14:30
GitHub: Ixiko

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by Frosti » 04 Aug 2020, 13:39

Das Kribbeln im Bauch ob es funktioniert. Unvergleichlich! Danke!
Last edited by Frosti on 05 Aug 2020, 05:56, edited 1 time in total.

just me
Posts: 7291
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by just me » 05 Aug 2020, 03:46

Moin, freut mich!

Noch ein Hinweis: Wenn Du noch andere Sachen mit externen ListViews veranstalten willst, musst Du beachten, dass 32-Bit Anwendung die Strukturen wie z.B. LVITEM immer im 32-Bit Format erwarten und auch befüllen.

User avatar
Frosti
Posts: 353
Joined: 27 Oct 2017, 14:30
GitHub: Ixiko

Re: 64bit -> 32bit Problem bei Zugriff auf externe SysListview?

Post by Frosti » 05 Aug 2020, 06:00

Da ich in diesem Fall nicht an den Text(String) wollte, war mir schnell klar das ich bei LVITEM die Lösung nicht finde werde. Meine nächste Idee ist das Verschieben von Einträgen in einer 32bit Listview. Da werde ich Deinen Tip wahrscheinlich brauchen. Danke.

Post Reply

Return to “Ich brauche Hilfe”