Предупреждения безопасности MS Access после изменения атрибутов через параметр CreateFileA OPEN_EXISTING - PullRequest
1 голос
/ 16 апреля 2019

У меня есть код, который показан ниже, главное - внести некоторые изменения в файл .accdb, сохранив существующие атрибуты CreationTime, LastAccessTime и LastWriteTime этого файла.

Все отлично работает, но я столкнулся с этой проблемой: Оригинальные проекты MS Access (тысячи файлов .accdb) содержат макросы VBA. Стандартная политика: «Отключить все макросы с уведомлением». Поэтому, как только пользователь нажал кнопку, файл сохраняет свои предпочтения (только для этого файла) - и это нормально.

Но после того, как я внесу изменения в файл с помощью следующего сценария, он сбрасывает настройки безопасности для этого точного файла, и в следующий раз, когда пользователь открывает базу данных, появляется желтое «Предупреждение о безопасности» (все макросы и активное содержимое совпадают , ничего нового!).

Проблема в том, что у меня есть тысячи файлов accdb. Мне нужно внести небольшие изменения, но сохранить существующие атрибуты. И когда пользователи откроют эти файлы, не должно быть новой панели предупреждений безопасности.

Я могу, но я не хочу:

  • изменить настройки безопасности для активного содержимого

  • сделать эту папку надежной папкой

  • любые другие изменения параметров безопасности, такие как Regedit и так далее.

Я НЕ добавляю никаких макросов или активного контента, сообщение появляется, потому что, я думаю, некоторые настройки после использования CreateFileA были изменены. (например, если я вручную переименую файл, MS Access думает, что это другой файл - и показывает панель безопасности - и это правильно; но почему он появляется после изменения атрибутов файла?)

Спасибо! Постскриптум Мы используем MS Access 2016.


Option Explicit

Public Const GENERIC_WRITE = &H40000000, GENERIC_READ = &H80000000, FILE_ATTRIBUTE_NORMAL = &H80, OPEN_EXISTING = 3

Public Type FileTime:  dwLowDateTime As Long:  dwHighDateTime As Long: End Type

Public Type SYSTEMTIME:  wYear As Integer:  wMonth As Integer:  wDayOfWeek As Integer:  wDay As Integer:  wHour As Integer:  wMinute As Integer:  wSecond As Integer:  wMilliseconds As Integer: End Type

Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFilename As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

Declare Function SetFileTime Lib "kernel32" (ByVal hFile As Long, lpCreationTime As FileTime, lpLastAccessTime As FileTime, lpLastWriteTime As FileTime) As Long

Declare Function GetFileTime Lib "kernel32" (ByVal hFile As Long, lpCreationTime As FileTime, lpLastAccessTime As FileTime, lpLastWriteTime As FileTime) As Long

Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FileTime) As Long

Declare Function LocalFileTimeToFileTime Lib "kernel32" (lpFileTime As FileTime, lpLocalFileTime As FileTime) As Long

Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FileTime, lpSystemTime As SYSTEMTIME) As Long

Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpLocalFileTime As FileTime, lpFileTime As FileTime) As Long

Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public GlobCreationDate As Date, GlobLastAccess As Date, GlobLastWrite As Date

Public FileAddress As String



Function DTtoFT(ByVal DT As Date) As FileTime 'DateTimeToFileTime
Dim ST As SYSTEMTIME, lTime As FileTime
ST.wYear = Year(DT): ST.wMonth = Month(DT): ST.wDay = Day(DT): ST.wHour = Hour(DT): ST.wMinute = Minute(DT): ST.wSecond = Second(DT)
SystemTimeToFileTime ST, lTime
LocalFileTimeToFileTime lTime, DTtoFT
End Function

Function FTtoDT(FT As FileTime) As Date 'FileTimeToDateTime
Dim lTime As FileTime, ST As SYSTEMTIME
FileTimeToLocalFileTime FT, lTime
FileTimeToSystemTime lTime, ST
FTtoDT = DateSerial(ST.wYear, ST.wMonth, ST.wDay) + TimeSerial(ST.wHour, ST.wMinute, ST.wSecond)
End Function


