如何以编程方式调用Windows权限对话框?

我正在尝试编写证书管理器,我想管理证书文件的权限。 我不希望重新发明Windows权限对话框的轮子,所以理想情况下会有某种shell命令,我可以传递其权限被管理的项目的路径。 然后,我可以调用它并让shell负责更新权限。

我在这里和那里看到过一些shell函数SHObjectProperties,但是没有明确说明如何使用它。 任何帮助,将不胜感激。

您可以使用ShellExecuteEx显示Windows文件权限对话框(使用“属性”动词和“安全性”参数)。

这将在您的过程中显示如下所示的对话框,文件权限查看和编辑将完全正常运行,就像您通过Windows资源管理器shell获得此对话框一样:

在此处输入图像描述

以下是Windows窗体的示例,其中选择了一个文件,然后显示该文件的安全属性。 我从此Stackoverflow答案中使用了ShellExecuteEx的P / Invoke代码。

 using System; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; namespace FileSecurityProperties { public partial class FileSelectorForm : Form { private static bool ShowFileSecurityProperties(string Filename, IntPtr parentHandle) { SHELLEXECUTEINFO info = new SHELLEXECUTEINFO(); info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info); info.lpVerb = "properties"; info.lpFile = Filename; info.nShow = SW_SHOW; info.fMask = SEE_MASK_INVOKEIDLIST; info.hwnd = parentHandle; info.lpParameters = "Security"; // Opens the file properties on the Security tab return ShellExecuteEx(ref info); } private void fileSelectButton_Click(object sender, EventArgs e) { if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { ShowFileSecurityProperties( openFileDialog.FileName, this.Handle); // Pass parent window handle for properties dialog } } #region P/Invoke code for ShellExecuteEx from https://stackoverflow.com/a/1936957/4486839 [DllImport("shell32.dll", CharSet = CharSet.Auto)] static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct SHELLEXECUTEINFO { public int cbSize; public uint fMask; public IntPtr hwnd; [MarshalAs(UnmanagedType.LPTStr)] public string lpVerb; [MarshalAs(UnmanagedType.LPTStr)] public string lpFile; [MarshalAs(UnmanagedType.LPTStr)] public string lpParameters; [MarshalAs(UnmanagedType.LPTStr)] public string lpDirectory; public int nShow; public IntPtr hInstApp; public IntPtr lpIDList; [MarshalAs(UnmanagedType.LPTStr)] public string lpClass; public IntPtr hkeyClass; public uint dwHotKey; public IntPtr hIcon; public IntPtr hProcess; } private const int SW_SHOW = 5; private const uint SEE_MASK_INVOKEIDLIST = 12; #endregion #region Irrelevant Windows forms code ///  /// Required designer variable. ///  private System.ComponentModel.IContainer components = null; ///  /// Clean up any resources being used. ///  /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code ///  /// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///  private void InitializeComponent() { this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); this.fileSelectButton = new System.Windows.Forms.Button(); this.SuspendLayout(); // // openFileDialog1 // this.openFileDialog.FileName = ""; // // fileSelectButton // this.fileSelectButton.Location = new System.Drawing.Point(52, 49); this.fileSelectButton.Name = "fileSelectButton"; this.fileSelectButton.Size = new System.Drawing.Size(131, 37); this.fileSelectButton.TabIndex = 0; this.fileSelectButton.Text = "Select file ..."; this.fileSelectButton.UseVisualStyleBackColor = true; this.fileSelectButton.Click += new System.EventHandler(this.fileSelectButton_Click); // // FileSelectorForm // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(248, 162); this.Controls.Add(this.fileSelectButton); this.Name = "FileSelectorForm"; this.Text = "File Selector"; this.ResumeLayout(false); } #endregion private System.Windows.Forms.OpenFileDialog openFileDialog; private System.Windows.Forms.Button fileSelectButton; public FileSelectorForm() { InitializeComponent(); } #endregion } static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FileSelectorForm()); } } } 

如果您希望单独获取文件权限对话框,而不是作为常规文件属性对话框中的选项卡,则可以使用aclui.dll ,例如使用EditSecurity函数 ,但这不会为您提供其他要求有权为您处理文件权限处理,因为您必须提供一个接口,如果您沿着该路线行进,它将获取和设置安全属性,并且它看起来像很多编码。

这是一个utilily类,它允许您只拥有安全属性表(而不是shell显示的所有表)。

在此处输入图像描述

你可以在控制台应用程序中这样调用它:

 class Program { [STAThread] static void Main(string[] args) { // NOTE: if the dialog looks old fashioned (for example if used in a console app), // then add an app.manifest and uncomment the dependency section about Microsoft.Windows.Common-Controls PermissionDialog.Show(IntPtr.Zero, @"d:\temp\killroy_was_here.png"); } } 

或者在winform应用程序中这样

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { PermissionDialog.Show(IntPtr.Zero, @"d:\temp\killroy_was_here.png"); } } 

这是主要的课程。 它基本上使用与shell相同的东西,但在它自己的属性表中。

 public static class PermissionDialog { public static bool Show(IntPtr hwndParent, string path) { if (path == null) throw new ArgumentNullException("path"); SafePidlHandle folderPidl; int hr; hr = SHILCreateFromPath(Path.GetDirectoryName(path), out folderPidl, IntPtr.Zero); if (hr != 0) throw new Win32Exception(hr); SafePidlHandle filePidl; hr = SHILCreateFromPath(path, out filePidl, IntPtr.Zero); if (hr != 0) throw new Win32Exception(hr); IntPtr file = ILFindLastID(filePidl); System.Runtime.InteropServices.ComTypes.IDataObject ido; hr = SHCreateDataObject(folderPidl, 1, new IntPtr[] { file }, null, typeof(System.Runtime.InteropServices.ComTypes.IDataObject).GUID, out ido); if (hr != 0) throw new Win32Exception(hr); // if you get a 'no such interface' error here, make sure the running thread is STA IShellExtInit sei = (IShellExtInit)new SecPropSheetExt(); sei.Initialize(IntPtr.Zero, ido, IntPtr.Zero); IShellPropSheetExt spse = (IShellPropSheetExt)sei; IntPtr securityPage = IntPtr.Zero; spse.AddPages((p, lp) => { securityPage = p; return true; }, IntPtr.Zero); PROPSHEETHEADER psh = new PROPSHEETHEADER(); psh.dwSize = Marshal.SizeOf(psh); psh.hwndParent = hwndParent; psh.nPages = 1; psh.phpage = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteIntPtr(psh.phpage, securityPage); // TODO: adjust title & icon here, also check out the available flags psh.pszCaption = "Permissions for '" + path + "'"; IntPtr res; try { res = PropertySheet(ref psh); } finally { Marshal.FreeHGlobal(psh.phpage); } return res == IntPtr.Zero; } private class SafePidlHandle : SafeHandle { public SafePidlHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid { get { return handle == IntPtr.Zero; } } protected override bool ReleaseHandle() { if (IsInvalid) return false; Marshal.FreeCoTaskMem(handle); return true; } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct PROPSHEETHEADER { public int dwSize; public int dwFlags; public IntPtr hwndParent; public IntPtr hInstance; public IntPtr hIcon; public string pszCaption; public int nPages; public IntPtr nStartPage; public IntPtr phpage; public IntPtr pfnCallback; } [DllImport("shell32.dll")] private static extern IntPtr ILFindLastID(SafePidlHandle pidl); [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern int SHILCreateFromPath(string pszPath, out SafePidlHandle ppidl, IntPtr rgflnOut); [DllImport("shell32.dll")] private static extern int SHCreateDataObject(SafePidlHandle pidlFolder, int cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out System.Runtime.InteropServices.ComTypes.IDataObject ppv); [DllImport("comctl32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr PropertySheet(ref PROPSHEETHEADER lppsph); private delegate bool AddPropSheetPage(IntPtr page, IntPtr lParam); [ComImport] [Guid("1f2e5c40-9550-11ce-99d2-00aa006e086c")] // this GUID points to the property sheet handler for permissions private class SecPropSheetExt { } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214E8-0000-0000-C000-000000000046")] private interface IShellExtInit { void Initialize(IntPtr pidlFolder, System.Runtime.InteropServices.ComTypes.IDataObject pdtobj, IntPtr hkeyProgID); } [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("000214E9-0000-0000-C000-000000000046")] private interface IShellPropSheetExt { void AddPages([MarshalAs(UnmanagedType.FunctionPtr)] AddPropSheetPage pfnAddPage, IntPtr lParam); void ReplacePage(); // not fully defined, we don't use it } } 

Opps我糟糕的’attrib’是以前的样子。

您要做的我相信是“更改文件夹和文件的安全描述符”。 命令行工具是cacls。

请参阅: http : //en.wikipedia.org/wiki/Cacls