Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,14 @@ public class SetServiceCommand : ServiceOperationBaseCommand
}
internal string displayName = null;

/// <summary>
/// Account under which the service should run
/// </summary>
/// <value></value>
[Parameter]
[Credential()]
public PSCredential Credential { get; set; }



/// <summary>
Expand Down Expand Up @@ -1589,6 +1597,7 @@ protected override void ProcessRecord()
{
ServiceController service = null;
string ServiceComputerName = null;
IntPtr password = IntPtr.Zero;
foreach (string computer in ComputerName)
{
bool objServiceShouldBeDisposed = false;
Expand Down Expand Up @@ -1679,9 +1688,9 @@ protected override void ProcessRecord()
continue;
}

// modify startup type or display name
// Modify startup type or display name or credential
if (!String.IsNullOrEmpty(DisplayName)
|| (ServiceStartMode)(-1) != StartupType)
|| (ServiceStartMode)(-1) != StartupType || null != Credential)
{
DWORD dwStartType = NativeMethods.SERVICE_NO_CHANGE;
switch (StartupType)
Expand All @@ -1701,6 +1710,13 @@ protected override void ProcessRecord()
"bad StartupType");
break;
}

string username = null;
if (null != Credential)
{
username = Credential.UserName;
password = Marshal.SecureStringToCoTaskMemUnicode(Credential.Password);
}
bool succeeded = NativeMethods.ChangeServiceConfigW(
hService,
NativeMethods.SERVICE_NO_CHANGE,
Expand All @@ -1710,8 +1726,8 @@ protected override void ProcessRecord()
null,
IntPtr.Zero,
null,
null,
IntPtr.Zero,
username,
password,
DisplayName
);
if (!succeeded)
Expand Down Expand Up @@ -1847,6 +1863,10 @@ protected override void ProcessRecord()
} //End try
finally
{
if (IntPtr.Zero != password)
{
Marshal.ZeroFreeCoTaskMemUnicode(password);
}
if (objServiceShouldBeDisposed)
{
service.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,39 @@ Describe "Set/New-Service cmdlet tests" -Tags "Feature", "RequireAdminOnWindows"
$newServiceCommand.$parameter | Should Be $value
}

It "Set-Service can change credentials of a service" {
try {
$startUsername = "user1"
$endUsername = "user2"
$testPass = "Secret123!"
$servicename = "testsetcredential"
net user $startUsername $testPass /add > $null
net user $endUsername $testPass /add > $null
$password = ConvertTo-SecureString $testPass -AsPlainText -Force
$creds = [pscredential]::new(".\$startUsername", $password)
$parameters = @{
Name = $servicename;
BinaryPathName = "$PSHOME\powershell.exe";
StartupType = "Manual";
Credential = $creds
}
$service = New-Service @parameters
$service | Should Not BeNullOrEmpty
$service = Get-CimInstance Win32_Service -Filter "name='$servicename'"
$service.StartName | Should BeExactly $creds.UserName

$creds = [pscredential]::new(".\$endUsername", $password)
Set-Service -Name $servicename -Credential $creds
$service = Get-CimInstance Win32_Service -Filter "name='$servicename'"
$service.StartName | Should BeExactly $creds.UserName
}
finally {
Get-CimInstance Win32_Service -Filter "name='$servicename'" | Remove-CimInstance -ErrorAction SilentlyContinue
net user $startUsername /delete > $null
net user $endUsername /delete > $null
}
}

It "New-Service can create a new service called '<name>'" -TestCases @(
@{name = "testautomatic"; startupType = "Automatic"; description = "foo" ; displayname = "one"},
@{name = "testmanual" ; startupType = "Manual" ; description = "bar" ; displayname = "two"},
Expand Down