Solved

WinExec? Shell?  File Copy, zip, unzip problem!

Posted on 1998-05-15
4
669 Views
Last Modified: 2008-02-01
I am using MS Access 2.0 under Windows 95.
I used WINEXEC and Shell to run a batch file in the background so the MS DOS window does not show up.  The batch file actually copy a zip file from DriveA into c:\dir and then run pkunzip on that file.
On the reverse, I run another batch file to zip up a mdb file and copy it back to Drive A.
This is where to problem starts.  I think the batch file is not able to execute all the commands smoothly because one of the zip or mdb file got "locked" (Acccess denied) along the way.
I press Ctrl-Alt-Del to bring up the Task Manager and I found that a few "Winoldap" is opened.  After I manually end-task these few "Winoldap", I could then access that "locked" file.  Note that the file is still "locked" even after I closed Access.
I wonder if this is due to the process not ended properly?

The following it the code I used a RunCode macro to execute:

Function CopyIn ()

Success = WinExec("c:\dir\copyin.bat, SW_HIDE)

End Function

I hope someone have a detailed answer.

Deeply appreciated!
0
Comment
Question by:spear051598
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 1

Expert Comment

by:Anita030598
ID: 1974037
Did you make sure your database is not opened in exclusive mode?
0
 
LVL 9

Accepted Solution

by:
cymbolic earned 100 total points
ID: 1974038
One thing you need to be aware of is that even if you fire a task off in DOS mode from a batch file, 95 will run that task asynchronously.  SO you have no guarentee that one task finishes before a subsequent task starts.  Also, if you are using batch files, remember to place an "EXIT" command at the end of your batch file to be sure that 95 closes the DOS window and frees up the allocated resource.

For another (better) way to kick off a task and check for completion, see the following:
0
 
LVL 9

Expert Comment

by:cymbolic
ID: 1974039
You can use the following WIN32 API based function call to start a task and wait for completion.  The function to convert a path/file name to a DOS name is necessary occasionally because dos command lines are not tolerant of long file names in 95, particularly when they contain embedded blanks.

Option Explicit
Private Const SYNCHRONIZE = &H100000
Private Const INFINITE = &HFFFF           '  Infinite timeout
Private Const DEBUG_PROCESS = &H1
Private Const DEBUG_ONLY_THIS_PROCESS = &H2

Private Const CREATE_SUSPENDED = &H4

Private Const DETACHED_PROCESS = &H8

Private Const CREATE_NEW_CONSOLE = &H10

Private Const NORMAL_PRIORITY_CLASS = &H20
Private Const IDLE_PRIORITY_CLASS = &H40
Private Const HIGH_PRIORITY_CLASS = &H80
Private Const REALTIME_PRIORITY_CLASS = &H100

Private Const CREATE_NEW_PROCESS_GROUP = &H200

Private Const CREATE_NO_WINDOW = &H8000000

Private Const WAIT_FAILED = -1&
Private Const WAIT_OBJECT_0 = 0
Private Const WAIT_ABANDONED = &H80&
Private Const WAIT_ABANDONED_0 = &H80&
Private Const WAIT_TIMEOUT = &H102&

Private Const SW_SHOW = 5

Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type

Private Const STARTF_USEPOSITION = &H4
Private Const STARTF_USESIZE = &H2

Private Type STARTUPINFO
        cb As Long
        lpReserved As String
        lpDesktop As String
        lpTitle As String
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateProcessBynum Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
Declare Function GetDOSName& Lib "kernel32" Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer _
As Long)

Declare Function FindExecutable& Lib "shell32.dll" Alias "FindExecutableA" _
(ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String)

Public Sub CreateProcess(prc$)
    Dim res&, ShellPgm$
    Dim sinfo As STARTUPINFO
    Dim pinfo As PROCESS_INFORMATION
    On Error GoTo prcerr
    sinfo.cb = Len(sinfo)
    sinfo.lpReserved = vbNullString
    sinfo.lpDesktop = vbNullString
    sinfo.lpTitle = vbNullString
    sinfo.dwFlags = 0
    ShellPgm$ = prc$ + Chr$(0)
    sinfo.dwFlags = STARTF_USEPOSITION + STARTF_USESIZE
    sinfo.dwX = 20 + FMigWiz.Left \ 14
    sinfo.dwY = 150 + FMigWiz.Top \ 14
    sinfo.dwXSize = FMigWiz.Width \ 14
    sinfo.dwYSize = (FMigWiz.Height \ 14) - 100
    res = CreateProcessBynum(vbNullString, ShellPgm$, 0, 0, True, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, sinfo, pinfo)
    If res Then
     ' Let the process initialize
     Call WaitForInputIdle(pinfo.hProcess, INFINITE)
     ' We don't need the thread handle
     Call CloseHandle(pinfo.hThread)
     Do
        res = WaitForSingleObject(pinfo.hProcess, 0)
        If res <> WAIT_TIMEOUT Then
            ' No timeout, app is terminated
            Exit Do
        End If
        DoEvents
     Loop While True
     ' Kill the last handle of the process
     Call CloseHandle(pinfo.hProcess)
    End If
