[Résolu][C#] Modifier un Windows Service déjà installé

Bonjour la zone,

Je cherche un moyen de modifier le nom d’utilisateur et le mot de passe d’un service déjà existant, en C#.

J’ai fait quelques recherches, mais tout ce que j’ai trouvé avait l’air de sous-entendre qu’il fallait passer par des P/Invoke pour le faire.

Avant de me lancer là-dedans je voulais donc poser la question ici, histoire de pas faire du boulot pour rien.

Merci d’avance :slight_smile:

Je n’ai peut être pas compris ce que tu demandes, mais sinon c’est relativement simple :

clic-droit sur le poste de travail, gérer, services et applications, services, clic droit sur ton service, propriétés, connexions, et là tu rentres le nom et le mot de passe idoine. TADAM :). Attention aux droits du compte utilisé (j’ai déjà eu des mauvaises surprises !).

[quote=“darkhy, post:2, topic: 48055”]Je n’ai peut être pas compris ce que tu demandes, mais sinon c’est relativement simple :

clic-droit sur le poste de travail, gérer, services et applications, services, clic droit sur ton service, propriétés, connexions, et là tu rentres le nom et le mot de passe idoine. TADAM :). Attention aux droits du compte utilisé (j’ai déjà eu des mauvaises surprises !).[/quote]

Je crois qu’il veut le faire au travers d’une application qu’il va coder en C# :crying:

Oupse, je croyais que le service était écrit en C#, point.

As tu regardé si c’était faisable par la base de registre ?

Sinon tu peux aussi faire appel depuis ton code à l’utilitaire sc (sc \serverX config TonService password= xxxx).

Tiens je viens de retomber sur mon propre thread. Comme j’ai trouvé la réponse, je la mets ici, peut-être que ça pourra servir à quelqu’un.

Je me suis aidé de l’excellent site PInvoke.net et en particulier de cette page.

J’ai ajouté dessus une version quasi-identique à celle que j’ai implémenté.

C’est une classe utilitaire qui permet à la fois de récupérer et de modifier les infos d’un service existant.

