Exclusive file locking - SOLVED

4 posts in this topic

#1 ·  Posted (edited)

I've run into the problem where multiple script processes writing to a log file at the same time can interfere with one another. That is, file writes using FileWriteLine are not atomic, so a line of text from one process can have fragments of text from other processes mixed in with it. Exclusive file-locking should take care of the problem.

Looking through the standard UDFs, I see that _WinAPI_LockFile is available, but according to the MSDN documentation it doesn't block - it returns immediately if the lock can't be obtained - and there doesn't seem to be a UDF for the LockFileEx function. I considered writing my own UDF for LockFileEx, but some aspects (e.g., creating the OVERLAPPED structure and its members) look too complex for the amount of time I have available. I think approximating LockFileEx using LockFile could solve my problem, but I'd like to keep it simple while still working reliably. I'm not confident that (e.g.) a simple retry loop to simulate blocking will be adequate.

Any suggestions for a simple way to achieve exclusive file-locking with blocking?

Edited by tremolux66
Mark problem as solved

Share this post

Link to post
Share on other sites

this is what you're looking for:

i have used it successfully in a very much similar scenario to yours.

Share this post

Link to post
Share on other sites

#3 ·  Posted (edited)

Thanks, I'll  give that a try!

Edited by tremolux66

Share this post

Link to post
Share on other sites

Works great - problem solved! All the log messages are stored perfectly. :)

