2010-12-19 7 views
5

Jak programowo ustawić poświadczenia "Zaloguj się" dla dowolnej usługi systemu Windows przy użyciu C# (wmi/interop jest w porządku)?Jak ustawić dziennik usługi systemu Windows na poświadczeniach?

Uwaga, mój program jest uruchomiony jako administrator i muszę zmianę do utrzymywania się (dla wszystkich kolejnych restartów serwisowych)

Idealnie metoda ma następujący porządek:

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

Odpowiedz

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

Wybrałem to, ponieważ wiąże się ono z mniejszymi zależnościami i potencjalnie zapewnia bogatszą erę ror messages –

6

ten działa również:

 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

Nie można zmienić poświadczeń na żadne wbudowane konta (puste hasło). Wywołanie invoke wywołuje wyjątek InvalidOperationException z komunikatem "Operacja nie jest poprawna z powodu bieżącego stanu obiektu.". Dzieje się tak zawsze, nawet jeśli usługa jest w stanie zatrzymania. – BrutalDev

Powiązane problemy