Je la copie-colle ici :
[codebox]namespace Services
{
///


/// Some wrappers around Win32 calls dealing with services.
///

public class ServiceConfigurator
{
[StructLayout(LayoutKind.Sequential)]
private struct QueryServiceConfigStruct
{
public int serviceType;
public int startType;
public int errorControl;
public IntPtr binaryPathName;
public IntPtr loadOrderGroup;
public int tagID;
public IntPtr dependencies;
public IntPtr startName;
public IntPtr displayName;
}

        public struct ServiceInfo
        {
            public int serviceType;
            public int startType;
            public int errorControl;
            public string binaryPathName;
            public string loadOrderGroup;
            public int tagID;
            public string dependencies;
            public string startName;
            public string displayName;
        }

        #region constants
        private enum SCManagerAccess : int
        {
            GENERIC_ALL = 0x10000000
        }
        private enum ServiceAccess : int
        {
            QUERY_CONFIG = 0x1,
            CHANGE_CONFIG = 0x2,
        }
        private const int SERVICE_NO_CHANGE = 0xFFFF;
        #endregion

        #region DllImports
        [DllImport("advapi32.dll",
        SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr OpenSCManager(
        [MarshalAs(UnmanagedType.LPTStr)]
        string machineName,
        [MarshalAs(UnmanagedType.LPTStr)]
        string databaseName,
        int desiredAccess);

        [DllImport("advapi32.dll",
        SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr OpenService(
        IntPtr scManager,
        [MarshalAs(UnmanagedType.LPTStr)]
        string serviceName,
        int desiredAccess);

        [DllImport("advapi32.dll",
        SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int ChangeServiceConfig(
        IntPtr service,
        int serviceType,
        int startType,
        int errorControl,
        [MarshalAs(UnmanagedType.LPTStr)]
        string binaryPathName,
        [MarshalAs(UnmanagedType.LPTStr)]
        string loadOrderGroup,
        IntPtr tagID,
        [MarshalAs(UnmanagedType.LPTStr)]
        string dependencies,
        [MarshalAs(UnmanagedType.LPTStr)]
        string startName,
        [MarshalAs(UnmanagedType.LPTStr)]
        string password,
        [MarshalAs(UnmanagedType.LPTStr)]
        string displayName);

        [DllImport("advapi32.dll",
        SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int QueryServiceConfig(
        IntPtr service,
        IntPtr queryServiceConfig,
        int bufferSize,
        ref int bytesNeeded);
        #endregion

        public static ServiceInfo GetServiceInfo(string ServiceName)
        {
            if (ServiceName.Equals(""))
                throw new NullReferenceException("ServiceName must contain a valid service name.");
            IntPtr scManager = OpenSCManager(".", null,
            (int)SCManagerAccess.GENERIC_ALL);
            if (scManager.ToInt32() <= 0)
                throw new Win32Exception();

            IntPtr service = OpenService(scManager,
            ServiceName, (int)ServiceAccess.QUERY_CONFIG);
            if (service.ToInt32() <= 0)
                throw new NullReferenceException();

            int bytesNeeded = 5;
            QueryServiceConfigStruct qscs = new QueryServiceConfigStruct();
            IntPtr qscPtr = Marshal.AllocCoTaskMem(0);

            int retCode = QueryServiceConfig(service, qscPtr,
            0, ref bytesNeeded);
            if (retCode == 0 && bytesNeeded == 0)
            {
                throw new Win32Exception();
            }
            else
            {
                qscPtr = Marshal.AllocCoTaskMem(bytesNeeded);
                retCode = QueryServiceConfig(service, qscPtr,
                bytesNeeded, ref bytesNeeded);
                if (retCode == 0)
                {
                    throw new Win32Exception();
                }
                qscs.binaryPathName = IntPtr.Zero;
                qscs.dependencies = IntPtr.Zero;
                qscs.displayName = IntPtr.Zero;
                qscs.loadOrderGroup = IntPtr.Zero;
                qscs.startName = IntPtr.Zero;

                qscs = (QueryServiceConfigStruct)
                Marshal.PtrToStructure(qscPtr,
                new QueryServiceConfigStruct().GetType());
            }

            ServiceInfo serviceInfo = new ServiceInfo();
            serviceInfo.binaryPathName =
            Marshal.PtrToStringAuto(qscs.binaryPathName);
            serviceInfo.dependencies =
            Marshal.PtrToStringAuto(qscs.dependencies);
            serviceInfo.displayName =
            Marshal.PtrToStringAuto(qscs.displayName);
            serviceInfo.loadOrderGroup =
            Marshal.PtrToStringAuto(qscs.loadOrderGroup);
            serviceInfo.startName =
            Marshal.PtrToStringAuto(qscs.startName);

            serviceInfo.errorControl = qscs.errorControl;
            serviceInfo.serviceType = qscs.serviceType;
            serviceInfo.startType = qscs.startType;
            serviceInfo.tagID = qscs.tagID;

            Marshal.FreeCoTaskMem(qscPtr);
            return serviceInfo;
        }

        public static void ChangeAccount(string ServiceName,
        string Username, string Password)
        {
            ServiceInfo serviceInfo = GetServiceInfo(ServiceName);

            IntPtr scManager = OpenSCManager(".", null,
            (int)SCManagerAccess.GENERIC_ALL);
            if (scManager.ToInt32() <= 0)
                throw new Win32Exception();

            IntPtr service = OpenService(scManager,
            ServiceName, (int)ServiceAccess.CHANGE_CONFIG);
            if (service.ToInt32() <= 0)
                throw new Win32Exception();

            if (ChangeServiceConfig(service, serviceInfo.serviceType,
            serviceInfo.startType, serviceInfo.errorControl,
            serviceInfo.binaryPathName, serviceInfo.loadOrderGroup,
            IntPtr.Zero, serviceInfo.dependencies,
            Username, Password, serviceInfo.displayName) == 0)
            {
                throw new Win32Exception();
            }
        }
    }
}[/codebox]

Moins compliqué que ce que je pensais les P/Invoke finalement. Par contre ma solution ne marchera que sur des machines Windows… en attendant que le framework soit amélioré pour prendre en compte ces options.