Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2586
  • Last Modified:

How to close .bat file after execution

Hi experts,

I am trying to make my application self-updatable. On every run app checks current version available on server.
If there is new version I create a .bat file that should copy the new exe and restat application
Then from my application I run the .bat file and close the application. Here the code :
    ff = FreeFile
    Open App.Path & "\ver___tmp.bat" For Output As #ff
     
    Print #ff, "COPY """ & SourceURL & "\" & App.EXEName & ".exe"" " & App.Path & "\" & App.EXEName & ".exe.newver"""""
    Print #ff, "DEL """ & App.Path & "\" & App.EXEName & ".exe"" "
    Print #ff, "REN """ & App.Path & "\" & App.EXEName & ".exe.newver"" " & " """ &  App.EXEName & ".exe"" " 
   
    Print #ff, "Call """ & App.Path & "\" & App.EXEName & ".exe"" "
    Print #ff, "DEL ver___tmp.bat"
    Print #ff, "EXIT"
    Close #ff
    Shell App.Path & "\ver___tmp.bat"
    End

Everything is working OK. But .bat file remain running until my application runs.
How to force .bat to close itself after last command execution?

Any ideas?
0
Michael_D
Asked:
Michael_D
  • 7
  • 7
  • 3
  • +2
1 Solution
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
This works on Win XP Pro...

Instead of:

    Print #ff, "Call """ & App.Path & "\" & App.EXEName & ".exe"" "

Try:

    Print #ff, "Start """ & App.Path & "\" & App.EXEName & ".exe"" "

Regards,

Idle_Mind

0
 
Michael_DAuthor Commented:
Idle_Mind ,
I checked your suggession on Win 2000 Pro and its doesn't work. Even worse - After main application exits batch file terminates as well but but CMD.exe is running now!!!
Maybe some other method to get new file from server?
All I need - it 's just copy a file!
 
0
 
David LeeCommented:
Well, here's one quick way to do it.

    'Include a reference to Microsoft Scripting Runtime
    Dim objFSO As New FileSystemObject
    strSource = "Path and name of source file"
    strDestination = "Path and name of destination file"
    objFSO.CopyFile strSource, strDestination
    Set objFSO = Nothing
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Michael_DAuthor Commented:
BlueDevilFan,

I don't think that using fso will allow me overwrite an opened file.
Maybe my bad english caused misunderstanding.
But anyone of you I sure met some applications  that automaticly download new version, install it and after all job done restart itself so users allways work with most recent version. In my case I dont need download file from internet but simlpe copy it over LAN. I have a solution where additional exe involved (kind of loader). I don't like this solution. I need ONE exe file that update itself.

Thanks,

Michael

P.S. I have increased points because it's drive me nuts ... I NEED Solution

M
0
 
zonaltechCommented:
I can't take credit for the solution, but Erick37 already solved a similar problem in this topic:
http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_20237868.html

The key code being:

Shell Environ("COMSPEC") & " /C program.bat"
"COMSPEC" is the variable pointing to the OS's command interpreter.

Just some addition anecdotal conversation:
I have a similar auto-updating application. When dealing with windows apps, you want to stay as far away from DOS-type things as possible. It just looks clunky. Here's my suggestion: Generate a temporary VBScript to perform these actions, or...

