2010-12-19 11 views
5

मैं C# (wmi/interop ठीक है) का उपयोग कर मनमाने ढंग से विंडोज सेवा के लिए "लॉग ऑन" क्रेडेंशियल्स को प्रोग्रामेटिक रूप से कैसे सेट करूं?मैं क्रेडेंशियल्स पर विंडोज़ सेवा लॉग कैसे सेट करूं?

ध्यान दें, मेरा कार्यक्रम व्यवस्थापक के रूप में चल रहा है और मैं (बाद के सभी सेवा पुनरारंभ के लिए) लागू करने के लिए परिवर्तन

आदर्श रूप में विधि है निम्नलिखित sig की जरूरत है:

void SetWindowsServiceCreds(string serviceName, string username, string password) 
{ 
    // TODO write me 
} 

उत्तर

7
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, String lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName); 

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); 

[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] 
internal static extern IntPtr OpenSCManager(
    string machineName, 
    string databaseName, 
    uint dwAccess); 

[DllImport("advapi32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool CloseServiceHandle(IntPtr hSCObject); 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded); 

[StructLayout(LayoutKind.Sequential)] 
public class QUERY_SERVICE_CONFIG 
{ 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)] 
    public UInt32 dwServiceType; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)] 
    public UInt32 dwStartType; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)] 
    public UInt32 dwErrorControl; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 
    public String lpBinaryPathName; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 
    public String lpLoadOrderGroup; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)] 
    public UInt32 dwTagID; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 
    public String lpDependencies; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 
    public String lpServiceStartName; 
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] 
    public String lpDisplayName; 
}; 

private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F; 
private const uint SERVICE_QUERY_CONFIG = 0x00001; 
private const uint SERVICE_CHANGE_CONFIG = 0x00002; 
private const uint SERVICE_NO_CHANGE = 0xffffffff; 
private const int ERROR_INSUFFICIENT_BUFFER = 122; 

public static void SetWindowsServiceCreds(string serviceName, string username, string password) 
{ 
    IntPtr hManager = IntPtr.Zero; 
    IntPtr hService = IntPtr.Zero; 
    try 
    { 
     hManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); 
     if (hManager == IntPtr.Zero) 
     { 
      ThrowWin32Exception(); 
     } 
     hService = OpenService(hManager, serviceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); 
     if (hService == IntPtr.Zero) 
     { 
      ThrowWin32Exception(); 
     } 

     if (!ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, username, password, null)) 
     { 
      ThrowWin32Exception(); 
     } 
    } 
    finally 
    { 
     if (hService != IntPtr.Zero) CloseServiceHandle(hService); 
     if (hManager != IntPtr.Zero) CloseServiceHandle(hManager); 
    } 
} 

private static void ThrowWin32Exception() 
{ 
    int error = Marshal.GetLastWin32Error(); 
    Win32Exception e = new Win32Exception(error); 
    throw e;    
} 
+0

मैंने इसे चुना, क्योंकि इसमें कम निर्भरता शामिल है और संभावित रूप से समृद्ध एर प्रदान करता है ror संदेश –

6

यह साथ ही काम करता है:

 void SetWindowsServiceCreds(string serviceName, string username, string password) 
     { 
      string objPath = string.Format("Win32_Service.Name='{0}'", serviceName); 
      using (ManagementObject service = new ManagementObject(new ManagementPath(objPath))) 
      { 
       object[] wmiParams = new object[10]; 

       wmiParams[6] = username; 
       wmiParams[7] = password; 
       service.InvokeMethod("Change", wmiParams); 
      } 

     } 
+0

किसी अंतर्निहित खाते (रिक्त पासवर्ड) में प्रमाण-पत्रों को बदलने के लिए प्रतीत नहीं होता है। आवेदक कॉल संदेश के साथ एक अवैधऑपरेशन अपवाद फेंकता है "ऑब्जेक्ट की वर्तमान स्थिति के कारण ऑपरेशन मान्य नहीं है।"। यह हमेशा होता है भले ही सेवा एक बंद राज्य में है। – BrutalDev

संबंधित मुद्दे