Sub GetFTime(fName As String, Creation As Date, LastAccess As Date, LastWrite As Date)
Dim hFile As Long, ct As FileTime, at As FileTime, wt As FileTime
hFile = CreateFile(fName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
GetFileTime hFile, ct, at, wt
CloseHandle hFile
Creation = FTtoDT(ct): LastAccess = FTtoDT(at): LastWrite = FTtoDT(wt)
GlobCreationDate = FTtoDT(ct): GlobLastAccess = FTtoDT(at): GlobLastWrite = FTtoDT(wt)
End Sub

Sub SetFTime(fName As String, Optional Creation As Date = -657434, Optional LastAccess As Date = -657434, Optional LastWrite As Date = -657434)
Dim hFile As Long, ct As Date, at As Date, wt As Date

If Creation = -657434 Or LastAccess = -657434 Or LastWrite = -657434 Then
  GetFTime fName, ct, at, wt
  If Creation = -657434 Then Creation = ct
  If LastAccess = -657434 Then LastAccess = at
  If LastWrite = -657434 Then LastWrite = wt
End If

hFile = CreateFile(fName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
SetFileTime hFile, DTtoFT(Creation), DTtoFT(LastAccess), DTtoFT(LastWrite)
CloseHandle hFile
End Sub




Sub SetChanges()
Dim T1 As Date, T2 As Date, T3 As Date, T4 As Date, T5 As Date, T6 As Date
Dim cn As Object, strQuery As String
Dim strPathToDB As String

FileAddress = "D:\Projects\DB1.accdb"

GetFTime FileAddress, T1, T2, T3


'some code right here


SetFTime FileAddress, T1, T2, T3


'
End Sub

1 Ответ

0 голосов
/ 18 апреля 2019

Хорошо, ребята, я нашел решение, так что, возможно, это кому-нибудь поможет.

Причина, по которой MS Access показывал предупреждения системы безопасности, заключается в том, что сценарий технически изменял дату создания, даже если он и былта же дата.

Так что теперь я могу заявить, что MS Access использует дату создания, местоположение файла и имя файла в качестве триггера, я не знаю точно, используются ли они в качестве контрольной суммы или что-то в этом роде, но если вы измените какой-либо изAccess считает, что это может быть другой файл.

Я посмотрел через MS Windows API и обнаружил следующее:

Функция, использующая структуру FILETIME, можетдопускают значения за пределами нуля или положительные значения, обычно указанные членами dwLowDateTime и dwHighDateTime.Например, функция SetFileTime использует 0xFFFFFFFF, чтобы указать, что предыдущее время доступа файла должно быть сохранено.

Поэтому я немного изменил код:

Option Explicit
Public Const GENERIC_WRITE = &H40000000, GENERIC_READ = &H80000000, FILE_ATTRIBUTE_NORMAL = &H80, OPEN_EXISTING = 3
Public Type FileTime:  dwLowDateTime As Long:  dwHighDateTime As Long: End Type
Public Type SYSTEMTIME:  wYear As Integer:  wMonth As Integer:  wDayOfWeek As Integer:  wDay As Integer:  wHour As Integer:  wMinute As Integer:  wSecond As Integer:  wMilliseconds As Integer: End Type
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFilename As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Declare Function SetFileTime Lib "kernel32" (ByVal hFile As Long, lpCreationTime As FileTime, lpLastAccessTime As FileTime, lpLastWriteTime As FileTime) As Long
Declare Function GetFileTime Lib "kernel32" (ByVal hFile As Long, lpCreationTime As FileTime, lpLastAccessTime As FileTime, lpLastWriteTime As FileTime) As Long
Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FileTime) As Long
Declare Function LocalFileTimeToFileTime Lib "kernel32" (lpFileTime As FileTime, lpLocalFileTime As FileTime) As Long
Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FileTime, lpSystemTime As SYSTEMTIME) As Long
Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpLocalFileTime As FileTime, lpFileTime As FileTime) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public GlobCreationDate As Date, GlobLastAccess As Date, GlobLastWrite As Date
Public FileAddress As String

Function DTtoFT(ByVal DT As Date) As FileTime 
Dim ST As SYSTEMTIME, lTime As FileTime
ST.wYear = Year(DT): ST.wMonth = Month(DT): ST.wDay = Day(DT): ST.wHour = Hour(DT): ST.wMinute = Minute(DT): ST.wSecond = Second(DT)
SystemTimeToFileTime ST, lTime
LocalFileTimeToFileTime lTime, DTtoFT
End Function

Function FTtoDT(FT As FileTime) As Date 
Dim lTime As FileTime, ST As SYSTEMTIME
FileTimeToLocalFileTime FT, lTime
FileTimeToSystemTime lTime, ST
FTtoDT = DateSerial(ST.wYear, ST.wMonth, ST.wDay) + TimeSerial(ST.wHour, ST.wMinute, ST.wSecond)
End Function

Sub GetFTime(fName As String, Creation As Date, LastAccess As Date, LastWrite As Date)
Dim hFile As Long, ct As FileTime, at As FileTime, wt As FileTime
hFile = CreateFile(fName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
GetFileTime hFile, ct, at, wt
CloseHandle hFile
Creation = FTtoDT(ct): LastAccess = FTtoDT(at): LastWrite = FTtoDT(wt)
GlobCreationDate = FTtoDT(ct): GlobLastAccess = FTtoDT(at): GlobLastWrite = FTtoDT(wt)
End Sub



Sub SetFTime(fName As String, Optional Creation As Date = -657434, Optional LastAccess As Date = -657434, Optional LastWrite As Date = -657434)
Dim hFile As Long, ct As Date, at As Date, wt As Date
Dim CreateF As FileTime, AccessF As FileTime

If Creation = -657434 Or LastAccess = -657434 Or LastWrite = -657434 Then
  GetFTime fName, ct, at, wt
  If Creation = -657434 Then Creation = ct
  If LastAccess = -657434 Then LastAccess = at
  If LastWrite = -657434 Then LastWrite = wt
End If

CreateF.dwLowDateTime = 0: CreateF.dwHighDateTime = 0
AccessF.dwLowDateTime = 0: AccessF.dwLowDateTime = 0

hFile = CreateFile(fName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
SetFileTime hFile, CreateF, AccessF, DTtoFT(LastWrite)
CloseHandle hFile
End Sub



Sub SetChanges()
Dim T1 As Date, T2 As Date, T3 As Date
Dim cn As Object, strQuery As String
Dim strPathToDB As String

FileAddress = "D:\Projects\DB1.accdb"

GetFTime FileAddress, T1, T2, T3

'some code right here'

SetFTime FileAddress, T1, T2, T3

End Sub

Как это работает: теперь скрипт не вносит никаких изменений в CreationTime и LastAccessTime и использует предыдущие атрибуты файла.Но он меняет LastWriteTime сразу после выполнения некоторого кода.И, наконец, он работает без сброса безопасности для конечного пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...