News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Number and type of arguments required for call to C library

Started by jj2007, May 21, 2014, 10:21:19 PM

Previous topic - Next topic

GoneFishing

Thanks,  Dave

[EDIT]: I've detected the first mistake in my code: the call to CopyHere doesn't return status SUCCESS because  as stated here :
QuoteReturn value

This method does not return a value.
Remarks

No notification is given to the calling program to indicate that the copy has completed.

This VBScript is zipping the file / folder only if I call the MessageBox after CopyHere :

SET o=CreateObject("Shell.Application")
SET n=o.Namespace("C:\new.zip")
n.CopyHere("C:\myfolder")
Wscript.Echo "Please, wait"


My code requires major fixes ... I'll be back in a day or two  ;)


dedndave

i think i am starting to understand the interface a little bit   :P
i can see that you were right - CopyHere wants the source

dedndave

something like this

CLSIDFromProgID
CoCreateInstance
IDispatch::GetIDsOfNames(szTarget)
IDispatch::Invoke(Shell.NameSpace(idTarget))
IDispatch::GetIDsOfNames(szSource)
IDispatch::Invoke(Folder.CopyHere(idSource))
(wait for it to finish)
IDispatch::Release


i'm getting closer, at least   :biggrin:

peter_asm

i was thinking how to wait on thread termination and ExecNotificationQueryAsync might work, see vbscript for basic example


option explicit

Dim sink, end_query, wmi, shell, zip, completed

Set wmi = GetObject("WINMGMTS:\\.\root\cimv2")

Set sink = WScript.CreateObject ("WbemScripting.SWbemSink", "SINK_")

' query to monitor for deletion of threads
end_query  = "SELECT * FROM __InstanceDeletionEvent " & _
             "WITHIN 1 "                              & _
             "WHERE TargetInstance ISA 'Win32_Thread'"
               
completed = False
wmi.ExecNotificationQueryAsync sink, end_query

set shell=CreateObject("Shell.Application")
set zip=shell.Namespace("C:\users\pete\desktop\test.zip")


   ' http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
   ' ===============================================================
   ' 4 = do not display a progress box
   ' 16 = Respond with "Yes to All" for any dialog box that is displayed.
   ' 128 = Perform the operation on files only if a wildcard file name (*.*) is specified.
   ' 256 = Display a progress dialog box but do not show the file names.
   ' 2048 = Version 4.71. Do not copy the security attributes of the file.
   ' 4096 = Only operate in the local directory. Don't operate recursively into subdirectories.
   
   ' even though ignore is specified, a dialog box still gets displayed
Call zip.CopyHere("C:\test_folder", 4)

WScript.StdOut.Write "Please wait"

Do While Not completed
  WScript.Sleep 500
  WScript.StdOut.Write "."
Loop

WScript.StdOut.WriteLine vbCrLf & "Complete"

' notifys when thread is ending
Sub SINK_OnObjectReady(ByVal objWbemObject, ByVal objWbemAsyncContext)
  completed = True
End Sub



If i try using wildcards, it just complains about file being too long.
pity MS don't have a built in wait feature for this. i suppose because it's part of explorer and explorer always running, no need.

implementing this solution as C++ would mean inheriting from IWbemObjectSink and I've no idea how that would be done using assembly so it's probably more pain than it's worth.

found another script example : https://github.com/ynkdir/winscript/blob/master/bin/zip.bat

dedndave

my thinking was...

if i can open the zip file for write, it must be done   :biggrin:
windows will put a lock on the zip file while processing

GoneFishing

Quote from: dedndave on May 28, 2014, 12:43:23 AM
something like this

CLSIDFromProgID
CoCreateInstance
IDispatch::GetIDsOfNames(szTarget)
IDispatch::Invoke(Shell.NameSpace(idTarget))
IDispatch::GetIDsOfNames(szSource)
IDispatch::Invoke(Folder.CopyHere(idSource))
(wait for it to finish)
IDispatch::Release


i'm getting closer, at least   :biggrin:
One remark :  GetIDsOfNames takes a IDispatch member name as a parameter  - "Namespace" or "CopyHere" and returns its DISPID .


adeyblue

For closure, I got my head around the workngs of the zipfldr's IStorage / IStream interfaces (which don't create a separate thread nor any UI when zipping) and they're bugged :(
They create a temporary directory fine, then an IBindCtx that'll make the shell create the file if it doesn't exist, all good so far. Unfortunately they then blunder transforming the filesystem path to a pidl: they call SHILCreateFromPath, which requires the path to already exist, instead of SHSimpleIDListFromPath which doesn't. They then call the function that uses the IBindCtx and would create the file, but since the transfomation fails they never get that far.

Shame really since it's not that much more code to use them.

Quote
if i can open the zip file for write, it must be done   
windows will put a lock on the zip file while processing
You'll have to make sure it's already opened the file before you try to, otherwise it'll probably fail (it uses FILE_SHARE_READ when calling CreateFile).

dedndave

i think you misunderstand

you start the ZIP thread
perhaps, wait a few hundred microseconds (give it a chance to get started)
then, you attempt to open the ZIP file (probably with FILE_SHARE_WRITE flag)
if it fails, it means the ZIP thread still has the file locked (wait a few hundred microseconds, try again)
when you can successfully open the ZIP file,
it means the ZIP thread has released it - you close the handle and exit

there's probably some cleaner way to test the file lock flag (more COM stuff   ::) )

dedndave

Quote from: vertograd on May 28, 2014, 03:16:54 AM
One remark :  GetIDsOfNames takes a IDispatch member name as a parameter
"Namespace" or "CopyHere" and returns its DISPID .

thanks vertograd

what i am trying to figure out, is how to determine what "named methods or classes" are available for a specific type of object

i found a COM book online - a lot of material to read
eventually, i'll work my way through it
for now, i just want to read enough to get past this one thing - lol

peter_asm

Would be neat to see way using COM API to monitor when the thread ends.

dedndave

normally, we could use GetExitCodeThread
but - that requires a thread handle
don't guess you have that - it may be possible to get it (difficult with no thread id)

it might be easier to get a thread count
might be something for that in the TEB


jj2007

afaik WaitForSingleObject can take a process handle, too.

GoneFishing

Quote from: dedndave on May 28, 2014, 10:48:43 AM

thanks vertograd

what i am trying to figure out, is how to determine what "named methods or classes" are available for a specific type of object

i found a COM book online - a lot of material to read
eventually, i'll work my way through it
for now, i just want to read enough to get past this one thing - lol

All is simple - search on msdn or dig into headers in Windows SDK
NameSpace is a member of Shell object 
CopyHere is a member of Folder object (you can get there following the link in NameSpace description)

Another way is to use powershell . It's completely object-oriented
To create Shell object:
$shApp=New-Object -ComObject Shell.Application
To dump its members:
$shApp | Get-Member
To create Folder object:
$oFolder=$shApp.Namespace("C:\")
To dump its members:
$oFolder | Get-Member
and so on
You may learn COM with powershell  :t









Gunther

Hi vertograd,

Quote from: vertograd on May 28, 2014, 04:44:37 PM
Another way is to use powershell . It's completely object-oriented
To create Shell object:
$shApp=New-Object -ComObject Shell.Application
To dump its members:
$shApp | Get-Member
To create Folder object:
$oFolder=$shApp.Namespace("C:\")
To dump its members:
$oFolder | Get-Member
and so on
You may learn COM with powershell  :t

Wow. I've done it a wide berth around powershell in the past. Was that an error?

Gunther
You have to know the facts before you can distort them.