Share this post

Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • usmiv4o
      By usmiv4o
      #cs ---------------------------------------------------------------------------- AutoIt Version: Author: usmiv4o Script Function: AutoIt script to check if files in directory are changed. It is usefull for security contra-inteligense measures. Function Name: LoadTripwireDB() Description: Loads database (text file tripwire.txt) and compare files in /test folder for changes. compares Hash (MD5) checksums. If they are not the same starts Initial() Function Name: Initial() Description: Checks directory and makes index of files and their MD5 checksums in text file (tripwire.txt) Function Name: Hush() Description: Checks file and returns its MD5 checksum. Requirement(s): Windows XP Return Value(s): On Success - Returns true. Files are the same as before. On Failure - return false. Example: LoadTripwireDB() #ce ---------------------------------------------------------------------------- #include <Crypt.au3> #include <File.au3> #include <Array.au3> $sDir = @ScriptDir & "\Test" $sFilePath = @ScriptDir & "\tripwire.txt" Func Hush(ByRef $sFile) $sRead = FileOpen( $sFile) $dHash = _Crypt_HashData($sRead, $CALG_MD5) ; Create a hash of the text entered. ConsoleWrite("Hash of file " & $sFile & " is " & $dHash & @CRLF) EndFunc ;ConsoleWrite("Files in Dir are " & $aScriptDir[0] & @CRLF) ;$sFilePath = @ScriptDir & "\Examples.txt" ;_FileWriteFromArray($sFilePath, $aScriptDir, 1) ;_ArrayDisplay($aScriptDir, "1D display") Func Initial() $aScriptDir = _FileListToArray($sDir) for $i = 1 To UBound($aScriptDir) - 1 $dHash = _Crypt_HashData($i, $CALG_MD5) ;ConsoleWrite("File " & $aScriptDir[$i] & " is " & $dHash & @CRLF) ConsoleWrite($aScriptDir[$i] & ":" & $dHash & @CRLF) ;Hush($aScriptDir[$i]) ;FileWrite $hFileOpen = FileOpen($sFilePath, $FO_APPEND) If $hFileOpen = -1 Then MsgBox($MB_SYSTEMMODAL, "", "An error occurred when reading the file.") EndIf FileWrite($hFileOpen, $aScriptDir[$i] & ":" & $dHash & @CRLF) Next EndFunc Func Monitor() $aScriptDir = _FileListToArray($sDir) for $i = 1 To UBound($aScriptDir) - 1 Next EndFunc Func LoadTripwireDB() $comparison_ok = false $dArray = _FileListToArray($sDir) ;directory $dArray0 = UBound($dArray) - 1 $fArray = FileReadToArray($sFilePath) ;file $fArray0 = UBound($fArray) ;_ArrayDisplay($dArray, "files array") if $dArray0 = $fArray0 Then ; are file same as recorded in txt file? ;ConsoleWrite("files in monitoring dir: " & $dArray[0] & " = file recorded: " & $fArray0 & @CRLF & $fArray[0]& @CRLF) for $i = 1 To UBound($dArray) - 1 ;ConsoleWrite("i = " & $i & @CRLF) $dHash = _Crypt_HashData($i, $CALG_MD5) ;binary ;$dHash = BinaryToString($dHash) $ffhash = StringSplit( $fArray[$i-1],":") $fhash = $ffhash[2] ;ConsoleWrite("IsBinary $dHash " & IsBinary($dHash) & @CRLF) if $dHash = $fhash Then ;if compared hashes are equal ;ConsoleWrite($fhash & ":" & $dHash & " equal" & @CRLF) ;ConsoleWrite("File: " & $fhash & @CRLF & "Directory: " & $dHash & @CRLF & "equal: yes " & @CRLF) Else ;if compared hashes are not equal ;ConsoleWrite("File: " & $fhash & @CRLF & "Directory: " & $dHash & @CRLF & "equal: not " & @CRLF) ;MsgBox(0,"hash md5",$fhash & ":" & $dHash & " not equal") EndIf Next ;ConsoleWrite("hashes are equal" & @CRLF) $comparison_ok = true Else ConsoleWrite("number of files in monitoring dir are not same as recorded" & @CRLF) ConsoleWrite("directory: " & $dArray[0] &":"& "files: " & UBound($fArray) - 1 & @CRLF) EndIf Return $comparison_ok EndFunc #main if LoadTripwireDB() = true Then ConsoleWrite(" hashes are equal " & @CRLF) ElseIf LoadTripwireDB() <> true Then ConsoleWrite(" hashes are not equal " & @CRLF) ConsoleWrite(" hashes are not equal " & @CRLF) Initial() EndIf  
    • nhardel
      By nhardel
      So I have been bashing my head in for a couple days and have searched both AutoIT forums and Thwack Forums for an answer.  I understand this could be hard to help sense I can't provide a server for someone to help me test against.  I am trying to use the WinHTTP.au3 to connect with Solarwinds Orion SDK thru REST/JSON api calls.  Here is the documentation that they provide.
      I have been trying just to make a basic connection but for some reason cannot get past the authorization process with WinHTTP.  Here is my test code.
      #Region Includes #include <log4a.au3> #include "WinHttp.au3" #EndRegion Global $sAddress = "https://usandl0213:17778/SolarWinds/InformationService/v3/Json/Query?query=SELECT+NodeID+FROM+Orion.NODES" Global $array_URL = _WinHttpCrackUrl($sAddress) ;~ Row|Col 0 ;~ [0]|https ;~ [1]|2 ;~ [2]|usandl0213 ;~ [3]|17778 ;~ [4]| ;~ [5]| ;~ [6]|/SolarWinds/InformationService/v3/Json/Query ;~ [7]|?query=SELECT+NodeID+FROM+Orion.NODES Global $hOpen = _winhttpOpen() If @error Then _log4a_Fatal("Error intializing the usage of WinHTTP functions") Exit 1 EndIf Global $hConnect = _winhttpConnect($hOpen, $array_URL[2]) If @error Then _log4a_Fatal("Error specifying the initial target server of an HTTP request.") _WinHttpCloseHandle($hOpen) Exit 2 EndIf Global $hRequest = _WinHttpOpenRequest($hConnect, _ "GET", _ "/SolarWinds/InformationService/v3/Json/Query?query=SELECT+NodeID+FROM+Orion.NODES", _ "HTTP/1.1") If @error Then _log4a_Fatal(MsgBox(48, "Error", "Error creating an HTTP request handle.") _WinHttpCloseHandle($hConnect) _WinHttpCloseHandle($hOpen) Exit 3 EndIf _WinHttpAddRequestHeaders($hRequest, "Authorization: Basic YXV0b2l0X2xvZ2luOnRlc3Q=") _WinHttpAddRequestHeaders($hRequest, "User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3") _WinHttpAddRequestHeaders($hRequest, "Host: usandl0213:17778") _WinHttpAddRequestHeaders($hRequest, "Accept: */*") _WinHttpSendRequest($hRequest) If @error Then MsgBox(48, "Error", "Error sending specified request.") Close_request() Exit 4 EndIf ; Wait for the response _WinHttpReceiveResponse($hRequest) If @error Then MsgBox(48, "Error", "Error waiting for the response from the server.") Close_request() Exit 5 EndIf Global $sChunk, $sData ; See what's returned If _WinHttpQueryDataAvailable($hRequest) Then Global $sHeader = _WinHttpQueryHeaders($hRequest) ;~ ConsoleWrite(@crlf) ConsoleWrite($sHeader & @CRLF) ; Read While 1 $sChunk = _WinHttpReadData($hRequest) If @error Then ExitLoop $sData &= $sChunk WEnd ConsoleWrite($sData & @CRLF) ; print to console Else MsgBox(48, "Error", "Site is experiencing problems.") EndIf Close_request() Func Close_request() ; Close open handles and exit _WinHttpCloseHandle($hRequest) _WinHttpCloseHandle($hConnect) _WinHttpCloseHandle($hOpen) EndFunc I am definitely connecting to the server but get a 401 Unauthorized response.  Output of above script:
      HTTP/1.1 401 Unauthorized Cache-Control: private Date: Thu, 27 Jul 2017 15:31:21 GMT Content-Length: 1668 Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.5 Set-Cookie: ASP.NET_SessionId=lgwin2qsbbrip2mxg01fot05; path=/; HttpOnly Set-Cookie: TestCookieSupport=Supported; path=/ Set-Cookie: Orion_IsSessionExp=TRUE; expires=Thu, 27-Jul-2017 17:31:21 GMT; path=/ WWW-Authenticate: Negotiate WWW-Authenticate: NTLM X-UA-Compatible: IE=9 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET X-Same-Domain: 1 X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Body:
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""> <html xmlns=""> <head><link rel="stylesheet" type="text/css" href="/orion/js/jquery-1.7.1/jquery-ui.css.i18n.ashx?l=en-US&v=42660.90.L&csd=%23b0b9c5;%23d2ddec;%2392add1;" /> <link rel="stylesheet" type="text/css" href="/orion/styles/orionminreqs.css.i18n.ashx?l=en-US&v=42660.90.L&csd=%23b0b9c5;%23d2ddec;%2392add1;" /> <link rel="stylesheet" type="text/css" href="/webengine/resources/steelblue.css.i18n.ashx?l=en-US&v=42660.90.L&csd=%23b0b9c5;%23d2ddec;%2392add1;" /> <link rel="stylesheet" type="text/css" href="/orion/ipam/res/css/sw-events.css.i18n.ashx?l=en-US&v=42660.90.L&csd=%23b0b9c5;%23d2ddec;%2392add1;" /> <script type="text/javascript" src="/orion/js/orionminreqs.js.i18n.ashx?l=en-US&v=42660.90.L"></script> <script type="text/javascript" src="/orion/js/modernizr/modernizr-2.5.3.js.i18n.ashx?l=en-US&v=42660.90.L"></script> <script type="text/javascript" src="/orion/js/jquery-1.7.1/jquery-1.7.1.framework.min.js.i18n.ashx?l=en-US&v=42660.90.L"></script> <script type="text/javascript">(function(){var de=$(document.documentElement); de.addClass('sw-is-locale-en'); $.each(jQuery.browser,function(k,v){if(v===true){ de.addClass('sw-is-'+k); de.addClass('sw-is-'+k+'-'+parseInt(jQuery.browser.version)); }}); })();</script> <script type="text/javascript">SW.Core.Loader._cbLoaded('jquery');</script> <script type="text/javascript">SW.Core.Date._init(0,-14400000);</script> <title> </title></head> <body> <script> window.location = 'Login.aspx'; </script> </body> </html> To me this looks like it if it is still looking for my credentials.   I did verify that things work as expected using Chrome and REST test client.  I do get certificate errors in IE if I try to go directly.  Bypass certificate issues and page will try to save out to .json file
      Looking for any help.
    • mLipok
      By mLipok
      Recently I was working on TeamVierwer API .
      I had a little break, and wanted to check out another platform.
      Here is the result of my attempt:
      #include "GHAPI.au3" _GHAPI_AccessToken('') _GHAPI_GetUser("users/mLipok") _GHAPI_GetUserOrganizations("users/mLipok") _GHAPI_RootEndpoints() and GHAPI.au3
      #include-once #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7 #Tidy_Parameters=/sort_funcs /reel #Region GHAPI.au3 - Header ; #INDEX# ======================================================================================================================= ; Title .........: GHAPI UDF ; AutoIt Version : ; Language ......: English ; Description ...: This is an UDF for for communicate with via GitHub RESTful API ; Author(s) .....: mLipok ; Modified ......: ; =============================================================================================================================== #cs Title: GHAPI UDF Filename: GHAPI.au3 Description: This is an UDF for for communicate with via GitHub RESTful API Author: mLipok Modified: Last Update: 2017/05/23 Requirements: AutoIt or higher #ce #EndRegion GHAPI.au3 - Header #Region GHAPI.au3 - Include #include <array.au3> #include <FileConstants.au3> #include <MsgBoxConstants.au3> #EndRegion GHAPI.au3 - Include #Region GHAPI.au3 - Declarations Global $oErrorHandler = ObjEvent("AutoIt.Error", "_GHAPI_ErrFunc") Global $__g_sGitHubAPI_BaseUrl = "" ; URL of the GitHub API Global $__g_sGitHubAPI_Version = "v3" ; Put the current API version in here Global Enum _ $GHAPI_ERR_SUCCESS, _ $GHAPI_ERR_GENERAL, _ $GHAPI_ERR_COMERROR, _ $GHAPI_ERR_STATUS, _ $GHAPI_ERR_COUNTER Global Enum _ $GHAPI_EXT_DEFAULT, _ $GHAPI_EXT_PARAM1, _ $GHAPI_EXT_PARAM2, _ $GHAPI_EXT_PARAM3, _ $GHAPI_EXT_COUNTER Global Enum _ $GHAPI_RET_SUCCESS, _ $GHAPI_RET_FAILURE, _ $GHAPI_RET_COUNTER #EndRegion GHAPI.au3 - Declarations #Region GHAPI.au3 - API Functions Func _GHAPI_ErrFunc($oError) ; Do anything here. ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_GHAPI_ErrFunc Func _GHAPI_AccessToken($sParam = Default) ; ; Local Static $sAccessToken = '' If $sParam <> Default Then $sAccessToken = $sParam Return $sAccessToken EndFunc ;==>_GHAPI_AccessToken Func _GHAPI_GetUser($sUser) Local $oHTTP = __GHAPI_HTTP_Open("GET", $sUser) Local $oJSON = __GHAPI_HTTP_Send($oHTTP) If @error Then Return SetError(@error, @extended, False) #forceref $oJSON EndFunc ;==>_GHAPI_GetUser Func _GHAPI_GetUserOrganizations($sUser) Local $oHTTP = __GHAPI_HTTP_Open("GET", $sUser & '/orgs') Local $oJSON = __GHAPI_HTTP_Send($oHTTP) If @error Then Return SetError(@error, @extended, False) #forceref $oJSON EndFunc ;==>_GHAPI_GetUserOrganizations Func _GHAPI_RootEndpoints() Local $oHTTP = __GHAPI_HTTP_Open("GET", '') Local $oJSON = __GHAPI_HTTP_Send($oHTTP) If @error Then Return SetError(@error, @extended, False) #forceref $oJSON EndFunc ;==>_GHAPI_RootEndpoints #EndRegion GHAPI.au3 - API Functions #Region GHAPI.au3 - INTERNAL Functions Func __GHAPI_HTTP_Open($sMethod, $sCommand, $sURLParameters = '') Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") Local $sURL = $__g_sGitHubAPI_BaseUrl & "/" & $sCommand & $sURLParameters ;~ __GHAPI_DebugOut("> $sURL=" & $sURL & @CRLF) $oHTTP.Open($sMethod, $sURL, False) If @error Then Return SetError(@error, @extended, Null) $oHTTP.setRequestHeader("Authorization", "Bearer " & _GHAPI_AccessToken()) ; Accept: application/vnd.github.v3+json $oHTTP.setRequestHeader("Accept", "application/vnd.github." & $__g_sGitHubAPI_Version & "+json") ; User-Agent: Awesome-Octocat-App $oHTTP.setRequestHeader("User-Agent", "AutoIt UDF") Return $oHTTP EndFunc ;==>__GHAPI_HTTP_Open Func __GHAPI_HTTP_Send(ByRef $oHTTP, $sSendParameter = Default) If $sSendParameter = Default Then $oHTTP.Send() Else $oHTTP.Send($sSendParameter) EndIf ConsoleWrite('+' & $oHTTP.Status & @CRLF) ConsoleWrite('>' & $oHTTP.StatusText & @CRLF) ConsoleWrite($oHTTP.ResponseText & @CRLF) ConsoleWrite(@CRLF) If @error Then Return SetError(@error, @extended, $GHAPI_RET_FAILURE) ;~ Return SetError($GHAPI_ERR_SUCCESS, $oJSON.Size, $oJSON) EndFunc ;==>__GHAPI_HTTP_Send #EndRegion GHAPI.au3 - INTERNAL Functions #Region GHAPI.au3 - HOWTO / DOCS / HELP #CS #CE #EndRegion GHAPI.au3 - HOWTO / DOCS / HELP  
      This is just a modest start up and not a whole fully workable UDF, just so for a try, but maybe someone will be useful
      EDIT 1:
      If you need to make it workable just ask about specyfic feature.
      EDIT 2:
      Some changes in using word "GitHub" - to meet this rules:
    • 5ervant
      By 5ervant
      What's the best way to receive file from a desktop app?
      app.exe will execute a cmd with "au3file.exe /path/of/the/file.xml" and the au3file.exe will get and delete that. Or else? THE MOST IMPORTANT PART OF THE QUESTION
      And best way to transfer file to a desktop app?
      au3file.exe do a $_POST request and the app.exe MUST HAVE a local HTTP server that can receive $_POST, but it looks heavy 'cause the app must have a server such XAMPP. au3file.exe execute a cmd with "app.exe /path/of/the/file.xml" and the app.exe will now get that file and delete. Or else?  
    • LeloDragneel
      By LeloDragneel
      Hey guys,
      I'm looking to implement an accurate voice recognition method in my program. I tried to understand the Microsoft SAPI API, read their online documentation and found it very confusing and unclear. (Like seriously, it's so bad and vague, but that's just my opinion). I have also tried using UTTER UDF, but could not get a grasp either, because you know, that's an extension UDF to Microsoft SAPI.
      Let's face it, the Google Speech Recognition is much more accurate than Microsoft SAPI (by far). Right now, I am determined to just use the Google Speech API. I have dug deep in regards to implementing the Google Speech API in AutoIT and I haven't found even one post about it. I suppose it's because the Google Speech API was only recently made available to the public. In case you don't know what I'm talking about, here's the link to google api. On that page, notice that there is language support for various languages such as Java, C#, and PHP. However, there's no support for AutoIT. So my question is; how can I go about implementing the Google Speech API into my AutoIT program? Is it even possible?
      Cheers guys!