Jump to content

Lecdev

Active Members
  • Posts

    26
  • Joined

  • Last visited

Recent Profile Visitors

283 profile views

Lecdev's Achievements

Seeker

Seeker (1/7)

3

Reputation

  1. I haven't tried this yet but the way I read on msdn it should basically be like this and shouldn't need much more? Func _ADO_Recordset_Open_New_Custom(ByRef $oActiveConnection, $sSQL_QueryStatement, $iCurType = 0, $iLockType = 1) Local Const $oADO_COMErrorHandler = ObjEvent("AutoIt.Error", __ADO_ComErrorHandler_WrapperFunction) If @error Then Return SetError($ADO_ERR_COMHANDLER, @error, $ADO_RET_FAILURE) #forceref $oADO_COMErrorHandler __ADO_Connection_IsReady($oActiveConnection) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) ElseIf Not IsString($sSQL_QueryStatement) Then Return SetError($ADO_ERR_INVALIDPARAMETERTYPE, $ADO_EXT_PARAM2, $ADO_RET_FAILURE) ElseIf $sSQL_QueryStatement = "" Then Return SetError($ADO_ERR_INVALIDPARAMETERVALUE, $ADO_EXT_PARAM2, $ADO_RET_FAILURE) EndIf Local $oRecordset = ObjCreate("ADODB.Recordset") If @error Then Return SetError($ADO_ERR_COMERROR, @error, $ADO_RET_FAILURE) $oRecordset.ActiveConnection = $oActiveConnection ; should be an already open active connection $oRecordset.DataSource = $sSQL_QueryStatement ; should be a query statement that returns data else the recordset will stay closed $oRecordset.CursorType = $iCurType ; from CursorTypeEnum (default 0 is forward-only) declare your custom cursor here, it cannot be done on an already open recordset $oRecordset.LockType = $iLockType ; from LockTypeEnum (default 1 is read-only) ; $oRecordset.Open ; Return SetError($ADO_ERR_SUCCESS, $ADO_EXT_DEFAULT, $oRecordset) ; sould return the recordset with the custom cursor? EndFunc
  2. mLipok I think in my opinion you are almost right. As far as I know mssql should always support bookmarks but not all data sources will and ado could be used for something else. maybe best method is to prefer bookmarks and use adBookmarkFirst but if its not supported to then check support for adMovePrevious and if that is ok you can use moveFirst, if neither are supported I think there is nothing more you can do except explicitly close the recordset before the next query. You have done this way with _ADO_Recordset_ToString but not in _ADO_Recordset_ToArray I found the truth table by the way it is here in the details for BOF, EOF properties. https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/bof-eof-properties-ado?view=sql-server-ver15
  3. I'm not so sure that removing the MoveFirst method support is correct, it shouldn't be adding records, it is supposed to throw an error if there is no data hence needing to check BOF and EOF first and shouldn't do anything more than set the internal pointer to the first already existing record in the recordset if it does contain a record. There is a truth table on msdn somewhere to show the results of the move methods in different circumstances I will try to find it. also in some deeper research on recordset clean up I have found these notes mentioned in msdn; " If You Explicitly Open It, Explicitly Close It: Pooling problems are frequently caused by an application that does not clean up its connections. Connections are placed in the pool at the time that the connection is closed and not before. To avoid this, always explicitly close an object you open. If you don't explicitly close it, chances are it won't ever be released to the pool. Even if the language you use has effective and reliable garbage collection, an instance of an open ADO Connection or Recordset object going out of scope does not equate to the Close method of that object being implicitly invoked. You must close it explicitly. Failing to close an open Connection or Recordset object is probably the single most frequent cause of connection creep and the single largest cause of incorrect diagnoses of pooling failure. " and details here: https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/close-method-ado?view=sql-server-ver15 suggesting that if you are leaving open the connection and re-using you should use the close method on the recordset before nulling the object var and also that closing the connection object doesn't close the command objects either, it does however close a recordset but it is common to leave connections open throughout several queries. it may be necessary to add the following for certain situations; Func _ADO_Recordset_Close(ByRef $oRecordset) Local Const $oADO_COMErrorHandler = ObjEvent("AutoIt.Error", __ADO_ComErrorHandler_WrapperFunction) If @error Then Return SetError($ADO_ERR_COMHANDLER, @error, $ADO_RET_FAILURE) #forceref $oADO_COMErrorHandler __ADO_Recordset_IsValid($oRecordset) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) $oRecordset.Close Return SetError($ADO_ERR_SUCCESS, $ADO_EXT_DEFAULT, $ADO_RET_SUCCESS) EndFunc ;==>_ADO_Recordset_Close Func _ADO_Command_Close(ByRef $oCommand) Local Const $oADO_COMErrorHandler = ObjEvent("AutoIt.Error", __ADO_ComErrorHandler_WrapperFunction) If @error Then Return SetError($ADO_ERR_COMHANDLER, @error, $ADO_RET_FAILURE) #forceref $oADO_COMErrorHandler __ADO_Command_IsValid($oCommand) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) $oCommand.Close Return SetError($ADO_ERR_SUCCESS, $ADO_EXT_DEFAULT, $ADO_RET_SUCCESS) EndFunc ;==>_ADO_Command_Close I also found that the execute method always returns a recordset with a forward only cursor so moveFirst likely doesn't work in the end. instead to do this you have to open your own recordset. https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/execute-method-ado-connection?view=sql-server-ver15#remarks You could use recordset.supports(adMovePrevious) to check if the recordset is forward only or check the recordset.CurserType property which may be able to change the type but not sure if this works on a read-only Recordset once already opened.
  4. Thanks mLipok I will try this soon. Hopefully my original example worked well enough to start with I wrote it at 4:30am without any sleep before posting, looks like your modal db is bigger than mine, maybe this is mssql engine version? i am using mssql 2019? 2mb works for me but looks like you need 5mb. For the above mentioned warning, without yet testing my best guess is that the recordset object Isn't cleaned up in the _ADO_Execute function when you use $bReturnAsArray = True and can't be cleaned up later because the object handle Isn't returned, instead the array is. I had noticed this in the UDF function so I avoided using it this way in my scripts because then I can always clean up the object. I thought it might be a risk of the recordset object being left open and ado perhaps returning the handle to the same object the next time which then maybe increments the size of the original recordset object and adds further field objects to that original. Rather than working out how to test this theory I just chose to always use $bReturnAsArray = false in my scripts, maybe you can try adding the clean up of the recordset object to the _ADO_Execute function if $bReturnAsArray is true before returning with the array and see if the problem persists? Thanks
  5. #include <ADO.au3> _ADO_ComErrorHandler_UserFunction(_ADO_COMErrorHandler_Function) _BLOB_Example() Func _BLOB_Example() _MSSQL_CreateDatabaseWithNameAndPath() _MSSQL_CreateBlobTable() Local $hFileOpened = FileOpen("SomePdf.pdf", 16) ; opened in $FO_BINARY mode Local $bFileData = FileRead($hFileOpened) ; whole file in binary FileClose($hFileOpened) _MSSQL_InsertFileBinary($bFileData) $bFileData = Null _MSSQL_ReadFileBinary($bFileData) $hFileOpened = FileOpen("SomePdfNewCopy.pdf", 26) ; opened in ($FO_BINARY, $FO_OVERWRITE, $FO_CREATEPATH) mode FileWrite($hFileOpened, $bFileData) If Not @Compiled Then ConsoleWrite("Done, Exiting in 2 Seconds") ; Sleep(2000) Exit ; EndFunc ;==>_BLOB_Example Func _MSSQL_CreateDatabaseWithNameAndPath($NewDbName = "Test_db", $DirectoryPath = @ScriptDir, $Server = "localhost\SQLEXPRESS", $User = "sa", $Pwd = "") If $NewDbName = "" Then Return SetError(-1, -2, $ADO_RET_FAILURE) If $DirectoryPath = "" Then Return SetError(-2, -2, $ADO_RET_FAILURE) ; note *** directories must exist first, use DirGetSize() to ensure the path exists then if not create with DirCreate() Local $sConnectionString = 'DRIVER={SQL Server};SERVER=' & $Server & ';DATABASE=master;UID=' & $User & ';PWD=' & $Pwd & ';' Local $commandstr = "select name from master.dbo.sysdatabases where name='" & $NewDbName & "'" Local $CreateNew = True ; Create connection object Local $oConnection = _ADO_Connection_Create() ; Open connection with $sConnectionString _ADO_Connection_OpenConString($oConnection, $sConnectionString) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) ; check if database exists already Local $oRecordset_Final = _ADO_Execute($oConnection, $commandstr) Local $aRowsResult = _ADO_Recordset_ToArray($oRecordset_Final) If IsArray($aRowsResult) Then Local $aRecordsetContent = _ADO_RecordsetArray_GetContent($aRowsResult) If IsArray($aRecordsetContent) Then If $aRecordsetContent[0][0] = $NewDbName Then $CreateNew = False ; already exists EndIf EndIf EndIf If $CreateNew Then ; doesnt exist, create it $commandstr = "CREATE DATABASE " & $NewDbName & " ON PRIMARY " & _ "( NAME = " & $NewDbName & ", " & _ "FILENAME = '" & $DirectoryPath & "\" & $NewDbName & ".mdf', " & _ "SIZE = 2MB, MAXSIZE = 100MB) " & _ "LOG ON (NAME = " & $NewDbName & "_log, " & _ " FILENAME = '" & $DirectoryPath & "\" & $NewDbName & "_log.ldf', " & _ " SIZE = 2MB, " & _ " MAXSIZE = 100MB )" Local $oCommand = _ADO_Command_Create($oConnection) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) Local $Result = _ADO_Command_Execute($oCommand, $commandstr) If @error Then Return SetError(@error, @extended, $ADO_RET_FAILURE) If Not @Compiled Then ConsoleWrite("succesfully created database !" & @CRLF) Else If Not @Compiled Then ConsoleWrite("database exists already ! No need to create !" & @CRLF) EndIf ; Clean Up $oRecordset_Final = Null _ADO_Connection_Close($oConnection) $oConnection = Null EndFunc ;==>_MSSQL_CreateDatabaseWithNameAndPath Func _MSSQL_CreateBlobTable($DbName = "Test_db", $Server = "localhost\SQLEXPRESS", $User = "sa", $Pwd = "") Local $sConnectionString = 'DRIVER={SQL Server};SERVER=' & $Server & ';DATABASE=' & $DbName & ';UID=' & $User & ';PWD=' & $Pwd & ';' Local $oConnection = _ADO_Connection_Create() _ADO_Connection_OpenConString($oConnection, $sConnectionString) Local $oRecordset_Tables = _ADO_OpenSchema_Tables($oConnection, $DbName, Default, "FILE_BIN_DATA") If @error >= $ADO_ERR_RECORDSETEMPTY Then _ADO_Execute($oConnection, "CREATE TABLE FILE_BIN_DATA (ROWID int IDENTITY(1,1) NOT NULL" & _ ", File_Name Varchar(60) NOT NULL" & _ ", File_Data Varbinary(max) NULL" & _ ", CONSTRAINT [PK_FILE_BIN_DATA] PRIMARY KEY CLUSTERED " & _ "(" & _ " ROWID ASC " & _ ")) " & _ "ON [PRIMARY]") If @error Then If Not @Compiled Then ConsoleWrite('! ---> @error=' & @error & ' @extended=' & @extended & ' : CREATE TABLE' & @CRLF) EndIf $oRecordset_Tables = _ADO_OpenSchema_Tables($oConnection, $DbName, Default, "FILE_BIN_DATA") EndIf If Not @Compiled Then ConsoleWrite(_ADO_Recordset_ToString($oRecordset_Tables)) ; Clean Up $oRecordset_Tables = Null _ADO_Connection_Close($oConnection) $oConnection = Null EndFunc ;==>_MSSQL_CreateBlobTable Func _MSSQL_InsertFileBinary(ByRef $bFileBinaryIn) ;; do some insert command/ stream EndFunc ;==>_MSSQL_InsertFileBinary Func _MSSQL_ReadFileBinary(ByRef $bFileBinaryOut) ; do some select command/ stream EndFunc ;==>_MSSQL_ReadFileBinary here is some code, looking forward to some help.
  6. Has anyone got any examples working with BLOBs ( Varbinary(max) ) on MSSQL with ADO? I've done with SQLite which is allot easier for this specifically and now i have a few things to migrate to sql server, my brain is melting.
  7. does anyone know what exactly TimerDiff() is doing with the integer returned by TimerInit() in order to get milliseconds? Just trying to find out if i can use the integer timerinit() returns in a slightly different way to the norm because it will save me a great deal of effort. ( hoping to save the integer in a db and query rows where the difference in current time integer is > x where x = whatever the integer needs to be to = y hours )
  8. I know this is pretty old now but i was trying to get comms accross local system, admin and limited users for months in windows 10 and was just not having any luck with anything at all. ended up finding this solution, CreateFileW kernel32 dll call to create the handle to write the message in mailslot.au3 had to be changed because it still worked between admin and another limited user as it was, but not from local system to any other user. had to change the file attributes to normal instead of the original flag $SECURITY_ANONYMOUS. see below only after this would the security attributes pointer used to create the mailslot actually take affect on the system account. Func _MailSlotWrite($sMailSlotName, $vData, $iMode = 0) Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _ "wstr", $sMailSlotName, _ "dword", 0x40000000, _ ; GENERIC_WRITE "dword", 1, _ ; FILE_SHARE_READ "ptr", 0, _ ; lp security attributes (ignored on open existing) "dword", 3, _ ; OPEN_EXISTING "dword", 128, _ ; 0, _ ; SECURITY_ANONYMOUS replaced with file attribute normal 128 "ptr", 0) ; ......... above now works when creating the mailslot with a security pointer which i have used permissions.au3 udf to create, shown below. #include "MailSlot.au3" #include <Permissions.au3> Global Const $sMailSlotName = "\\.\mailslot\SampleCrossSessonMailslot" Global $ptrSecurityDescriptor = _ConvertStringSecurityDescriptorToSecurityDescriptor("O:BAD:(A;OICI;GRGW;;;AU)(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)") If @error Then Global $aError = DllCall("kernel32.dll", "dword", "GetLastError") if not @Compiled Then ConsoleWrite("err: " & $aError[0] & @CR) EndIf Global $tSecurityAttributes = DllStructCreate("dword Length;ptr Descriptor;bool InheritHandle") DllStructSetData($tSecurityAttributes, 1, DllStructGetSize($tSecurityAttributes)) DllStructSetData($tSecurityAttributes, 2, DllStructGetPtr($ptrSecurityDescriptor)) DllStructSetData($tSecurityAttributes, 3, 0) ; InheritHandle = FALSE Global $hMailSlot = _MailSlotCreate($sMailSlotName,0,0,$tSecurityAttributes) hopefully this saves someone else from banging their head against the wall.
  9. well part of the point is to replace the curser with the icon temporarily and unfortunately if you set the curser to id 16 to hide it _ispressed(01) or 02 dont work anymore. but I can do a bit of a hybrid below; Still no idea why the empty string doesnt disable the event function on GUISetOnEvent($GUI_EVENT_MOUSEMOVE ,"") though, thats a bit strange. #NoTrayIcon #include <Misc.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Opt("GUIOnEventMode", 1) Opt("MouseCoordMode", 2) ;1=absolute, 0=relative, 2=client ( final application will need to be absolute (default) ) #Region ### START Koda GUI section ### Form= Global $Form1 = GUICreate("Form1", @DesktopWidth / 2, @DesktopHeight / 2) GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close") Global $Icon1 = GUICtrlCreateIcon(@ProgramFilesDir & "\AutoIt3\Icons\MyAutoIt3_Yellow.ico", -1, 5, 5, 32, 32) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Global $EscapeDropIcon = 0, $IconCenterLeft, $IconCenterTop, $CursorInfo While 1 $CursorInfo = GUIGetCursorInfo($Form1) $WinCoords = WinGetPos($Form1) If $CursorInfo[4] = $Icon1 Then If _IsPressed(01) Then Icon1Click() EndIf If _IsPressed(02) Then GUICtrlSetPos($Icon1, 5, 5, 32, 32) EndIf EndIf Sleep(75) WEnd Func Icon1Click() GUICtrlSetCursor($Icon1, 16) GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "_IconPasteAtPosition") GUISetOnEvent($GUI_EVENT_SECONDARYDOWN, "_EscapeFollow") $EscapeDropIcon = 0 Local $TempCurserX, $TempCurserY Do $TempCurserX = MouseGetPos(0) - 16 $TempCurserY = MouseGetPos(1) - 16 If ($TempCurserX <> $IconCenterLeft) Or ($TempCurserY <> $IconCenterTop) Then $IconCenterLeft = $TempCurserX $IconCenterTop = $TempCurserY GUICtrlSetPos($Icon1, $IconCenterLeft, $IconCenterTop, 32, 32) EndIf Sleep(15) Until $EscapeDropIcon GUICtrlSetPos($Icon1, 5, 5, 32, 32) GUICtrlSetCursor($Icon1, -1) EndFunc ;==>Icon1Click Func Form1Close() Exit EndFunc ;==>Form1Close Func _IconPasteAtPosition() If Not $EscapeDropIcon Then GUICtrlCreateIcon(@ProgramFilesDir & "\AutoIt3\Icons\MyAutoIt3_Yellow.ico", -1, $IconCenterLeft, $IconCenterTop, 32, 32) GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "") GUISetOnEvent($GUI_EVENT_SECONDARYDOWN, "") $EscapeDropIcon = 1 EndIf EndFunc ;==>_IconPasteAtPosition Func _EscapeFollow() GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "") GUISetOnEvent($GUI_EVENT_SECONDARYDOWN, "") $EscapeDropIcon = 1 EndFunc ;==>_EscapeFollow
  10. In the sample change lines 53 and 63 from GUISetOnEvent($GUI_EVENT_MOUSEMOVE, "DoNothing") to GUISetOnEvent($GUI_EVENT_MOUSEMOVE, "") as it should be in order to disable the user defined on event function as per autoit help file and you should see it doesnt actually disable the function and the icon never stops following the mouse. (provided the script behaves the same on your pc as it does mine) I dont want the script to be calling a function forever everytime the mouse moves because its just undue stress on cpu usage, i would prefer to disable the on event function when its not needed the same way you can with other special event IDs.
  11. Can anyone tell me the default parameter to input into, GUISetOnEvent($GUI_EVENT_MOUSEMOVE, "") to disable a previously set user defined function? help file example says empty string ("") which works for other events but doesnt seem to on mouse move. Ive attached some of my test code to select icon by clicking and click on screen where needed to create an icon the same or cancel by right clicking and then escape the window with the keyboard escape key. best solution i have come up with after a few hours of trying different things is to create a DoNothing() function any help would be appreciated. dummy2.au3
  12. yeah i thought as much but i also thought if i did it from scratch myself it would be an endeavor of which the end would not be reached before the time i need something running unless its already been solved by someone.
  13. could this be extended to utilize the setsockopt winsock function to add to multicast groups and enable sending multicast packets? I'd be very interested in that.
  14. Ive spent a few hours reading threads dating back years to do with udp multicast. none of them seem to have ever been resolved. am i wasting my time trying to find a working solution to bind and use udp multicast addresses for example 239.xyz.xyz.xyz on a network to communicate to and from scripts on diferent computers using autoit? its a real bummer if its not possible.
  15. Has anyone worked out how to add an attachment to an email using a mail udf like _INetSmtpMail or similar? or even a library? I have a script that generates an automated pdf report and need to add in automated emailing of the report, I'm hoping this isn't too difficult it doesn't seem that far fetched of a task but I haven't been able to find any info on how exactly to do it with autoit... Edit: Dont worry I found this now. https://www.autoitscript.com/forum/topic/167292-smtp-mailer-udf/
×
×
  • Create New...