首页 > 解决方案 > 使用 Win32 API 移动文件时自动设置安全属性?(C#)

问题描述

我目前正在开发一个必须将文件移动到另一个应用程序文件夹的应用程序。但其他应用程序必须对复制的文件具有特定权限。当我使用 Win32 API 来 MoveFileFromApp(它是 uwp 应用程序)时,它不会更新安全属性以继承文件夹。这是 MoveFile (C#) 的代码

    [DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall,
    SetLastError = true)]
    internal static extern bool MoveFileFromApp(
        string lpExistingFileName,
        string lpNewFileName
    );

有谁知道如何在移动时自动为文件夹设置这些安全权限?非常感谢 !(对不起,不清楚的问题......)

标签: c#fileuwp

解决方案


我尝试通过以下代码在 UWP 应用程序中使用P/InvokeSetNamedSecurityInfo方法。UWP 应用程序中始终存在错误ERROR_ACCESS_DENIED (错误代码为 5)。但是在Win32中,使用带有值的方法来继承安全属性是成功的。SetNamedSecurityInfoUNPROTECTED_DACL_SECURITY_INFORMATION

在 UWP 中,对文件系统访问权限有一些限制。虽然SetNamedSecurityInfo可以成功调用该方法,但它并没有按预期工作。

在 UWP 中使用 SetNamedSecurityInfo 方法的代码:

public uint DACL_SECURITY_INFORMATION = 0x00000004;
public uint UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000;
public uint ACL_REVISION = 0x2;

[StructLayout(LayoutKind.Sequential)]
public struct ACL
{
    public byte AclRevision;
    public byte Sbz1;
    public ushort AclSize;
    public ushort AceCount;
    public ushort Sbz2;
}
public enum SE_OBJECT_TYPE
{
    SE_UNKNOWN_OBJECT_TYPE = 0,
    SE_FILE_OBJECT,
    SE_SERVICE,
    SE_PRINTER,
    SE_REGISTRY_KEY,
    SE_LMSHARE,
    SE_KERNEL_OBJECT,
    SE_WINDOW_OBJECT,
    SE_DS_OBJECT,
    SE_DS_OBJECT_ALL,
    SE_PROVIDER_DEFINED_OBJECT,
    SE_WMIGUID_OBJECT,
    SE_REGISTRY_WOW64_32KEY,
    SE_REGISTRY_WOW64_64KEY,
}

[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool MoveFileFromAppW(
    string lpExistingFileName,
    string lpNewFileName);

[DllImport("advapi32.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern uint SetNamedSecurityInfo(
    string lpFileName,
    SE_OBJECT_TYPE ObjectType,
    uint SecurityInfo,
    IntPtr psidOwner,
    IntPtr psidGroup,
    ref ACL pDacl,
    IntPtr pSacl);

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool InitializeAcl(ref ACL pAcl, int nAclLength, uint dwAclRevision);

[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
internal static extern bool MoveFileFromApp(
string lpExistingFileName,
string lpNewFileName
);

public void SetFilePermission(string FileName)
{//Use the method to let the file inherit the security attributes from parent object
    bool ret = false;
    ACL pDacl = new ACL();
    ret = InitializeAcl(ref pDacl, Marshal.SizeOf<ACL>(), ACL_REVISION);
    uint SecurityInfo = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
    uint err = SetNamedSecurityInfo(FileName, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfo, IntPtr.Zero, IntPtr.Zero, ref pDacl, IntPtr.Zero);

}

推荐阅读