In Windows NT-type operating systems, you can rename running executables. I have an application that is distributed over a network and running on every client machine. The initial installation program just installs references (DLL's, etc.) and a shortcut to the EXE on the network. Then when it's time to make a new release, I just rename the current central executable to <appname>.old and it still runs. I then copy the new build to <Appname>.exe then I change the field "CurrentRevision" in the central configuration table to the new revision number. The clients (which poll the database at an interval) detect this and compare to their current revision. If it is greater, the client programs individually trigger the "Updater.exe" program I have bundled with it, which basically kills the current local process and runs the .exe again. So I don't have to go around updating each client, and I still maintain control over when a rollout occurs.

If you still need to cater to Windows 98 users, or you want something less hands-on (such as internet updating?) you can just have the program call Updater.exe or a VBScript and exit, and let that process do the renaming and notifying after the main program exits.

Personally, I can't do that in my setup, because I use a central EXE, and clients shouldn't individually try to rename that, they'd all compete for it. I trade complete automation for precise control and one central EXE that is shared. Do whatever works best for your needs!
0
 
zonaltechCommented:
Also, I don't think you can _programmatically_ rename a running file in NT, you have to rename it from explorer. So the VBScript method, or the Shell example I provided should be the best solution for you.

However, if you run this program centrally on an intranet and do periodic manual rollouts, the "renaming before updating" method has great benefits!
0
 
David LeeCommented:
Michael,

Sorry, I keyed on this statement, "All I need - it 's just copy a file!", in your second posting and thought you were litteraly just looking to copy a file.  My mistake.

The way I've handled this in the past is to make two apps.  The first app is the updater.  It's the program the user actually runs and its only function is to check for an update, download it if there is one, and then launch the real application.  This approach works find so long as you're satisfied with checking for updates only when the program is initially launched.  If you need a solution that'll check while the main program is running, then you can use a variety of interprocess communication methods to achieve that.  For example, the updater program could check every x minutes for an update.  If it finds one, then it sends the actual app a shut-down message.  Once the real app has shutdown, then the updater downloads the update and relaunches the actual app.  There are several ways for the programs to communicate.  One simple way is by writing messages to a file or database that the other app checks periodically.  A more sophisticated method would be to use the Winsock control.  Or you could use the more exotic Named Pipes, Mailslots, etc.
0
 
Michael_DAuthor Commented:
zonaltech,

Seems like you on the right way.
Can you help me with VBScript? Some sample code?


BlueDevilFan,

As I mentioned before the solution with 2 exes not situable in my case. I am actively use this aproach. Even more - I made an application called AppLauncher: kind of Application Menu that checks not only versions but even needed dlls and ocxes and install them if need. But now I need ONLY ONE FILE - MyApp.exe that knows how to self-update.

Anyway thanks to all of you.
0
 
zonaltechCommented:
Try this on for size!

Dim ff As Long
    ff = FreeFile
    Open App.Path & "\ver___tmp.vbs" For Output As #ff
    Print #ff, "Main"
    Print #ff, "Sub Main()"
    Print #ff, "Dim fs 'As Scripting.FileSystemObject"
    Print #ff, "wscript.sleep ""3000""" ' Wait 3 seconds before running.
    Print #ff, "Set fs = Wscript.CreateObject(""Scripting.FileSystemObject"")"
    Print #ff, "fs.CopyFile """ & App.EXEName & ".exe.newver"", """ & App.EXEName & ".exe"""
    Print #ff, "fs.DeleteFile """ & App.Path & "\ver___tmp.vbs"""
    Print #ff, "End Sub"
    Close #ff
    Shell "wscript //B " & App.Path & "\ver___tmp.vbs"
    End

You may have just convinced/inspired me to ditch my Updater.exe, I'll try this on my application too!
0
 
zonaltechCommented:
I am also interested in your AppLauncher idea for initial installs, dynamically loading the OCX's and DLL's to the client system sounds better than using Package and Deployment Wizard...
0
 
David LeeCommented:
Doh!  Sorry again, Michael.  I'm going to have to get new glasses, or maybe a new brain.  

zonaltech - Interesting approach.  Two questions, if you don't mind.  One, how do you plan to handle additional processing issues, such as the copying of supporting files (e.g. DLLs, OCXs, etc.), registering new components, and so forth?  Two, how are you going to handle error processing?  There's always the chance that the script file will encounter a problem and fail.
0
 
Michael_DAuthor Commented:
Guys, sorry for late response

With VBscript the promlem is still here: Script doesn't continue after launching application to delete itself. But there is no window so I can live with it (untill I'll find the solution)
And follow is the full code:

Public Function Check4Update() As Boolean
Dim aFiles2Copy(1) As String
Dim SourceURL As String
Dim i As Integer
Dim ff
Check4Update = False
SourceURL = App.Path & "\Source\"
aFiles2Copy(0) = "updater.exe"
aFiles2Copy(1) = "updater.ini"
'Create temporary .vbs file for renaming files
    ff = FreeFile
    Open App.Path & "\ver___tmp.vbs" For Output As #ff
   
    Print #ff, "dim fso"
    Print #ff, "set fso=Wscript.CreateObject(""Scripting.FileSystemObject"")"

    Print #ff, "wscript.sleep ""3000""" ' Wait 3 seconds before running.

    For i = UBound(aFiles2Copy) To LBound(aFiles2Copy) Step -1
        Print #ff, "fso.CopyFile """ & SourceURL & "\" & aFiles2Copy(i) & """, """ & App.Path & "\" & aFiles2Copy(i) & ".newver"""
        Print #ff, "fso.DeleteFile """ & App.Path & "\" & aFiles2Copy(i) & """"
        Print #ff, "fso.MoveFile """ & App.Path & "\" & aFiles2Copy(i) & ".newver"" ,""" & App.Path & "\" & aFiles2Copy(i) & """"
    Next i
    Print #ff, "Dim oShell"
    Print #ff, "Set oShell = WScript.CreateObject(""WSCript.Shell"")"
    Print #ff, "oShell.run """ & App.Path & "\" & aFiles2Copy(0) & """, 0, True"

    Print #ff, "fso.DeleteFile """ & App.Path & "\ver___tmp.vbs"""
    Print #ff, "set fso=nothing"
    Close #ff
   
    Check4Update = True
   
    Shell "wscript //B " & App.Path & "\ver___tmp.vbs"

    End


End Function
0
 
Michael_DAuthor Commented:
Regarding AppLauncher.

Unfortunatly I don't have source code (I did it for my previous employer ) but idea is very simple:
The application itself is list of available applications (filled from database according users' permissions)
When user choose app to launch AppLauncher checks in another table for list of Dlls and ocxes required by application.(I filled this table from dependency file). Here comes little trick. Instead of actually find out if dll is registred or not and if the version of dll is up to date Launcher checks in  Registry for "custom made" keys. Setup package for AppLauncher itself creates some of those keys (for instance - VBRuntime, MDAC_TYP etc.). So when AppLauncher cannot find the flag that dll was installed on this PC, it copies dll and register it using regsvr32. Then it put information adout just copied dll into registry.
On next run it just checks for version number.
This schema works for more than 300 users!  
0
 
zonaltechCommented:
Michael, I'm glad you are satisfied, and for what it's worth, the vbs deletes itself on my machine; maybe that's because I was running it from the IDE in design mode. Either way, I'm also researching a more elegant way to do this, so we should both benefit ;).

BlueDevilFan, well, so far what I'm working on is an unattended installer, instead of or in addition to PDW. Since my application is one EXE on the network, the installer simply functions to update/install OCX/DLL client references. If I can make it unattended, I can simply use a method in Updater.exe (or equivalent) to run that installer again to refresh configuration. The installer and the EXE are both updated upon each rollout, so that's the point of origin for the clients to pull from. I've found some excellent tools at www.sysinternals.com, most notably the PsTools suite, which includes PsExec.exe. This is a commandline tool that can run remote processes on any machine in the network. It can even do it interactively, like with command prompts. (This is especially useful when they are workstations with no real remote access built in). So I can write scripts that force each computer to run the updated installer before the EXE rollout.

I would like something more dynamic though, which is why the script method interested me, since you can spawn separate VB-Like processes from an EXE. Another idea I had was to have the Updater.exe embedded in a *.RES Resource File and pull it out and run it when necessary. You could even put all the dependent files within the EXE in this manner, but depending on how many you have, it could get large. I try to keep things as bare-bones as possible reference-wise, so it's still an interesting thing to think about.

0
 
Michael_DAuthor Commented:
Ups, code dosen't work with long file names.

Error on this line oShell.run "C:\Program File\....."
If I replace "Program Files" with "Progra~1" everything is OK. I don't think there is no some workaround.

Regards,

Michael
0
 
Michael_DAuthor Commented:
OK I got it      in VBScript file should be surounded by 3(!) pairs of double quotes
    Print #ff, "oShell.run  """"""" & App.Path & "\" & aFiles2Copy(0) & """"""""

Thanks,

Michael
0
 
zonaltechCommented:
Ah, nice, I'll remember that; sometimes I just do & Chr(34) & to avoid the confusion.
0
 
VB_ASP_GodCommented:
working on something similar
this is what i've done!

    Open "c:\temp.bat" For Output As #1
    Print #1, "@echo off"
    Print #1, "echo.Updating File..."
    Print #1, "TSKill " & App.EXEName & " /a"
    Print #1, "Del " & Replace(App.Path & "\" & App.EXEName, "\\", "\") & ".exe"
    Print #1, "Copy C:\filename.exe " & Replace(App.Path & "\" & App.EXEName, "\\", "\") & ".exe"
    Print #1, "Del C:\filename.exe"
    Print #1, "Del c:\temp.bat"
    Print #1, "Start " & Replace(App.Path & "\" & App.EXEName, "\\", "\") & ".exe"
    Close #1
    SHELL "c:\temp.bat", vbHide
0
 
zonaltechCommented:
I found a solution for the OCX/DLL thing. I made a 'barebones' copy of the VB6 installer that I specially modified to automatically uninstall the application on startup, then re-install the application again. This works separate from my EXE updater. This way I have full control over smaller functionality changes and larger changes that require newer DLL's. I run the installer in silent mode with logging over the network remotely. I can then analyze the logs to see how successful the installs are. Can anyone think of a better way? I'm happy with the way I have it now, but I am open to more efficient ways of doing things.

Thanks!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 7
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now