PascalScript в Syncovery
Syncovery включает движок PascalScript, который позволяет во многих отношениях настраивать поведение вашего профиля. PascalScript был добавлен в Syncovery 8, и с момента первого выпуска в него было добавлено множество новых хуков и функций. Чтобы изменить определённое поведение, нужно написать функцию-хук и немного кода. В большинстве случаев наш технический отдел поддержки напишет код за вас. Для более крупных или сложных сценариев, пожалуйста, рассмотрите Подписку на премиум-поддержку, которая включает разработку пользовательских скриптов. Скрипт указывается в профиле с помощью флажка «Pascal Script…» на вкладке категории настроек задания. PascalScript имеют доступ ко всем настройкам профиля и могут читать и изменять их с помощью вспомогательных функций GetProfileProperty и SetProfileProperty.
Полезные готовые скрипты
Следующие скрипты можно использовать как есть — просто вставьте скрипт в диалог PascalScript.
- Сократить длинные пути
Этот сценарий укорачивает имена файлов, если полный путь становится длиннее 250 символов. Он добавляет хэш CRC32 на основе исходного имени файла, чтобы сокращённые имена были уникальными. Имена папок не изменяются. Сокращённые имена используются только при копировании с левой стороны на правую. Левая сторона остаётся без изменений. - Укоротить длинные имена файлов
Этот сценарий укорачивает имена файлов, длина которых превышает 114 символов, добавляя хэш CRC32 на основе исходного имени файла, чтобы гарантировать уникальность укороченных имён. Как и в предыдущем сценарии, имена папок не изменяются, а укороченные имена затрагивают только правую часть. - Преобразование недопустимых для Windows символов
Этот скрипт позволяет использовать недопустимые символы /:\?|<>«* в именах файлов слева. Правая сторона может быть совместимым с Windows хранилищем, например локальным диском NTFS. - Простые уведомления по электронной почте
Этот скрипт упрощает уведомления по электронной почте и легко редактируется для настройки ваших писем. - Отправка уведомлений по электронной почте в зависимости от результата профиля
Этот сценарий вызывает отправку уведомлений по электронной почте только в том случае, если было скопировано менее 10 или более 100 файлов слева направо. - Привязать FTP-подключение к определённому сетевому порту
Этот скрипт позволяет указать, какой сетевой порт использовать для FTP-подключения. Обратите внимание, что это работает только с библиотекой FTP 3 (в Windows) или 2 (на других платформах). - Удалять файлы старше 30 дней с исходной (левой) стороны
Этот сценарий заставит Syncovery удалять более старые файлы с исходной стороны односторонней синхронизации. Исходная сторона должна быть слева. Правая сторона будет служить архивом, где хранятся все исторические файлы, тогда как левая сторона содержит только файлы за последние 30 дней. Предполагается, что новые файлы появляются только слева. Профиль следует использовать только в режиме операции «Standard Copying». Количество дней можно изменить в сценарии. Вы также можете выбрать, удалять ли только что скопированные файлы (маловероятно, поскольку они, вероятно, не старше 30 дней), и/или файлы, которые уже существуют по обеим сторонам на момент запуска задания (более вероятный случай).
Доступные хуки PascalScript
В настоящее время доступны следующие хуки. По мере необходимости будут добавляться новые хуки для выполнения запросов клиентов.
- OnActionComplete
- OnAfterFileCopy
- OnBeforeFileCopy
- OnBeforeFileUpload
- OnBeforeFolderCreate
- OnBeforeMainActionPhase
- OnCanRunProfile
- OnCloudConnect
- OnCloudDisconnect
- OnDownloadComplete
- OnFileCopy
- OnGetCustomHeaders
- OnGetNextRunTime
- OnGetProfilePathBeforeListing
- OnGetProfilePathBeforeCopying
- OnHttpPost
- OnIncludeItem
- OnLogFileClosed
- OnMoveFileToDeletedFolder
- OnNeedToReRun
- OnNoActionItem
- OnNormalizeFilename
- OnProfileStart
- OnProfileResults
- OnProgress
- OnReplaceFilenameLeftToRight
- OnReplaceFilenameRightToLeft
- OnScanFolder
- OnSendEmail
- OnSkipOrIgnoreItem
- OnUploadComplete
- OnVerifySSHServerFingerprint
- OnVerifyTLSCertificate
- OnVolumeShadowComplete
Доступные функции PascalScript
Следующие функции доступны для вызова.
- стандартные функции, такие как Pos, Copy, Length, Ord
- function GetProfileProperty(const fieldname:UnicodeString):UnicodeString;
- function SetProfileProperty(const fieldname:UnicodeString;const val:UnicodeString):Boolean;(эти функции используют те же имена полей, что и формат XML и командная строка. См. словарь настроек в конце страницы командной строки Syncovery)
- function SaveProfileSettings:Boolean;
- procedure LoadFolderPriorityTextFile(const s:UnicodeString);
- function ConcatPath(const a,b:UnicodeString; const t: Int64):UnicodeString;
- function ConcatPathWithDelim(const a,b,delim:UnicodeString):UnicodeString;
- function ExtractFileName(const s: UnicodeString):UnicodeString;
- function ExtractFileNameFTP(const s: UnicodeString):UnicodeString;
- function ExtractFilePath(const s: UnicodeString):UnicodeString;
- function ExtractFilePathFTP(const s: UnicodeString):UnicodeString;
- function ExtractURLPartAfterServer(const s: UnicodeString):UnicodeString;
- function ExtractFileExt(const s: UnicodeString):UnicodeString;
- function ChangeFileExt(const s,t: UnicodeString):UnicodeString;
- function FileExists(const FileName: UnicodeString):Boolean;
- function FileExistsMatching(const FileName: UnicodeString):Boolean;
- function EntryExists(const FileName: UnicodeString):Boolean;
- function FileAge(const FileName: UnicodeString):Double;
- function FileCopy(const ASource,ADest:UnicodeString):Int64;
- function FileDelete(const AFile:UnicodeString):Int64;
- function FileRename(const ASource,ADest:UnicodeString):Int64;
- function ProfileRunning(const s: UnicodeString):Boolean;
- procedure Log(const s:UnicodeString);
- procedure MessageBox(const s:UnicodeString);
- function Execute(const s:UnicodeString; const TimeOutSeconds: Int64):Int64;
- function GetProfileName:UnicodeString;
- procedure SetProfileResult(const AResultText:UnicodeString);
- function CreateS3Connector(const BucketName,AccessID,SecretKey:UnicodeString;const Options:Integer):Opaque;
- function UploadFile(const LocalPath,DestinationPath:UnicodeString;const Connector:Opaque):Int64;
- function CloseConnector(const Connector:Opaque):Int64;
- function ConnFileExists(const Connector:Opaque; const FileName: UnicodeString):Boolean;
- function ConnDirectoryExists(const Connector:Opaque; const Name: UnicodeString):Boolean;
- function ConnCustomFTPCommand(const Connector:Opaque; const ACommand: UnicodeString;
const AOkResponse1,AOkResponse2,AOkResponse3:Integer;
var ResponseText: UnicodeString):Integer; - function ConnProcessWebForm(const Connector:Opaque;
const URL, AFormName, AField1, AValue1, AField2, AValue2: AnsiString;
const SaveResultPage: Boolean;
const SavePageFileName: UnicodeString): Boolean; - function ConnRenameFile(const Connector:Opaque; const AFromFileName,AToFileName: UnicodeString):Boolean;
- function ConnDeleteFile(const Connector:Opaque; const AFileName: UnicodeString):Boolean;
- function ConnDeleteFiles(const Connector:Opaque; const APath,AMask: UnicodeString):Integer;
- function ConnDeleteFilesOlderThan(const Connector:Opaque; const APath,AMask: UnicodeString;const AWhen:Double):Integer;
- function SendHTTPRequest(const requestype,mimetype,additionalheaders,URL,PostData:AnsiString;var ResultCode:Int64;var Response,ErrorResponse:AnsiString):Boolean;
- function StringReplace(const Source, OldPattern, NewPattern: UnicodeString;const CaseSensitive:Boolean): UnicodeString;
- function EncodeBase64(const s: UnicodeString):UnicodeString;
- function DecodeBase64(const s: UnicodeString):UnicodeString;
- function Utf8Encode(const s: UnicodeString):AnsiString;
- function Utf8Decode(const s: AnsiString):UnicodeString;
- function DecodeAnsiURL(const anurl:AnsiString):AnsiString;
- function DecodeUnicodeURL(const anurl:UnicodeString):UnicodeString;
- function UnicodeStringMD5Hex(const s: UnicodeString):UnicodeString;
- function EightBitStringMD5Hex(const s: AnsiString):AnsiString;
- function UnicodeStringMD5Base64(const s: UnicodeString):UnicodeString;
- function EightBitStringMD5Base64(const s: AnsiString):AnsiString;
- function UnicodeStringCRC32Hex(const s: UnicodeString):UnicodeString;
- function EightBitStringCRC32Hex(const s: AnsiString):AnsiString;
- function UnicodeStringCRC32Base64(const s: UnicodeString):UnicodeString;
- function EightBitStringCRC32Base64(const s: AnsiString):AnsiString;
- function SimpleEncrypt(const s: UnicodeString):UnicodeString;
- function SimpleDecrypt(const s: UnicodeString):UnicodeString;
- function AESEncrypt(const s,passphrase: UnicodeString):UnicodeString;
- function AESDecrypt(const s,passphrase: UnicodeString):UnicodeString;
- function ChooseFile(const Prompt,Extension:UnicodeString):UnicodeString;
- function OpenIniFile(const AFileName:UnicodeString):Int64;
- procedure CloseIniFile(const AnIni:Int64);
- function ReadIniString(const AnIni:Int64;const Section,Ident,Default:UnicodeString):UnicodeString;
- function GetInput(const s: UnicodeString):UnicodeString;
- function GetPassword(const s: UnicodeString):UnicodeString;
- function ReadRegistryString(const Key,OptName:UnicodeString):UnicodeString;
- procedure WriteRegistryString(const Key,OptName,Value:UnicodeString);
- function GetProfileRunID:UnicodeString;
- procedure ClearBody;
- function GetBodyLine(const i:Integer):UnicodeString;
- procedure SetBodyLine(const i:Integer;const s:UnicodeString);
- procedure DeleteBodyLine(const i:Integer);
- procedure AddBodyText(const s:UnicodeString);
- function GetActionList:UnicodeString;
- function GetProfileSettings:UnicodeString;
- function Now:Double;
- function NowUTC:Double;
- function OffsetFromUTC:Double;
- function TimeToStr(const DateTime: Double):UnicodeString;
- function DateTimeToStr(const DateTime: Double):UnicodeString;
- function DateToStr(const DateTime: Double):UnicodeString’;
- function DateTimeToStrWithFormat(const DateTime: Double;const FormatString:UnicodeString):UnicodeString;
- function MakeSurePathExists(const s:UnicodeString;const isRightSide:Boolean):Boolean;
- function GetTempDir:UnicodeString;
- function GetTempFilename(const TryCreateIt:Boolean;const Extension:UnicodeString):UnicodeString;
- function PathDelim:UnicodeString;
- function LeftDelim:UnicodeString;
- function RightDelim:UnicodeString;
- function GetDelim(const Connector: Opaque):UnicodeString;
- function IncludeLeadingPathDelim(const s: UnicodeString):UnicodeString;
- function OpenTextFile(const s:UnicodeString):Opaque;
- function AppendTextFile(const s:UnicodeString):Opaque;
- function CreateTextFile(const s:UnicodeString):Opaque;
- procedure WriteLine(const F:Opaque;const ALine:UnicodeString);
- function ReadLine(const F:Opaque):UnicodeString;
- function EOF(const F:Opaque):Boolean;
- procedure CloseFile(const F:Opaque);
- function AtomicAppendTextFileLine(const APath,ALine:UnicodeString):Boolean;(добавляет строку безопасным для многопоточной и многопроцессной работы способом)
- function YearOf(const dt:Double):Integer;
- function MonthOf(const dt:Double):Integer;
- function WeekOf(const dt:Double):Integer;
- function DayOf(const dt:Double):Integer;
- function DayOfTheWeek(const dt:Double):Integer;
- function SecondOf(const dt:Double):Integer;
- function HourOf(const dt:Double):Integer;
- function MinuteOf(const dt:Double):Integer;
- function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Integer): Double;
- function FileToCopyExistsLeft:Boolean;
- function FileToCopyExistsRight:Boolean;
- function FileToCopyLeftSize:Int64;
- function FileToCopyRightSize:Int64;
- function FileToCopyLeftModified:Double;
- function FileToCopyRightModified:Double;
- function CurrentFileModified:Double;
- function CurrentFileCreated:Double;
- function CurrentFileLastAccessed:Double;
- procedure CountDeletedFiles(const Left,Right:Integer);
(можно использовать подстановочные знаки в имени файла, но не в родительских папках)
Доступные глобальные переменные
Эти глобальные переменные обеспечивают прямой доступ к внутренним полям Syncovery. Некоторые из них следует считать доступными только для чтения, а другие предназначены для изменения по мере необходимости.
- ProfileTempDir: UnicodeString;
- LeftBasePath: UnicodeString;
- RightBasePath: UnicodeString;
- ProfileName: UnicodeString;
- ResultSummary: UnicodeString;
- LeftBindIP: UnicodeString;
- RightBindIP: UnicodeString;
- MinimumFreeSpaceLeft: Int64;
- MinimumFreeSpaceRight: Int64;
- MaxWaitWhenFreeSpaceLowSeconds: Integer;
- MinDate: Double;
- MaxDate: Double;
- FilterTimestamps: Boolean;
- FilterOnSourceSideOnly: Boolean;
- FiltersMustMatchOnBothSides:Boolean;
- NeedActionsLog: Boolean;
- UseBinaryCompToAvoidCopying: Boolean;
- RemoveEmptyFoldersOnlyOneLevelWhereAFileHasBeenRemoved: Boolean;
- IgnoreFileSizes: Boolean;
- SkipIfFileSizeChanging: Boolean;
- ActionsLogging: Boolean;
- FreeSpaceLogging: Boolean;
- CopyingStatisticsLogging: Boolean;
- FileCopyNoStatNeeded: Boolean;
- DoSmartTrackingDeletionsEvenIfOtherSideModified: Boolean;
Пример сценария OnActionComplete
Этот хук вызывается после выполнения любого действия, связанного с файлом или папкой, например после копирования, перемещения или удаления файла и т. п. В примере просто ведётся журнал действий. Результат функции Syncovery игнорирует.
function OnActionComplete(const StartTimeUTC, CompletionTimeUTC: Double;
const Success: Boolean;
const ActionStr, DirectionStr, Filename,
LeftFile, RightFile, Subfolder, MovedTo,
ErrorMsg: UnicodeString;
const ResultCode: Int64;
const ErrorSide: UnicodeString;
const ASize,ACompressedSize:Int64):Boolean;
begin
Log('Action Complete: '+ActionStr+' '+DirectionStr+' '+Filename);
Result:=true;
end;
Пример сценария OnAfterFileCopy
Этот хук вызывается после копирования файла. Результат функции Syncovery игнорирует. Он используется в примере сценария «Удалять файлы старше 30 дней из исходной (левой) стороны».
function OnAfterFileCopy(const DirectionIsL2R:Boolean;
const Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString;
const ResultCode:Int64):Boolean;
begin
Log('File Copy Complete: '+Source+' to '+Dest);
Result:=true;
end;
Пример сценария OnCanRunProfile
Этот хук вызывается, когда планировщик собирается запустить профиль. Вы можете решить, нужно ли запускать его сейчас или отложить. В примере хук используется, чтобы не допустить одновременного запуска двух определённых профилей или их пересечения. Этот сценарий нужно вводить как глобальный PascalScript через диалог «Параметры программы», вкладка «Дополнительно».
const p1='Profile Name 1';
p2='Profile Name 2';
function OnCanRunProfile(const ProfileName:UnicodeString; var PostponeBySeconds:Integer):Boolean;
begin
if ProfileName=p1 then
Result:=not ProfileRunning(p2)
else
if ProfileName=p2 then
Result:=not ProfileRunning(p1)
else
Result:=true;
if not Result then
PostponeBySeconds:=60;
end;
Пример сценария OnFileCopy
Этот хук позволяет заменить логику копирования файлов. Верните 0 при успешном выполнении, -1, если Syncovery должен копировать обычным образом, или любое другое значение как код ошибки.
function OnFileCopy(const DirectionIsL2R:Boolean;
const Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString;
const SourceConnector,DestConnector: Opaque):Int64;
begin
Result:=Execute('XCOPY.EXE "'+Source+'" "'+DestPath+'"',60);
end;
Пример сценария OnGetCustomHeaders
Этот хук позволяет добавлять пользовательские HTTP-заголовки к запросам Amazon S3. В будущих версиях Syncovery эту функцию можно будет добавить и для других облачных хранилищ и протоколов (по запросу клиента — просто попросите об этом).
function OnGetCustomHeaders(const RelativePath: UnicodeString;
const URL:AnsiString;var MIMEType, Headers: AnsiString;
const Connector:Opaque):Boolean;
var strDate:string;
begin
Result:=true;
Headers:='Cache-Control: 10';
Log('');
Log('Headers Added to '+RelativePath);
Log(Headers);
Log('');
end;
Пример сценария OnGetNextRunTime
Этот хук позволяет изменять расписание. Лучше всего задать профилю простое регулярное расписание и использовать хук, чтобы пропускать нежелательные времена запуска. Этот пример предназначен для профиля, который должен запускаться «каждый день в XX:YY». Хук гарантирует, что фактически он будет запускаться только в первый будний день месяца.
function OnGetNextRunTime(const LastRun, ProposedNextRun: Double):Double;
var DidItRunThisMonth:Boolean;
begin
Result:=ProposedNextRun;
DidItRunThisMonth:=(MonthOf(LastRun)=MonthOf(Now)) and
(MonthOf(LastRun)=MonthOf(ProposedNextRun)) and
(DayOf(LastRun)<DayOf(ProposedNextRun));
if DidItRunThisMonth then begin
// go to the next month
while DayOf(Result)>1 do
Result:=Result+1;
end
else begin
// go to the next month if we are beyond week #1
while DayOf(Result)>7 do
Result:=Result+1;
end;
// second, advance further until it's not a weekend
while DayOfTheWeek(Result)>=6 do
Result:=Result+1;
end;
Примеры сценариев OnIncludeItem
Обработчик OnIncludeItem вызывается отдельно для каждой стороны синхронизации. Параметр isRightSide указывает, какую сторону мы сейчас рассматриваем.
Следующий сценарий служит для исключения файлов без расширения имени. Такое исключение невозможно задать через маски исключения.
function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isFolder or (Pos('.',FileName)>0);
end;
Второй пример для OnIncludeItem будет обрабатывать только подпапки, содержащие файл READY.toprocess, а также любые подпапки, существующие на правой стороне.
function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isRightSide or not isFolder or
ConnFileExists(Connector,ConcatPath(ConcatPath(LeftBasePath,RelativePath,Connector),FileName,Connector)+
'\READY.toprocess');
end;
Пример сценария OnScanFolder
Это, вероятно, лучший способ искать ‘READY.toprocess’. Хук OnScanFolder вызывается непосредственно перед сканированием папки, и в хуке можно использовать информацию об обеих сторонах.
function OnScanFolder(const FolderLevel: Integer;
const RelativePath, LeftCompletePath, RightCompletePath: UnicodeString;
const LeftExists,RightExists:Boolean;
const LeftConnector, RightConnector: Opaque):Boolean;
begin
Result:=RightExists or ConnFileExists(LeftConnector,LeftCompletePath+'\READY.toprocess');
end;
Пример сценария OnProfileStart
Эта функция может использоваться для проверки или изменения настроек профиля при запуске, включая некоторые функции, которые можно разблокировать только через PascalScript. В примере проверяется, отмечены ли какие-либо флажки «Bypass File Buffering», и они снимаются.
var Checked:Boolean;
function OnProfileStart:Boolean;
begin
Result:=true;
if Checked then
Exit;
Checked:=true;
if (GetProfileProperty('BypassOSFileBufferingLeft')='Yes') or
(GetProfileProperty('BypassOSFileBufferingRight')='Yes') then begin
SetProfileProperty('BypassOSFileBufferingLeft','No');
SetProfileProperty('BypassOSFileBufferingRight','No');
SaveProfileSettings;
Log('');
Log('Bypass File Buffering has been removed via PascalScript.');
end
else begin
Log('');
Log('File buffering settings have been verified via PascalScript.');
end;
end;
Пример сценария OnProfileResults
Этот сценарий ничего не делает, но при завершении профиля функция вызывается с некоторой статистикой. Пример реального применения можно скачать вверху этой страницы («Отправка уведомлений по электронной почте в зависимости от результатов профиля»). Возвращаемое этой функцией значение («Result») игнорируется.
function OnProfileResults(const FilesCopiedL2R,FilesCopiedR2L:Integer;
const FilesToCopyL2R,FilesToCopyR2L:Integer;
const BytesCopiedL2R,BytesCopiedR2L:Int64;
const ResultString:UnicodeString;
const Error:Boolean):Boolean;
begin
Result:=true;
end;
Пример сценария OnNormalizeFilename
Этот хук позволяет «нормализовать» имена файлов, чтобы Syncovery считал имена файлов одинаковыми, несмотря на незначительные различия. В примере сценарий нормализует пробельные символы, так что между другими символами всегда будет только один пробел. Два и более последовательных пробела сводятся к одному. В результате Syncovery считает одинаковыми файлы с разным количеством подряд идущих пробелов в именах по обе стороны профиля. Эти имена файлов на диске не изменяются. Изменение происходит только в памяти, для целей сравнения. В окне предварительного просмотра синхронизации будут показаны нормализованные имена файлов.
function OnNormalizeFilename(const FileName: UnicodeString;
const isFolder, isRightSide: Boolean):UnicodeString;
var Changed:UnicodeString;
begin
Result:=FileName;
repeat
Changed:=StringReplace(Result,' ',' ',true);
if Changed=Result then
break;
Result:=Changed;
until false;
end;
Пример сценария OnReplaceFilenameLeftToRight
Этот сценарий будет переименовывать файлы при копировании слева направо. В нашем примере перед расширением файла добавляется «-draft».
function OnReplaceFilenameLeftToRight(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
begin
if isFolder then
Result:=FileName
else
Result:=ChangeFileExt(FileName,'-draft')+ExtractFileExt(FileName);
end;
Пример сценария OnReplaceFilenameRightToLeft
Если вы выполняете двустороннюю синхронизацию, и новые файлы могут появляться справа, нам также нужен способ переименования в обратном направлении. Этот пример сценария удаляет вставку «-draft» из имён.
function OnReplaceFilenameRightToLeft(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
var ToFind:UnicodeString;
P:Integer;
begin
if isFolder then
Result:=FileName
else begin
ToFind:=''-draft''+ExtractFileExt(FileName);
p:=Pos(ToFind,FileName);
if p>0 then
Result:=Copy(FileName,1,p-1)+ExtractFileExt(FileName)
else
Result:=FileName
end;
end;
Пример сценария OnUploadComplete
Этот сценарий установит для файлов, загруженных по FTP, права доступа 777.
function OnUploadComplete(const FileName, LocalFilePath, CompleteURL: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
var CmdRes:Int64;
ResponseText:UnicodeString;
begin
CmdRes:=ConnCustomFTPCommand(Connector,'SITE CHMOD 777 '+FileName,200,200,200,ResponseText);
Log('Set Permissions for '+FileName+': '+ResponseText);
Result:=true;
end;
Пример сценария OnDownloadComplete
Этот сценарий будет переименовывать загруженные файлы, добавляя дополнительное расширение «.downloaded».
function OnDownloadComplete(const FileName, CompleteURL, LocalFilePath: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
begin
if ConnRenameFile(Connector,CompleteURL,FileName+'.downloaded') then
Log('Renamed '+FileName+' to '+FileName+'.downloaded')
else
Log('Rename failed: '+FileName+' to '+FileName+'.downloaded');
Result:=true;
end;
Пример сценария OnVolumeShadowComplete
Этот сценарий выполнит внешнюю команду (batch- или CMD-файл) сразу после создания теневой копии тома.
function OnVolumeShadowComplete(const Volume,ShadowPath:UnicodeString):Boolean;
begin
Result:=Execute('C:\Tests\test.bat',120)=0;
end;
Пример сценария OnBeforeFolderCreate
Этот сценарий предотвратит создание любых папок, кроме тех случаев, когда это необходимо для копирования файлов в место назначения. Этот хук также можно использовать для изменения путей папок в месте назначения.
function OnBeforeFolderCreate(const DirectionIsL2R:Boolean;
var Source,Dest,Reason:UnicodeString):Boolean;
begin
Result:=false;
end;
Пример сценария OnBeforeFileCopy
Этот сценарий будет изменять пути назначения при копировании (слева направо), добавляя дополнительную подпапку «archive», которой нет на стороне источника.
function OnBeforeFileCopy(const DirectionIsL2R:Boolean;
var Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString):Boolean;
var AddFolderName,NewDestPath,NewDest,NewRightSubPath:UnicodeString;
begin
Result:=true;
if not DirectionIsL2R then
Exit;
AddFolderName:='archive';
NewDestPath:=ConcatPathWithDelim(DestPath,AddFolderName,PathDelim);
NewDest:=ConcatPathWithDelim(NewDestPath,ExtractFileName(Dest),PathDelim);
NewRightSubPath:=IncludeLeadingPathDelim(ConcatPathWithDelim(RightSubPath,AddFolderName,PathDelim));
if not MakeSurePathExists(NewDestPath,true) then begin
Log('Could not create '+NewDestPath);
Exit;
end;
Log('OnBeforeFileCopy');
Log('Source:'+Source);
Log('DestPath:'+DestPath+' changed to '+NewDestPath);
Log('Dest:'+Dest+' changed to '+NewDest);
Log('LeftSubPath:'+LeftSubPath);
Log('RightSubPath:'+RightSubPath+' changed to '+NewRightSubPath);
Log('');
Dest:=NewDest;
DestPath:=NewDestPath;
RightSubPath:=NewRightSubPath;
end;
Пример сценария OnBeforeFileUpload
Этот сценарий вызывается перед загрузкой файла через протокол Интернета и может использоваться для изменения поведения загрузки. Приведённая ниже примерная функция перед загрузкой вызовет антивирусный сканер.
function OnBeforeFileUpload(const DirectionIsL2R:Boolean;
var Source,Dest,DestPath,LeftSubPath,RightSubPath,ErrorMsg:UnicodeString;
var ErrorCode:Int64):Boolean;
begin
if not DirectionisL2R then begin
Result:=true;
Exit;
end;
Result:=Execute('"C:\Program Files\ClamAV\clamscan.exe" '+Source,60)=0;
if Result then
Log('Virus scan OK: '+Source)
else begin
Log('Virus scan failed, not uploading: '+Source);
ErrorMsg:='Virus detected';
ErrorCode:=$E1;
end;
end;
Пример сценария OnHttpPost
Этот хук можно использовать для включения загрузки файлов по протоколу HTTP. Сценарию нужно задать соответствующие заголовки и свойства формы.
function OnHttpPost(const RelativePath : UnicodeString;
var URL, MIMEType, Header : AnsiString; var LAsForm : Boolean;
var LFormData : AnsiString;
const Connector : Opaque) : Boolean;
begin
URL := 'https://ru.syncovery.com';
Header := 'Authorization: Bearer abcdefghijklmnopqrstuvwxyz';
LAsForm := true;
Result := true;
LFormData := 'orderstates';
Log('');
Log('Header Added to '+RelativePath);
Log(Header);
Log('');
end;
Пример скрипта OnGetProfilePathBeforeListing
Этот скрипт использует этот хук, чтобы указать отдельную папку TEMP для профиля. Исходное назначение функции — изменять путь слева или справа и/или учетные данные.
function OnGetProfilePathBeforeListing(const isRightSide:Boolean;
var Path,UserName,Password:UnicodeString;
var AuthKey,AuthKeyPassword:AnsiString;
var Port:Integer):Boolean;
begin
ProfileTempDir:='H:\TEMP';
Result:=true;
end;
Пример скрипта OnGetProfilePathBeforeCopying
Этот хук можно использовать для изменения пути и/или учетных данных. В примере скрипта ничего не делается.
function OnGetProfilePathBeforeCopying(const isRightSide:Boolean;
var Path,UserName,Password:UnicodeString;
var AuthKey,AuthKeyPassword:AnsiString;
var Port:Integer):Boolean;
begin
Result:=true;
end;
Пример скрипта OnBeforeMainActionPhase
Этот скрипт разрешает запуск задания только если нужно скопировать фиксированное число файлов слева направо.
function OnBeforeMainActionPhase(const CopyL2RCount,CopyR2LCount,DeleteLCount,DeleteRCount,MoveLCount,MoveRCount:Int64;
const CopyL2RBytes,CopyR2LBytes,DeleteLBytes,DeleteRBytes,MoveLBytes,MoveRBytes:Int64):Boolean;
begin
if CopyL2RCount=14 then
Result:=true
else begin
Result:=false;
Log('Not continuing because CopyL2RCount is '+IntToStr(CopyL2RCount));
end;
end;
Пример скрипта OnCloudConnect
Этот скрипт можно использовать для входа на веб-сайт при использовании протокола HTTP для загрузки файлов по URL.
function OnCloudConnect(const URL:AnsiString;
const isRightSide,isFirstConnectionInJob:Boolean;
const Connector: Opaque):Boolean;
begin
if isFirstConnectionInJob and not isRightSide then
Result:=ConnProcessWebForm(Connector,
'https://www.superflexible.com/usrlogin.php?',
'login',
'username','tobias',
'password','abcdefghijklmn',
false,'')
else
Result:=true;
end;
Пример скрипта OnCloudDisconnect
Этот обработчик вызывается перед окончательным отключением от облачного или FTP-сервера в конце запуска профиля.
Его можно использовать для выполнения некоторых завершающих действий.
В примере скрипт ничего не делает.
function OnCloudDisconnect(const URL:AnsiString;
const isRightSide,isMainConnectionInJob,isFinalDisconnection:Boolean;
const Connector: Opaque):Boolean;
begin
Log('Before final disconnection');
Result:=true;
end;
Пример скрипта OnLogFileClosed
Этот скрипт копирует файл журнала в другую папку после его закрытия.
function OnLogFileClosed(const FileName:UnicodeString):Boolean;
begin
FileCopy(FileName,'E:\LogCopies\'+ExtractFileName(FileName));
Result:=true;
end;
Пример скрипта OnMoveFileToDeletedFolder
Этот скрипт предотвращает сохранение нескольких версий удалённых файлов, сначала удаляя потенциально существующий файл из папки удалённых файлов.
function OnMoveFileToDeletedFolder(const Path:UnicodeString;
var MoveToPath:UnicodeString;
var proceedToDeleteInsteadOfMoving:Boolean;
const Connector:Opaque):Boolean;
begin
if FileExists(MoveToPath) then FileDelete(MoveToPath);
Result:=true;
end;
Пример скрипта OnNeedToRerun
Этот скрипт заставляет задание выполняться повторно, пока не будет выполнено ожидаемое условие (не будет скопирован хотя бы один файл).
function OnNeedToReRun(const FilesCopiedL2R,FilesCopiedR2L:Integer;
const FilesToCopyL2R,FilesToCopyR2L:Integer;
const BytesCopiedL2R,BytesCopiedR2L:Int64;
const ResultString:UnicodeString;
const Error:Boolean):Boolean;
begin
if FilesCopiedL2R+FilesCopiedR2L>0 then
Result:=false
else
Result:=true;
end;
