As part of an auto-update macro, I have a copy of an Access FrontEnd on the local drive which when opened, checks to see if the file on the server has a newer CreatedDate. If it is newer, my code currently uses fileSystemObject to CopyFile and overwrites the local drive version (filename remains the same).
The problem I am having however is that when this is done, the 'date created' does not change to that of the newer file and so continually loops as the old file is closed and the new one opened - which checks for updates based on date created... I even tried using kill on the local file and waiting 10 seconds before doing the Copyfile command but even then it appears with the deleted file's creation date.
When I get back to the office I'm going to try copying the file from the server to the local drive without renaming it, deleting the original local drive file, then copying the newly created file so I can rename it back to the original name (the name should not be changed so that any shortcuts will still work).
Has anyone come across this before and found a solution? Am I missing something obvious that would 'refresh' the created date of the file?
EDIT
I think this is pretty close to what I had.
Dim strSource As String, strDest As String, strOrigDB As String, strSvrDB As String
Dim varOldDB As Variant, varNewDB As Variant, fso As Object
Set fso = CreateObject("scripting.filesystemobject")
strSource = "\\192.168.1.2\Data\svrDatabase"
strSvrDB = "AnyOldName.mde"
strDest = "C:\myFolder\myDatabase"
strOrigDB = "KeepMyName.mde"
varOldDB = (strDest & "\" & strOrigDB)
varNewDB = (strSource & "\" & strSvrDB)
If fso.getfile(varOldDB).DateCreated < fso.getfile(varNewDB).DateCreated Then
Kill strDest & "\" & strOrigDB
Excel.Application.Wait Now() + TimeValue("00:00:05")
fso.copyfile (strSource & "\" & strSvrDB), (strDest & "\" & strOrigDB), True
'open new database version
ShellExecute 0, "Open", (strDest & "\" & strOrigDB), "", "", 1
DoCmd.Quit
End If
I was originally using date modified, but noticed that as soon as the Front end opened, this would get renewed and would therefore always be a newer date value than the server file.
EDIT
After thinking about this, and hoping my logic hasn't completely broken down, it would be best if I had a shortcut for the user to click on, but instead of opening the Frontend, it opens a script file that checks for an update. If there is an update, then it deletes the local Frontend and copies the server one (which should be named differently to the original) to the local folder - then opens the new frontend.
This would mean that the datecreated being checked is always going to be updated on copy to the local folder and the kill will work because the file has not been opened. I am still a little wary of using lastdatemodified incase a user has the database open when an update is created - the Frontend contains tables used in searches which I believe will alter the modified date of the Frontend. In this scenario the local date modified would still be greater than a new frontend on the server.
You should be using Date Modified. That's when the file was last changed.
This is what helps says about times.
Timestamps are updated at various times and for various reasons. The only guarantee about a file timestamp is that the file time is correctly reflected when the handle that makes the change is closed.
So try closing all files before comparing times.
Also From https://support.microsoft.com/en-us/kb/172190
When a name is removed from a directory (rename or delete), its short/long name pair and creation time are saved in a cache, keyed by the name that was removed. When a name is added to a directory (rename or create), the cache is searched to see if there is information to restore. The cache is effective per instance of a directory. If a directory is deleted, the cache for it is removed.
Also coping from an untrusted source will change last modified for sure.
Also there are rules for copy versus move.
Also files need to be wholey within Windows eco system for windows rules to apply for sure.
Related
Scenario
I have an excel file that contains data. There are multiple users accessing the file at the same time.
Problem
There will be problem if multiple users tried to input data to that excel file at the same time due to only one user is allowed to open the file at one time
Question
Is there any way whereby I can update the excel file (Eg: add a value to a cell, delete a value from a cell, find a particular cell etc) without opening it so that multiple users can update it at the same time using excel VBA?
I went to the direction of using shared files. But later found out to be excel shared files are very buggy. If use shared file, excel/macro can be very slow, intermittent crashes and sometime the whole file may get corrupted and could not be opened or repaired afterwards. Also depends on how many users use the file, the file size can grow quite big. So it is best not to use shared workbook. Totally not worth trying. Instead if need multiple users to update data simultaneously, it is better to use some database such as MSAccess, MSSql (Update MSSQL from Excel) etc with excel. For my situation since number of users are less, I didn't use any database, instead put a prompt for the user to wait until the other user close that file. Please see the codes below to check if a file is opened and if so, to prompt user. I got this code from stack overflow itself and I modified to suit my needs.
Call the module TestFileOpened as below.
Sub fileCheck()
Call TestFileOpened(plannerFilePathTemp)
If fileInUse = True Then
Application.ScreenUpdating = True
Exit Sub
End If
End Sub
Here plannerFilePathTemp is the temporary file location of your original file. Whenever an excel file opened, a temp file will be created. For example, your original file location is as below
plannerFilePath = "C:\TEMP\XXX\xxx.xlsx"
Thus your temporary file location will be
plannerFilePathTemp = "C:\TEMP\XXX\~$xxx.xlsx"
or in other words, temporary file name will be ~$xxx.xlsx
The following codes will be called upon Call TestFileOpened(plannerFilePathTemp)
Public fileInUse As Boolean
Sub TestFileOpened(fileOpenedOrNot As String)
Dim Folder As String
Dim FName As String
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(fileOpenedOrNot) Then
fileInUse = True
MsgBox "Database is opened and using by " & GetFileOwner(fileOpenedOrNot) & ". Please wait a few second and click again", vbInformation, "Database in Use"
Else
fileInUse = False
End If
End Sub
Function GetFileOwner(strFileName)
Set objWMIService = GetObject("winmgmts:")
Set objFileSecuritySettings = _
objWMIService.Get("Win32_LogicalFileSecuritySetting='" & strFileName & "'")
intRetVal = objFileSecuritySettings.GetSecurityDescriptor(objSD)
If intRetVal = 0 Then
GetFileOwner = objSD.Owner.Name
Else
GetFileOwner = "Unknown"
End If
End Function
I encountered Out of memory issues also when used shared files. So during the process, I figured out the following methods to minimize memory consumption
Some tips to clear memory
As part of a larger macro Excel retrieves .dat files from a folder. After a crash and rebooting, the macro no longer works and seizes up upon trying to refresh.
There was also changes in security upon reboot where I had to enable all macros to be able to step though this current one.
I have double checked to make sure the path is correct and the files are still there.
Updated code and ended up crashing for unrelated memory issue. Fixed the memory problem and now won't run and is giving the same error code and message as before even with updated code. Current code which will run through the first loop but fails on the second.
If I am not mistaken, Dir just returns the filename found within that directory and not the full path to that file. What likely happened is your directory was initially set to F: so the macro used this as the default path when searching for the file. The best way to do this would be to store your directory in a constant string, and then append the two together. Something like this:
Const fPath as String = "F:YourPathHere\"
strFile = fPath & Dir(fPath & "*.dat")
Debug.Print strFile ' Just to make sure it is setting properly.
I have recently started getting System.UnauthorizedAccessException errors when using File.AppendAllText to write to a shared drive on the network. I think there were some changes to the network when this happened. The code in my application hasn't changed.
I have asked our IT dept to grant me full permission to the folder. I can see I have permissions for Modify, Read & Execute, Read, Write under my username if I navigate to the file and look at the Security tab under properties. I am also part of a group with read, write and modify permissions to the folder.
This works without error in the same folder:
File.WriteAllText(myFile, myText)
This generates a System.UnauthorizedAccessException error when it reaches the AppendallText:
If File.Exists(myFile) = False Then
' Create a file to write to.
Dim createText As String = logTime & " " & report_data
File.WriteAllText(myFile, createText)
Else
Dim appendText As String = logTime & " " & report_data
File.AppendAllText(myFile, appendText)
End If
I have tried deleting the file and creating it again, that made no difference.
I tried File.SetAttributes(myFile, FileAttributes.Normal)
The IT dept can't see what the problem is.
I can manually open, change and modify the file. The problem only arises if I am trying to do this programmatically.
Is there a different 'user' which tries to modify files? Could the file be open somehow, or would that generate a different error?
I'm using VB.NET 2012, .net framework 4.5, Windows 8.1
The network changes were the problem. It doesn't seem possible to resolve this as it is. Instead I made a copy of the text data, append my new text to that, delete the file, and save the updated text to a new file.
In Access VBA, I have a procedure I've put together to do this:
Allow the user to select zip file(s)
Extract any files from the zip files to the same directory (In this
specific use-case instance, it is ALWAYS extracting Excel files from
Zip files, never any change, and always using the same password)
Then I want the code to Delete the Zip file after extracting the
.xls file.
Everything works beautifully except the delete file portion. The issue is that when I tell it to delete "FileName.Zip", it is deleting "FileName.Zip" AND "FileName.xls"
Is there any way to make sure that he kill command ONLY deletes what I want it to delete? I've used it before on various occasions, and never had this happen before.
Here is the code I am using:
Dim fd As FileDialog
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim i As Variant
Set db = CurrentDb
Set rs = db.OpenRecordset("tblProjectPath")
Set fd = FileDialog(msoFileDialogFilePicker)
fd.AllowMultiSelect = True
fd.Title = "Select TOC Return File(s) to process"
fd.InitialFileName = rs.Fields("ProjectPath") & "\FilingReports\*.zip"
fd.Show
For Each i In fd.SelectedItems
'Debug.Print i
Debug.Print '------------------------'
Debug.Print i
Unzip (i) 'The bit calling the command line unzip utility to unzip the file - just telling it to extract all files to the current folder.
Debug.Print i
'Kill i
'had to take out the kill bit, b/c it was deleting both the .zip and .xls files which is not desired nor expected
If InStr(i, ".zip") Then
Kill i 'Tried to specify only .zip files even though think I shouldn't need to, but it's still deleting .xls files
End If
Next i
Edit: Add Unzip code to post:
Unzip code:
Sub Unzip(Path As String)
Dim strUnzip As String
Dim QU As String 'quotation mark
QU = Chr(34)
strUnzip = QU & "c:\program files (x86)\winzip\wzunzip" & QU & " -s" & _
"ZipPassword " & _
Path & " " '& _
Call Shell(strUnzip)
End Sub
At this point, I don't really think a "real" answer will come about. However, I'll post what I've decided to do with the particular process I'm writing this code for anyway.
I'm going to use a folder structure to divide up the files:
1. Place zip file(s)
2. Unzip files to a 2nd folder
3. After processing Excel files in 2nd folder, move to a 3rd "complete" folder.
This will get around the deleting wrong files bit.
Also, it appears that the cause for the issue is related to something to do with the call to the WinZip Command Line Unzip utility (wzunzip) in the Unzip code above, or else something with the tool itself. I thought that maybe it was b/c the tool was asking me if I wanted to overwrite existing files, but that wasn't the case, b/c I had the same issue when there were no files to overwrite.
Anyway, I'm attempting to close this one up at this point. Thanks to Wayne G. Dunn for his assistance on this.
I am having trouble deleting files after calling the GetPrivateProfileString command. I have the following code:
'Read the INI File
sb = New StringBuilder(500)
Select Case FileType
Case "Scanner File"
res = GetPrivateProfileString("ScannerSetings", "ScannerType", "", sb, sb.Capacity, Filename)
Case "Scale File"
res = GetPrivateProfileString("ScaleSetings", "ScaleType", "", sb, sb.Capacity, Filename)
End Select
'If the result is a value store it, otherwise move it to unprocessed
If res <> 0 Then InputArray.Add(sb.ToString)
File.Delete(Filename)
After reading the details from the INI file, as soon as I try to delete the file, I am getting the following error: The process cannot access the file 'R:\Drop\011_11_Scanner' because it is being used by another process.
I cannot even delete these files manually until I exit my application.
Any help would be appreciated.
Thanks
I cannot even delete these files manually until I exit my application.
This clearly shows that the file that Filename points to is locked. As long as it's locked, you won't be able to delete it.
Check your code for any file handles you have opened (eg for writing purposes) and did not close.
If you don't close a file after you've opened it, the file is not released and remains in locked state… which practically means it can not be deleted until (a) you close that file-handle, or (b) you close your program, since that's what's holding the file-handle after opening.
EDIT
The next thing that comes to mind is that VB.NET may need special user access rights to remove the INI on recent Windows versions. You can quickly cross-check that by simply executing your application with elevated user rights (eg via right-click menu; run as admin). I can't imagine that that's actually the problem — but it's worth a shot. Should it indeed be the problem, check (and modify) the permissions on the folder your application and/or INI resides in.