Как проверить у файла наличие защиты?

270
03 января 2018, 16:39

При скачивании файла с интернета он маркируется для защиты таким образом:

Как с помощью своего приложения отслеживать файлы с такой пометкой защиты?
Например при перетаскивании файла на приложение.

Answer 1

Скорее всего, вам нужно просто разблокировать файл в случае, если он заблокирован.

Официальный путь — вызовите Powershell-cmdlet Unblock-File. Для этого установите nuget-пакет System.Management.Automation, и воспользуйтесь таким кодом:

using (var ps = PowerShell.Create())
{
    ps.AddCommand("Unblock-File", true);
    ps.AddParameter("LiteralPath", fullPath);
    ps.Invoke();
}

Альтернативный путь — можно воспользоваться знанием о том, что в текущих версиях Windows данные о заблокированном файле содержатся в альтернативном потоке данных NTFS под названием Zone.Identifier, и убрать его через P/Invoke (код одолжен на en.SO):

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile(string name );
public bool Unblock(string fileName) {
    return DeleteFile(fileName + ":Zone.Identifier");
}

Окей, если вам и правда нужно лишь проверить, есть ли защита, придётся поработать с COM-объектами. За блокировку отвечает COM-объект PersistentZoneIdentifier. Код одолжен здесь и здесь, и адаптирован.

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
static class BlockChecker
{
    public static bool IsBlocked(string path)
    {
        object persistZoneId = Activator.CreateInstance(
            Type.GetTypeFromCLSID(Guid.Parse(CLSID_PersistentZoneIdentifier)));
        var zoneIdentifier = (IZoneIdentifier)persistZoneId;
        var persistFile = (IPersistFile)persistZoneId;
        try
        {
            persistFile.Load(path, 0); // STGM_READ
            var id = zoneIdentifier.GetId();
            return id == URLZONE.URLZONE_INTERNET || id == URLZONE.URLZONE_UNTRUSTED;
        }
        catch
        {
            return false;
        }
        finally
        {
            if (persistZoneId != null)
                Marshal.FinalReleaseComObject(persistZoneId);
        }
    }
    const string CLSID_PersistentZoneIdentifier = "0968e258-16c7-4dba-aa86-462dd61e31a3";
    const string IID_IZoneIdentifier = "cd45f185-1b21-48e2-967b-ead743a8914e";
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid(IID_IZoneIdentifier)]
    public interface IZoneIdentifier
    {
        URLZONE GetId();
        void SetId(URLZONE zone);
        void Remove();
    }
    public enum URLZONE : uint
    {
        URLZONE_LOCAL_MACHINE = 0,
        URLZONE_INTRANET = 1,
        URLZONE_TRUSTED = 2,
        URLZONE_INTERNET = 3,
        URLZONE_UNTRUSTED = 4,
    }
}

Пользоваться очевидным образом: BlockChecker.IsBlocked(fullPath).

Если файла не существует, то будет возвращено true, так что проверяйте самостоятельно.

Если что, вы можете и удалить блокировку при помощи

zoneIdentifier.Remove();
persistFile.Save(path, true);
READ ALSO
Ошибка в новом unity3d

Ошибка в новом unity3d

Приветствую! В старой версии unity эта ошибка игнорировалась, в новом не дает с ней запускать игру: Step Offset must be less or equal to <scaled Height> + <scaled Radius>...

374
Как вывести определенные узлы XML?

Как вывести определенные узлы XML?

Нужно вывести дочерние узлы определенного узлаВот xml документ:

266
Начало цикла с новый данных

Начало цикла с новый данных

Есть 3 цикла от 000 до 999, в коде прописано что если число, к примеру доходит до 193, то он дальше не идет(194,

280