/// <summary> /// In this function, we assume the caller has already checked that the user does not exist. /// Check it using ExistsLocalAccount method /// </summary> /// <param name="username"></param> /// <param name="password"></param> /// <param name="isAdmin"></param> /// <param name="schedulerOnAzure"></param> internal static void AddLocalAccount(string username, SecureString password, bool isAdmin, bool schedulerOnAzure) { CredentialNativeMethods.USER_INFO_1 info = new CredentialNativeMethods.USER_INFO_1(); info.sUsername = username; if (password == null) { info.sPassword = Marshal.StringToCoTaskMemUni(String.Empty); } else { info.sPassword = Marshal.SecureStringToCoTaskMemUnicode(password); } info.uiPriv = CredentialNativeMethods.USER_PRIV_USER; info.sHome_Dir = null; info.sComment = null; info.sScript_Path = null; info.uiFlags = CredentialNativeMethods.UF_SCRIPT; // Check the string length to prevent memory overflow if (info.sUsername.Length > 128) { throw new ArgumentException("The user name is too long."); } if (password != null && password.Length > 512) { throw new ArgumentException("The password is too long."); } try { uint errParam = 0; int errCode = CredentialNativeMethods.NetUserAdd(null, 1, ref info, out errParam); if (errCode != CredentialNativeMethods.NERR_Success) { switch (errCode) { case CredentialNativeMethods.NERR_UserExists: throw new ArgumentException("The local user " + username + " already exists."); case CredentialNativeMethods.NERR_PasswordTooShort: throw new ArgumentException("The password given is too short."); default: throw new Exception("Error when trying to create local account " + username + " exists. Error code: " + errCode + ", sub-error: " + errParam); } } } finally { if (info.sPassword != IntPtr.Zero) { try { Marshal.ZeroFreeCoTaskMemUnicode(info.sPassword); } catch { } } } AddUserGroups(username, isAdmin, schedulerOnAzure); }