CfSetInSyncState ведет себя не так, как задокументировано. (CfAPI)

Я пытаюсь использовать CfSetInSyncState с USN.

документация говорит, что вы можете предоставить USN, и изменение будет выполнено только тогда, когда USN все еще совпадает.

Однако вызов метода для файла NOT_IN_SYNC с текущим номером USN не увенчается успехом. Он возвращает 0x80070179 "ERROR_CLOUD_FILE_NOT_IN_SYNC". Возвращенное значение USN также не изменилось.

У меня есть минимальный образец на github, который продемонстрирует это.

Я пробовал разные флаги для получения дескриптора, а также вместо этого использовал метод CreateFile. Открытие файла также не меняет USN. Но пока я не знаю, я не смог установить SyncState, если был предоставлен USN, и я не смог получить текущий USN из функции.

Как я могу использовать CfSetInSyncState таким образом, чтобы он устанавливал состояние IN_SYNC только тогда, когда USN не изменился.


Редактировать

Я обновил образец, поэтому он очистит потенциальные предыдущие файлы и сгенерирует некоторый вывод:

Cloud sample test!
Try Set In Sync

Created placeholder test1.txt with USN 1631131882568.
Try to set Sync state IN_SYNC
Faild to set InSyncState
USN was NOT changed.


Try Set NOT In Sync

Created placeholder test2.txt with USN 1631131882728.
setting USN variable to -1 But will still work for NOT_IN_SYNC.
Seting Sync state to NOT IN SYNC.
USN was changed now 0.

Я запускаю это в проекте AppPackage, так как это требование CfAPI.

Я ожидаю, что первый блок (установка не синхронизируемого файла для синхронизации) не завершится ошибкой, поскольку USN не изменился до вызова cfSetInSyncState. (Это то, что сейчас меня блокирует)

Я также ожидал бы получить текущий USN, когда метод вернется, даже если он не удался. Но я не уверен в этом. В документации указано ...value after setting the in-sync state..., которое я могу интерпретировать только в случае успеха.

Во втором блоке (синхронизация файла с несинхронизированным) я ожидаю получить текущий номер USN вместо 0.

В настоящее время я пробую разные подходы к открытию дескриптора файла, но пока ничего не помогло. Есть ли ошибка при регистрации SyncRoot, что для его работы должен быть установлен какой-то флаг?


person lokimidgard    schedule 23.03.2020    source источник
comment
При создании нового файла/файла-заполнителя CfSetInSyncState устанавливает CF_IN_SYNC_STATE_NOT_IN_SYNC успех с установкой tmpUsn на ноль. Если файл выходит, CfCreatePlaceholders завершится ошибкой с ошибкой 0x800700b7 (невозможно создать файл, когда файл уже существует). облачный файл запрещен.). Поэтому я не могу воспроизвести вашу проблему. Вы можете попробовать мои тесты или показать, как воспроизвести вашу проблему.   -  person Rita Han    schedule 24.03.2020
comment
@RitaHan-MSFT Спасибо за быстрый ответ. Я обновил код на github. Теперь у меня есть два отдельных файла: один для sync-›NOT_sync и один NOT_sync-›sync. Моя проблема в основном с NOT_sync-›sync. Если вы запустите обновленный пример, я ожидаю, что вы получите тот же результат. (рядом с числовыми значениями)   -  person lokimidgard    schedule 24.03.2020
comment
Я не уверен на 100%, почему этот вопрос был признан оффтопом. Я думаю, что это было расплывчато, может быть. Я попытался конкретизировать свою проблему, поэтому она больше не будет считаться оффтопом. Если бы это было не проблемой, подсказка была бы неплохой ;) Проблема, которая у меня есть I call a Method that does not what I wan/expectt, похоже, связана с программированием.   -  person lokimidgard    schedule 24.03.2020


Ответы (1)


  • Для нового создания заполнителя с помощью CF_PLACEHOLDER_CREATE_FLAG_NONE : чтобы он успешно изменил состояние синхронизации на CfSetInSyncState, вы можете установить для входного USN значение 0 вместо USN, возвращенного из CfCreatePlaceholders.
  • Для нового создания заполнителя с помощью CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC : Либо 0, либо USN, возвращенный из CfCreatePlaceholders в качестве входных данных, успешно изменит состояние синхронизации на CfSetInSyncState.

Я ожидаю, что первый блок (установка не синхронизирующего файла для синхронизации) не выйдет из строя

Отредактированная строка кода: tmpUsn = 0;// usn;

Снимок результата:

введите здесь описание изображения

Обновление: CfSetInSyncState не возвращает фактический номер USN. Вы можете получить фактический USN через DeviceIoControl с FSCTL_READ_FILE_USN_DATA следующим образом:

#define BUF_LEN 1024
// ...

