Solved

How to close .bat file after execution

Posted on 2004-08-20
19
2,477 Views
Last Modified: 2012-06-22
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
Comment
Question by:Michael_D
  • 7
  • 7
  • 3
  • +2
19 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 11855150
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11855583
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
 
LVL 76

Expert Comment

by:David Lee
ID: 11855882
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11856331
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
 
LVL 2

Expert Comment

by:zonaltech
ID: 11856419
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
 
LVL 2

Expert Comment

by:zonaltech
ID: 11856430
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
 
LVL 76

Expert Comment

by:David Lee
ID: 11856502
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11856676
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
 
LVL 2

Accepted Solution

by:
zonaltech earned 500 total points
ID: 11856854
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 2

Expert Comment

by:zonaltech
ID: 11856876
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
 
LVL 76

Expert Comment

by:David Lee
ID: 11857259
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11857494
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11857549
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
 
LVL 2

Expert Comment

by:zonaltech
ID: 11857809
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11883255
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
 
LVL 13

Author Comment

by:Michael_D
ID: 11883786
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
 
LVL 2

Expert Comment

by:zonaltech
ID: 11886013
Ah, nice, I'll remember that; sometimes I just do & Chr(34) & to avoid the confusion.
0
 

Expert Comment

by:VB_ASP_God
ID: 12178917
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
 
LVL 2

Expert Comment

by:zonaltech
ID: 12185564
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

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

708 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now