Exit Sub

prcerr:
 errit "Error Starting " + prc$
End Sub
Public Function DosName$(LongName$)
'Use api call to get short DOS Path/File Name
'Declare Function GetDOSName& Lib "kernel32" Alias "GetShortPathNameA" _
'(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer _
'As Long)
Dim sn$, ln$
Dim cchb As Long
ln$ = LongName$ + Chr$(0)
sn$ = Space$(65)
cchb = 65
cchb = GetDOSName&(ln$, sn$, cchb)
DosName$ = Left$(sn$, cchb)
End Function
Public Function GetExePath$(Path$)
'uses following api to locate associated program path
'Declare Function FindExecutable& Lib "shell32.dll" Alias "FindExecutableA" _
'(ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String)
Dim fil$
Dim dr$
Dim rslt$
Dim i As Integer
dr$ = Path$
i = Len(dr$)
While Mid$(dr$, i, 1) <> "\"
 i = i - 1
Wend
fil$ = Mid$(dr$, i + 1)
dr$ = Left$(dr$, i)
rslt$ = Space$(255) 'returned result
If FindExecutable&(fil$, dr$, rslt$) > 32 Then 'success
 i = InStr(rslt$, ".EXE")
 rslt$ = Left$(rslt$, i + 3)
 i = InStr(rslt$, Chr$(0))
 While i > 0
  rslt$ = Left$(rslt$, i - 1) + " " + Mid$(rslt$, i + 1)
  i = InStr(rslt$, Chr$(0))
 Wend
 GetExePath$ = DosName$(rslt$)
Else
 GetExePath$ = ""
End If
End Function

0
 

Author Comment

by:spear051598
ID: 1974040
Thanks Cymbolic,

Wow! your answer is rather involving.  After looking at your profile, I can see why... As you probably know by now, I am rather new to coding.  I have worked in Access for quite a while but mainly used macros to complete almost all my task.  I just got into coding recently.  But thanks very much.  I'd have to study the codes for a while and will keep up as much as possible.

By the way, do you have another shorter alternative to complete the task without waiting for the process to complete.... The reason is that I am out of time... and an interim solution is to break up the process in 2 stages.... not very professional I know... For now, I just need to ensure that each backup process will zip up the mdb file and copy into Drive A.. and then be sure that no files get "locked" after that.  I have tried something instead and it looked rather ok on Window 98 beta.  I am not sure if it'll be ok on my user's win95 machine.  Here it is:

MyCommand = "pkunzip a:\backup.zip c:\mydir\"
X= Shell (MyCommand, 7)

The process is very straight forward.  The difference is that this runs the pkunzip directly rather than running a batch file that executes the pkunzip or zip function.  So this makes me suspect that the "winoldap" thing that appear in Task Manager is perhaps due to the batch file being fired off.... do you think they are related?  However, the problem here is that the Dos Window which is opened by the above code stays open.  Now I have to think of a way to close it automatically.  With the batch file, I can add "exit" and this will close off the window automatically.  Well, can you give me some more insight into this?  Thanks again....

0

Featured Post

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In Part II of this series, I will discuss how to identify all open instances of Excel and enumerate the workbooks, spreadsheets, and named ranges within each of those instances.
The Windows Phone Theme Colours is a tight, powerful, and well balanced palette. This tiny Access application makes it a snap to select and pick a value. And it doubles as an intro to implementing WithEvents, one of Access' hidden gems.
Familiarize people with the process of utilizing SQL Server stored procedures from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Micr…
In Microsoft Access, learn how to use Dlookup and other domain aggregate functions and one method of specifying a string value within a string. Specify the first argument, which is the expression to be returned: Specify the second argument, which …

751 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question