2013-04-02 3 views
5

C#コードのみを使用して、特定のユーザー(おそらくNET SERVICEユーザー)に特定のサービスの開始および停止を許可する方法を教えてください。C#コードを使用して特定のサービスを開始および停止する権限をユーザーに与える方法

私は、私はすでに動作しているサービス、およびフォルダのアクセス許可を設定し、インストールルーチンを持って、サービスをインストールし、[編集] のWindows XPからWindowsの8まで、あらゆる

上で動作するように結果のコードが必要です

サービスでは、更新があるかどうかを確認し、更新されている場合はダウンロードし、更新プログラムを起動してサービスを更新(および終了)します。

updaterプログラムは、サービスexe(およびその他の必要なファイル)を更新し、サービスを再起動する必要があります。

私はリサーチから、個々のサービスを開始したり停止したりする権限をサービスユーザ(この場合はネットワークサービス)に与えることは可能だが、コード内で行うことはapiには分からない。

+3

だけでなく、あなたがその特定のユーザのためのサービスアカウントを作成することができませんでしたか?あなたは現在何を持っていますか。「SOはコード工場ではありません」ということを心に留めておいてください。自分で何かを試してみる必要があるかどうかを報告してください。あなたのためにあなたの仕事をしなさい – MethodMan

+0

私はちょっとした手がかりが必要です。サービスアカウントとは何ですか? –

+0

ちょうどそれを見上げた。関連性があるとは確信していません。なぜなら、質問は「サービスの開始と停止のために私のサービスのアカウントの許可をどのように与えるのか」になるからです。または私は何かを逃していますか? –

答えて

6

私は他の場所からいくつかの手がかりを得て、それを把握するために管理:

[StructLayoutAttribute(LayoutKind.Sequential)] 
struct SECURITY_DESCRIPTOR { 
    public byte revision; 
    public byte size; 
    public short control; 
    public IntPtr owner; 
    public IntPtr group; 
    public IntPtr sacl; 
    public IntPtr dacl; 
} 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool QueryServiceObjectSecurity(IntPtr serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfo, 
    ref SECURITY_DESCRIPTOR lpSecDesrBuf, 
    uint bufSize, 
    out uint bufSizeNeeded); 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool QueryServiceObjectSecurity(SafeHandle serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfo, 
    byte[] lpSecDesrBuf, 
    uint bufSize, 
    out uint bufSizeNeeded); 

[DllImport("advapi32.dll", SetLastError = true)] 
static extern bool SetServiceObjectSecurity(SafeHandle serviceHandle, 
    System.Security.AccessControl.SecurityInfos secInfos, 
    byte[] lpSecDesrBuf); 

public void SetServicePermissions(string service, string username) { 
    System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(service, "."); 
    ServiceControllerStatus status = sc.Status; 
    byte[] psd = new byte[0]; 
    uint bufSizeNeeded; 
    bool ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, 0, out bufSizeNeeded); 
    if (!ok) { 
     int err = Marshal.GetLastWin32Error(); 
     if (err == 122 || err == 0) { // ERROR_INSUFFICIENT_BUFFER 
      // expected; now we know bufsize 
      psd = new byte[bufSizeNeeded]; 
      ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, bufSizeNeeded, out bufSizeNeeded); 
     } else { 
      throw new ApplicationException("error calling QueryServiceObjectSecurity() to get DACL for " + _name + ": error code=" + err); 
     } 
    } 
    if (!ok) 
     throw new ApplicationException("error calling QueryServiceObjectSecurity(2) to get DACL for " + _name + ": error code=" + Marshal.GetLastWin32Error()); 

    // get security descriptor via raw into DACL form so ACE 
    // ordering checks are done for us. 
    RawSecurityDescriptor rsd = new RawSecurityDescriptor(psd, 0); 
    RawAcl racl = rsd.DiscretionaryAcl; 
    DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, racl); 

    // Add start/stop/read access 
    NTAccount acct = new NTAccount(username); 
    SecurityIdentifier sid = (SecurityIdentifier) acct.Translate(typeof(SecurityIdentifier)); 
    // 0xf7 is SERVICE_QUERY_CONFIG|SERVICE_CHANGE_CONFIG|SERVICE_QUERY_STATUS| 
    // SERVICE_START|SERVICE_STOP|SERVICE_PAUSE_CONTINUE|SERVICE_INTERROGATE 
    dacl.AddAccess(AccessControlType.Allow, sid, 0xf7, InheritanceFlags.None, PropagationFlags.None); 

    // convert discretionary ACL back to raw form; looks like via byte[] is only way 
    byte[] rawdacl = new byte[dacl.BinaryLength]; 
    dacl.GetBinaryForm(rawdacl, 0); 
    rsd.DiscretionaryAcl = new RawAcl(rawdacl, 0); 

    // set raw security descriptor on service again 
    byte[] rawsd = new byte[rsd.BinaryLength]; 
    rsd.GetBinaryForm(rawsd, 0); 
    ok = SetServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, rawsd); 
    if (!ok) { 
     throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error()); 
    } 
} 
+0

"サービスのDACLを変更する" https://msdn.microsoft.com/en-us/library/windows/desktop/ms684215(v=vs.85).aspx – Liviu

関連する問題