CHAR Buffer[BUF_LEN];
DWORD dwBytes;
HANDLE hFile = INVALID_HANDLE_VALUE;
USN_RECORD_V2* fUsn = NULL;

hFile = CreateFile(TEXT("C:\\Test\\Cloud\\test1.txt"),
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    0,
    NULL);

if (hFile == INVALID_HANDLE_VALUE)
{
    printf("CreateFile failed (%d)\n", GetLastError());
    return;
}

memset(Buffer, 0, BUF_LEN);

if (!DeviceIoControl(hFile,
    FSCTL_READ_FILE_USN_DATA,
    NULL,
    0,
    Buffer,
    BUF_LEN,
    &dwBytes,
    NULL))
{
    printf("Read journal failed (%d)\n", GetLastError());
    return;
}

printf("****************************************\n");

fUsn = (USN_RECORD_V2*)Buffer;

printf("USN: %I64x\n", fUsn->Usn);
printf("File name: %.*S\n",
    fUsn->FileNameLength / 2,
    fUsn->FileName);
printf("Reason: %x\n", fUsn->Reason);

CloseHandle(hFile);

См. Fsutil usn, < a href="https://docs.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_read_file_usn_data" rel="nofollow noreferrer">FSCTL_READ_FILE_USN_DATA IOCTL.

person Rita Han    schedule 24.03.2020
comment
Я знаю, что использование значения USN, равного 0, всегда будет устанавливать состояние синхронизации. Но мне нужно проверить, нет ли новых изменений. Применение: 1. Некоторые файлы были изменены, поэтому они не синхронизированы. 2. Выполните изменения в облаке. 3. Установите Синхронно. Проблема: между 2 и 3 могут произойти новые изменения. Если я использую 0 в качестве USN, файлы будут помечены как синхронизированные, но будут изменения mssing. идеально: 1. Некоторые файлы были изменены, поэтому они не синхронизированы. 2. Получите USN файла. 3. Внесите изменения в облаке. 4. Установите синхронизацию с USN из 2. Это означает, что при успешном выполнении 4 в облаке не будет пропущенных изменений. - person lokimidgard; 24.03.2020
comment
Кроме того, если я использую Zero в качестве USN, он установит SyncState, но в документе также говорится, что при возврате значение [USN] является окончательным USN после операции. При проверке файла с помощью fsutil usn readdata <FILE_NAME> USN, скорее всего, не будет равен нулю (то есть до значения после возврата). Я должен как-то использовать этот метод неправильно. - person lokimidgard; 24.03.2020
comment
@lokimidgard Я могу воспроизвести эту проблему, и CfSetInSyncState, похоже, не возвращает фактический USN. Вы можете получить фактический USN через DeviceIoControl с FSCTL_READ_FILE_USN_DATA в качестве обходного пути. Вы можете обратиться к моему ответу на обновление для примера кода использования этого API. По вопросу документа я проконсультируюсь с соответствующим инженером и сообщу вам, если будет какой-либо прогресс. - person Rita Han; 25.03.2020
comment
Спасибо за обходной путь для получения USN. Кстати, в вашем образце, кажется, отсутствует длина буфера const size_t BUF_LEN = 80; Я предполагаю, что для USN в качестве входных данных нет такого простого обходного пути. - person lokimidgard; 25.03.2020
comment
@lokimidgard Я добавляю определение BUF_LEN. Надеюсь, этот ответ поможет. - person Rita Han; 25.03.2020
comment
Я также пытался использовать CfUpdatePlaceholder в качестве обходного пути для ввода USN, но это также имеет те же проблемы, что и CfSetInSyncState. Я еще не нашел других методов, использующих USN в CFApi. - person lokimidgard; 26.03.2020
comment
Удалось выяснить, как использовать USN в качестве входных данных для CfSetInSyncState? Это важная функция, чтобы узнать, все ли изменения обработаны. В настоящее время он блокирует меня и может привести к сбою нашего проекта :( - person lokimidgard; 30.03.2020
comment
@lokimidgard Я проконсультировался с соответствующим инженером за помощью в этом вопросе и сообщил вам, если есть какой-либо прогресс. - person Rita Han; 30.03.2020
comment
Я знаю, вы говорите мне, есть ли прогресс, но есть ли у вас оценка? Это было бы полезно для планирования. в настоящее время я работаю над этой проблемой на других вещах. Тем не менее, у меня закончились другие темы. Так что я, возможно, буду вынужден заморозить этот проект до тех пор, пока он не будет решен. Даже грубая оценка, например, не в ближайшие 4 месяца, была бы полезной. - person lokimidgard; 16.04.2020
comment
@lokimidgard Я продолжаю следить за этой проблемой и проконсультировался с соответствующим инженером, чтобы узнать, есть ли обновление. - person Rita Han; 16.04.2020