The MASM Forum

General => The Campus => Topic started by: x64Core on November 15, 2012, 08:56:14 PM

Title: check if a file exists [better way]
Post by: x64Core on November 15, 2012, 08:56:14 PM
Hi Guys, I would like to know your opinions please,
I want to do a loop which will check if a file exists, for example, doing a timer call-back function , Create a thread and use Sleep ( to avoid the increase of the CPU ). opinions? please, thanks!  :biggrin:
Title: Re: check if a file exists [better way]
Post by: jj2007 on November 15, 2012, 09:34:08 PM
No extra thread needed, just use SetTimer wisely. Here is a little test - performance depends strongly on whether you use Sleep 1 or Sleep 0...

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
   Init
   xor ebx, ebx
   MsgBox 0, "Open Task Manager and watch the CPU usage. Press Shift to start the second test", "Hi", MB_OK
   NanoTimer()
   .Repeat
      invoke Sleep, 1
      .if !Exist("\Masm32\include\Windows.inc")
         MsgBox 0, "No WinInc", "Hi", MB_OK
      .endif
      invoke GetKeyState, VK_SHIFT
      inc ebx
   .Until ebx>100000 || sword ptr ax<0
   MsgBox 0, Cat$(Str$("Sleep 1: %i tests took ", ebx)+Str$("%i ms", NanoTimer(ms))), "Hi", MB_OK

   xor ebx, ebx
   NanoTimer()
   .Repeat
      invoke Sleep, 0
      .if !Exist("\Masm32\include\Windows.inc")
         MsgBox 0, "No WinInc", "Hi", MB_OK
      .endif
      invoke GetKeyState, VK_SHIFT
      inc ebx
   .Until ebx>100000 || sword ptr ax<0
   MsgBox 0, Cat$(Str$("Sleep 0: %i tests took ", ebx)+Str$("%i ms", NanoTimer(ms))), "Hi", MB_OK
   Exit
end start
Title: Re: check if a file exists [better way]
Post by: hutch-- on November 15, 2012, 10:22:31 PM
Sleep or SleepEx is not the right function to use here, a timer in the message loop (WndProc) is more efficient and does not lock the thread for the sleep duration.
Title: Re: check if a file exists [better way]
Post by: jj2007 on November 15, 2012, 11:23:33 PM
Quote from: hutch-- on November 15, 2012, 10:22:31 PM
Sleep or SleepEx is not the right function to use here, a timer in the message loop (WndProc) is more efficient and does not lock the thread for the sleep duration.

Of course. I chose a console example to avoid posting a full-fledged win app, but the logic is the same:
SetTimer handle, ID, 0, 0 is a lot different from
SetTimer handle, ID, 1, 0
Title: Re: check if a file exists [better way]
Post by: dedndave on November 16, 2012, 02:07:28 AM
depending on what you are doing, you can use FindFirstFile/FindNextFile/FindClose

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364418%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364418%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364428%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364428%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364413%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364413%28v=vs.85%29.aspx)

you can use FindFirstFileEx/FindNextFile/FindClose to specify certain attributes

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364419%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364419%28v=vs.85%29.aspx)

in some cases, you can use GetFileAttributesEx, instead - depends on what you're after
works great if you are looking for one specific file
it can be used to tell you if the file exists, attributes, and size

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946%28v=vs.85%29.aspx)

i try to use the later if possible, as it is fast and efficient
if it won't do the job, however, you can use one of the other methods   :P
Title: Re: check if a file exists [better way]
Post by: CommonTater on November 16, 2012, 03:42:18 AM
You can also try the shlwapi commands...

PathFileExists() (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773584(v=vs.85).aspx) to discover if a single file or folder exists (no wildcards).
PathIsDirectory() (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773621(v=vs.85).aspx)  to discover if a patname is a directory (again no wildcards).
and
PathIsDirectoryEmpty() (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773623(v=vs.85).aspx) to discover if a folder has files in it or not (still no wildcards)

There's a whole mess of these... listed HERE (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773559(v=vs.85).aspx) .
I find them very handy when you're just doing quick checks.

Title: Re: check if a file exists [better way]
Post by: jj2007 on November 16, 2012, 04:56:32 AM
Quote from: CommonTater on November 16, 2012, 03:42:18 AM
There's a whole mess of these... listed HERE (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773559(v=vs.85).aspx).

Hi Tater,

For an assembly coder, there are some highlights on that page ;-)

QuotePathAddBackslash

Adds a backslash to the end of a string to create the correct syntax for a path. If the source path already has a trailing backslash, no backslash will be added.

Note  Misuse of this function can lead to a buffer overrun. We recommend the use of the safer PathCchAddBackslash or PathCchAddBackslashEx function in its place.
Title: Re: check if a file exists [better way]
Post by: x64Core on November 16, 2012, 05:13:54 AM
Thanks guys Really I appreciate your help!  :biggrin:

ADD: guys, a question, How to could I to implement to SetTimerProc? any idea please.
Title: Re: check if a file exists [better way]
Post by: jj2007 on November 16, 2012, 06:08:14 AM
Quote from: RHL on November 16, 2012, 05:13:54 AM
How to could I to implement to SetTimerProc?

Simple and straightforward, just follow the SetTimer documentation. If you post your current proc here, we might comment on it.
Title: Re: check if a file exists [better way]
Post by: CommonTater on November 16, 2012, 07:20:54 AM
Quote from: jj2007 on November 16, 2012, 04:56:32 AM
For an assembly coder, there are some highlights on that page ;-)

:biggrin:  Glad I could help.

Title: Re: check if a file exists [better way]
Post by: jj2007 on November 16, 2012, 07:49:36 AM
Quote from: CommonTater on November 16, 2012, 07:20:54 AM
:biggrin:  Glad I could help.

Lol. Here is one "highlight":

QuoteHRESULT PathCchAddBackslashEx(
  _Inout_    PWSTR pszPath,
  _In_       size_t cchPath,
  _Out_opt_  PWSTR *ppszEnd,
  _Out_opt_  size_t *pcchRemaining
);

pszPath [in, out]

    A pointer to the path string. When this function returns successfully, the buffer contains the string with the appended backslash. This value should not be NULL.

[Mom, why should the pointer not be NULL?]

Then the final sentence that explains it all: Minimum supported client Windows 8

Win8 users, prepare for the worst :greensml:
Title: Re: check if a file exists [better way]
Post by: CommonTater on November 16, 2012, 07:59:49 AM
Quote from: jj2007 on November 16, 2012, 07:49:36 AM
[Mom, why should the pointer not be NULL?]

The input path can't be NULL because it's going to search for the zero (null) at the end of the string then add a backslash and new null on the end...  That would amount to an access violation at address 0.

The PathAddBackslash function is functionally equivalent to...

if (szString[strlen(szString) - 1] != '\\')
   strcat(szString, "\")

... in fact it probably uses strcat().

FWIW... I'm doing my level best to ignore Windows 8.
Title: Re: check if a file exists [better way]
Post by: jj2007 on November 16, 2012, 08:37:06 AM
 ;)

include \masm32\include\masm32rt.inc

.data
ThePath   db "C:\Masm32\include", 0

.code

start:   mov edi, offset ThePath
   xor eax, eax
   or ecx, -1
   repnz scasb
   .if byte ptr [edi-1]!="\"
      mov byte ptr [edi-1], "\"
      stosb
   .endif
   inkey offset ThePath
   exit

end start

Title: Re: check if a file exists [better way]
Post by: x64Core on November 16, 2012, 06:03:18 PM
hi, here it is my code, it's simple:


.386
.model flat,stdcall
include masm32rt.inc


MyTimer PROTO :HWND,:UINT,:UINT,:DWORD

.data
nmsg db "the file doesn't exist",0
Myfile db "C:\Test.txt",0
msg MSG <>
.code
start:

invoke SetTimer,0,11,8000,MyTimer


.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
invoke ExitProcess,0



MyTimer proc hWnd:HWND,uMsg:UINT,idEvent:UINT,dwTime:DWORD

invoke CreateFile,addr Myfile,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox,hWnd,addr nmsg,addr nmsg,MB_OK
.endif
ret

MyTimer endp

end start


But now my problem is, How to can I pass parameters/information to Timer procedure? My aim is, don't to use  global variables lol
wft? yeah if I don't want to use global variables how can I pass information to timer procedure, for example I want to use a string from
my timer procedure but without global variables, my rustic method was this:

put my string in a textbox control, then in the timer procedure get the control handle ( the control ID is constant, so it doesn't matter )
then use sendMessage to get the string from my timerproc without global variable :P but it's very rustic :( so I think it's impossible or
Is there any way to do this? or maybe how to could I implement a timer procedure ( which i can pass information ).
well any idea thanks guys!



Title: Re: check if a file exists [better way]
Post by: qWord on November 16, 2012, 06:19:55 PM
Quote from: RHL on November 16, 2012, 06:03:18 PMif I don't want to use global variables how can I pass information to timer procedure, for example I want to use a string from
one way is to associate the data with the window (-handle)
Title: Re: check if a file exists [better way]
Post by: x64Core on November 16, 2012, 06:30:59 PM
Quote from: qWord on November 16, 2012, 06:19:55 PM
Quote from: RHL on November 16, 2012, 06:03:18 PMif I don't want to use global variables how can I pass information to timer procedure, for example I want to use a string from
one way is to associate the data with the window (-handle)

  • use WNDCLASSEX.cbWndExtra + Get/SetWindwoLong
  • use Get/SetWindowLong with GWL_USERDATA
  • use properties (Set/GetProp)

GWL_USERDATA looks like very interesting, thank you qWord  :biggrin: