My compiled scripts are on a server, so that all users can access them. For several of them a shortcut file (.lnk) is created on the users desktop or autostart folder so that they can easily start them. Due to this, the file names of the compiled scripts with such a shortcut file shouldn't be changed, or the shortcuts have to be updated/renewed.
The problem:
When I try to update the compiled scripts Windows refuses to replace the files, since they are in use by some user. This could also happen late at night, since some users don't log off.
The solution:
If you add a small routine to your scripts which file names will not change with an update, they will kill themselves when they receive a message that they need to shut themselfs down. Thus this installation process by this program can be performed. But you do not want to terminate a software the user is currently working with. So the software will give him a 1 minute warning time. If he refuses to let the script shut down itself, it will remind him in 5 minutes periods again until he accepts or the warning message times out, so he has time to finish what ever he is doing.
But since Admins like me would like to know who is refusing, a message (username and computername) is send back to the installation program so that the Admin knows who he has to contact.
At then end the the Admin has a small log message which software has been installed and which users had to closer their apps, so he can inform them, that they can now start it again just by clicking the shortcut.
Do you know a better solution?
;############################################################################## ;# ;# GUI, that helps to install new Software Versions if they are in use by ;# other users. ;# ;# OS: Windows XP ;# AHK version: 1.0.41.02 (http://www.autohotkey.com/download/) ;# Date: 2006-02-03 ;# ;# Known problems: ;# - ;# ;# Wish list: ;# - ;# ;The code in is block comment needs to be put into the scripts that need auto kill to be updated /* ;add this into auto-exec-section ;if it is compiled, check if there is a kill message If A_ISCompiled SetTimer, CheckForAutoKillMessage, %CheckForAutoKillMessageInterval% Return ;############# Check for AutoKillMessage ################################## CheckForAutoKillMessage: ;check if auto-kill-message exists If FileExist("Kill_" . A_ScriptName . ".txt"){ ;give feedback with 1 minute timeout Minutes := CheckForAutoKillMessageInterval // 60 // 1000 MsgBox, 4404, New Version available, (LTrim There is a new version of %A_ScriptName% available. The installer requests you to shut down the software. You can press NO to get another message in %Minutes% minutes. If you press YES, the software will be shut down, so that the new software can be installed. This message will close itself in 1 minute and assume you want the software to shut down. ), 60 ;user needs more time, write message into kill file, so admin knows who needs time IfMsgBox, No FileAppend, I need more time: %USERNAME% on %COMPUTERNAME% at %A_Now%`n, Kill_%A_ScriptName%.txt ;user closes app or timeout is due, write message into kill file, so admin can inform user when done Else { FileAppend, I closed the app: %USERNAME% on %COMPUTERNAME% at %A_Now%`n, Kill_%A_ScriptName%.txt ExitApp } } return */ ;############# Directives ################################################# Version = v0.53 ;second part of window title InstallNewSoftwareFilename = InstallNewSoftware ;Script with GUI to keep automounts alive InstallNewSoftwareWindowtitle = Install New Software InstallNewSoftwareIconID = 69 ;icon for window and for process in task manager StartCenterIni = %A_ScriptName%.ini CheckForAutoKillMessageInterval := 5 * 60 * 1000 ;5 minutes Menu, Tray, Icon, %IconFile%, %InstallNewSoftwareIconID%, 1 ;icon for window and for proces in task manager #SingleInstance force #NoTrayIcon IniRead, PathInstallSoftware, %StartCenterIni%, InstallNewSoftware, PathInstallSoftware, %A_ScriptDir% LogText = ;############# Start of Script ############################################ ;Build GUI 1 - InstallNewSoftware Gui, 1: +AlwaysOnTop +Resize Gui, 1:Add,Text,Section ,Path to install droped software in Gui, 1:Add,Button, x+3 ys-5 gBrowsePathInstallSoftware,... Gui, 1:Add,Edit,xm ReadOnly r3 w300 vPathInstallSoftware,%PathInstallSoftware% Gui, 1:Add,Text,xm,Feedback: Gui, 1:Add,Edit,xm ReadOnly r10 w300 vEdtFeedback, Gui, 1:Add,Button,xm Section vBtnStop gBtnStop, Stop Gui, 1:Add,Button,ys vBtnClose gGuiClose, Close ;get previous position and show Gui IniRead, Pos_Gui1, %StartCenterIni%, InstallNewSoftware, Pos_Gui1, x0 y0 Gui1WinTitle = %InstallNewSoftwareWindowtitle% %Version% Gui, 1: Show, %Pos_Gui1% AutoSize, %Gui1WinTitle% WinWait, %Gui1WinTitle% WinGet, Gui1UniqueID, ID, %Gui1WinTitle% Gosub, CheckData Return ;############################################################################## ;############# End of AutoExecution-Section ############################### ;############################################################################## ;############################################################################## ;############# Actions of GUI 1 ########################################### ;############################################################################## ;############# Browse to Path where software needs to be installed ######## BrowsePathInstallSoftware: BrowseFolder("PathInstallSoftware", "Select path to install software") Return BrowseFolder(Control, Message){ Gui, 1:+OwnDialogs FileSelectFolder, SelectedDir, *%A_ScriptDir% , 3, %Message% If SelectedDir GuiControl, 1: ,%Control%,%SelectedDir% } ;############# Check correctness of data ################################## CheckData: Gui, 1:+OwnDialogs DataCheckStatus := True ;######################### Check existence of path If not FileExist(PathInstallSoftware) { MsgBox, 16, Path doesn't exist, (LTrim The path to install the software in couldn't be found: %PathInstallSoftware% Please select an existing path. ) DataCheckStatus := False } Return ;############# Handle files that have been droped ######################### GuiDropFiles: Gui, 1:Submit, NoHide ;check if path for installation exists, otherwise do nothing Gosub, CheckData If not DataCheckStatus Return ;loop over all droped files/folders and store them Loop, Parse, A_GuiControlEvent, `n { DropedFile = %A_LoopField% ;find out if item is a directory (Attribute contains "D") FileGetAttrib, Attributes, %DropedFile% If InStr(Attributes, "D") ListOfFolders = %ListOfFolders%%DropedFile%`n Else ListOfFiles = %ListOfFiles%%DropedFile%`n } ;give feedback, if folders were droped If ListOfFolders is not Space { LogText = %LogText% (Ltrim Folders can't be installed: These droped files are folders: %ListOfFolders% ) GuiControl, 1:, EdtFeedback, %LogText% ;empty list for next drop of folders ListOfFolders = } ;give feedback for files If ListOfFiles is not Space { LogText = %LogText% (Ltrim These files will now be installed into %PathInstallSoftware%: %ListOfFiles% Feedback will be given when done. ) GuiControl, 1:, EdtFeedback, %LogText% If ! InstallIsStoped { ;call install routine now and with a timer SetTimer, InstallSoftware, %CheckForAutoKillMessageInterval% Gosub, InstallSoftware }Else { LogText = %LogText%...but only if you press "Start"...`n GuiControl, 1:, EdtFeedback, %LogText% } } Return ;############# Stop to install software ################################### BtnStop: If InstallIsStoped { SetTimer, InstallSoftware, %CheckForAutoKillMessageInterval% Gosub, InstallSoftware GuiControl, 1:, BtnStop, Stop }Else{ SetTimer, InstallSoftware, Off GuiControl, 1:, BtnStop, Start } InstallIsStoped := not InstallIsStoped Return ;############# Try to install software #################################### InstallSoftware: Loop, Parse, ListOfFiles, `n { If A_LoopField is Space Continue File = %A_LoopField% SplitPath, File, OutFileName NewFile = %PathInstallSoftware%\%OutFileName% FileCopy, %File%, %NewFile%, 1 If ErrorLevel { ;it couldn't be overwritten, maybe it is in use. ;read kill message in PathInstallSoftware FileRead, KillFeedback, Kill_%OutFileName%.txt Minutes := CheckForAutoKillMessageInterval // 60 // 1000 LogText = %LogText%`n (Ltrim Couldn't copy: %OutFileName% %KillFeedback%"%InstallNewSoftwareWindowtitle%" will try again in %Minutes% [min], don't close it. ) GuiControl, 1:, EdtFeedback, %LogText% ;write kill message into PathInstallSoftware IfNotExist, Kill_%OutFileName%.txt FileAppend, AutoKillMessage for %OutFileName% issued %A_Now%`n , Kill_%OutFileName%.txt }Else { ;Copy was successful ;read and remove kill message in PathInstallSoftware FileRead, KillFeedback, Kill_%OutFileName%.txt FileDelete, Kill_%OutFileName%.txt ;give feedback LogText = %LogText% (Ltrim Installed successfully: %OutFileName% %KillFeedback% ) GuiControl, 1:, EdtFeedback, %LogText% ;remove file from list StringReplace, ListOfFiles, ListOfFiles, %File%`n, } } If ListOfFiles is Space SetTimer, InstallSoftware, Off Return ;############# Gui gets resized ########################################### GuiSize: new_w := A_GuiWidth - 20 new_h := A_GuiHeight - 135 GuiControl, 1:Move, PathInstallSoftware, w%new_w% GuiControl, 1:Move, EdtFeedback, w%new_w% h%new_h% new_y := A_GuiHeight - 29 GuiControl, 1:Move, BtnClose, y%new_y% GuiControl, 1:Move, BtnStop, y%new_y% Return ;############# If Gui is closed, exit script ############################## GuiEscape: GuiClose: Gui, 1:Submit ;store current position and exit app WinGetPos, PosX, PosY, , , ahk_id %Gui1UniqueID% IniWrite, x%PosX% y%PosY%, %StartCenterIni%, InstallNewSoftware, Pos_Gui1 IniWrite, %PathInstallSoftware%, %StartCenterIni%, InstallNewSoftware, PathInstallSoftware ExitApp Return ;############################################################################## ;############# End of File ################################################ ;##############################################################################