2015-01-19 3 views
5

인증서 관리자를 쓰려고하는데 인증서 파일에 대한 사용 권한을 관리하려고합니다. 나는 윈도우 권한 대화 상자의 바퀴를 재발 명하지 않기를 바란다. 그래서 이상적으로 어떤 권한이 관리되고있는 항목의 경로를 전달할 수있는 일종의 쉘 명령이있을 것이다. 그런 다음 쉘을 호출하여 쉘이 권한을 업데이트하도록 할 수 있습니다.Windows 권한 대화 상자를 프로그래밍 방식으로 호출하는 방법은 무엇입니까?

쉘 함수 SHObjectProperties가 여기 저기에서 언급되었지만 사용 방법은 분명하지 않습니다. 어떤 도움을 주시면 감사하겠습니다.

+0

http://www.codeguru.com/csharp/csharp/cs_webservices/security/article.php/c14315/The-Basics-of-Manipulating-File-Access-Control-Lists-with-C. htm – Plutonix

답변

9

당신은 ("속성"동사와 "보안"매개 변수를 사용하여) ShellExecuteEx를 사용하여 Windows 파일 권한 대화 상자를 표시 할 수 있습니다.

이것은 프로세스 내에서 다음과 같은 대화 상자를 표시합니다, 당신은 윈도우 탐색기 쉘을 통해이 대화 상자를 가지고 한 것처럼 파일 권한보기 및 편집이 완벽하게 작동 될 것입니다 :

enter image description here

다음은 Windows Forms에서 파일을 선택하고 해당 파일의 보안 속성을 표시하는 예제입니다. 나는 this Stackoverflow answer에서 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 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     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 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new FileSelectorForm()); 
     } 
    } 
} 

, 즉, 예를 들어, aclui.dll 사용 가능하다 EditSecurity function을 사용하지만이 방법을 사용하면 파일 사용 권한을 처리해야하는 다른 요구 사항이 없습니다. 왜냐하면 해당 경로를 사용하는 경우 보안 속성을 가져오고 설정하는 인터페이스를 제공해야하기 때문입니다. 그것은 많은 코딩처럼 보입니다.

0

Opps 내 나쁜 'attrib'는 예전과 같습니다.

내가 원하는 것은 "폴더 및 파일의 보안 설명자를 변경하는 것"입니다. 명령 행 도구는 cacls입니다.

참조하십시오 http://en.wikipedia.org/wiki/Cacls

+0

예 ... 관리를 위해 Windows 대화 상자를 호출하려고합니다. 모든 ACL 관리 및 UI 코드를 직접 작성하지 않아도되도록 노력하고 있습니다. 최악의 시나리오, 난 그냥 윈도우 UI를 복제하고 ACL을 직접 관리하지만, 그것은 고통 것입니다 ... –

6

다음은 보안 속성 시트 만 가질 수있는 utilily 클래스입니다 (셸이 표시하는 모든 시트가 아님).

enter image description here

당신은 콘솔 응용 프로그램에서 다음과 같이 호출 할 수 있습니다 :

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"); 
    } 
} 

그리고이 메인 클래스에서이 같은

. 기본적으로 쉘과 동일한 것을 사용하지만 자체 속성 시트에 있습니다.

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 
    } 
} 
관련 문제