Install windows service via Powershell on Win2012 - Access Denied - powershell

I am running the below but can't work out why I get access denied at the call to New-Service:
param(
[string]$serviceName,
[string]$exePath,
[string]$username,
[string]$password
)
"Attempting to install service '$serviceName' - '$exePath'"
$secpassword = convertto-securestring -String $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $secpassword)
$existingService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"
if ($existingService)
{
"'$serviceName' exists already. Stopping."
Stop-Service $serviceName
"Waiting 3 seconds to allow existing service to stop."
Start-Sleep -s 3
$existingService.Delete()
"Waiting 5 seconds to allow service to be un-installed."
Start-Sleep -s 5
}
"Installing the service."
New-Service -BinaryPathName $exePath -Name $serviceName -Credential $cred -DisplayName $serviceName -StartupType Automatic
"Installed the service."
"Starting the service."
Start-Service $serviceName
"Complete."
I have double checked the credentials I pass to the script of course, using 'adminstrator' and 'workgroup\administrator' for the username. I am actually logged in to the machine as administrator.

Have you tried using an elevated Powershell console? Right-Click Powershell > Run as Administrator. This issue happens a lot when running scripts that modify system settings, specially in Windows 2012.

Related

How to remotely start service on Azure VM with powershell 5.1

How can I start a service on an Azure VM remotely? It seems impossible to do without Powershell being "Run as Administrator". Is there a way to launch as admin?
(I would pass in Get-Credential parameter, but unfortunately the 5.1 version Set-Service command does not accept that as a parameter like it does in Powershell version 7.x, and i am limited to 5.1 for now.)
My credentials do have admin level rights on the VM, but i can't seem to figure out a way to pass that via a command.
I am triggering the call like this, where $action is either 'stop' or 'start':
$runCommand = Invoke-AzVMRunCommand `
-ResourceGroupName $rg `
-VMName $vm `
-CommandId 'RunPowerShellScript' `
-ScriptPath $scriptPath `
-Parameter #{action = $action}
The linked script would then execute something like this:
$serviceNames = #("service1, service2")
foreach($serviceName in $serviceNames){
$service = Get-Service -Name $serviceName
if($service){
if($action -ieq "start"){
Set-Service -InputObject $service -Status "Running"
}
}
else{
Write-Output "Service $serviceName not found!"
}
}
When i run from my laptop - it hangs.
When i run from Azure portal via "Run Command" - it hangs.
When i run from the VM itself - it says:
"Service '' cannot be configured due to the following error:
Access is denied
When i run from the VM itself but start Powershell as admin - It works!
Make sure you have to connect with local administrator password which you already configured with your VM.
If you are not able to connect the VM you need to reset your local administrator password/ Remote Desktop Service Configuration as per MS-DOC. We can reset either Azure Portal / VM Access extension and PowerShell.
If you want to connect the Azure VM from your local, you have to signed in with respective Azure subscription.
Use Set-AzVMAccessExtension to reset the local administrator account password.
VM has a single Access Agent. Use the same VM Access Agent which you used earlier.
Workaround
Way 1
Add the user to your VM
$Uname = "<UserName>"
$password = "<Password>"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
New-LocalUser $Uname -Password $securePassword -FullName $Uname -Description "test admin account"
Add-LocalGroupMember -Group "Administrators" -Member $Uname
Way 2
Reset the local Administrator password
$vm = Get-AzVM -ResourceGroupName "<ResourceGroup Name>" -Name "<Resource name>"
$Uname = "<UserName>"
$password = "<Password>"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials= New-Object System.Management.Automation.PSCredential ($Uname, $securePassword)
Set-AzVMAccessExtension -Credential $credentials -ResourceGroupName $vm.ResourceGroupName -VMName $vm.Name -Location $vm.Location -Name VMAccessAgent -TypeHandlerVersion "2.0"
Access the Script file using specific login
Connect-AzAccount
$vm = Get-AzVM -Name "<your vm name>" -ResourceGroupName "<your vm resource group>"
$runCommand = Invoke-AzVMRunCommand `
-ResourceGroupName $rg `
-VMName $vm `
-CommandId 'RunPowerShellScript' `
-ScriptPath $scriptPath `
-Parameter #{action = $action}

PowerShell run Command as different User when Credential Parameter is missing

I need to run a common PowerShell command to trigger a Group Policy Update "gpupdate" on a remote computer out of a workflow.
The workflow runs in a system user context, which do not have the local admin permissions on the clients to force a remote "gpupdate".
For that reason, I import a PowerShell credential secure string with "Import-CliXml" to run that statement in scope of a user which is local admin on the clients.
But, the command I want to use, don't support the native credential parameter. And I need to use a parameter for the remote client.
Invoke-GPUpdate -Computer $client -RandomDelayInMinutes 0
I tried many approches from the internet, but it won't work for me:
Start-Process powershell.exe -Credential $credentials -ArgumentList $ProcessCommand -WorkingDirectory $env:windir -NoNewWindow -PassThru
Start-Process powershell.exe -wait -Credential $credentials -ArgumentList "-command &{Start-Process Powershell.exe -argumentlist '$($cmnd)' -verb runas -wait}"
If I test to send the remote gpupdate out of a PowerShell console started with a user which is local admin on the remote client, it works.
Did anyone has a solution for this problem?
Many thanks!
When I connect to remote computers using PowerShell to execute commands on those computers I normally run the following. I've left an example of my code for you to use to execute Invoke-GPUpdate
#Local Host Computer
#$RequestingServer = $env:COMPUTERNAME
#Server List From Text File
#$ServerList = Get-Content 'C:\temp\servicetest\servers.txt'
#Server List In Script
$ServerList = 'Computer1','Computer2','Computer3','Computer4'
#Domain Admin Account
[STRING]$DomainAccountName = (whoami)
[STRING]$DomainAccountName = $DomainAccountName.Split("\")[1]
[STRING]$DomainAccountPassword = "Password01" #Obviously Change Password
$DomainAccountSecurePassword = $DomainAccountPassword | ConvertTo-SecureString -AsPlainText -Force
$DomainCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $DomainAccountName, $DomainAccountSecurePassword
#Local Server Admin Account
[STRING] $LocalUser = "Administrator" #Obviously Change Account
[STRING] $LocalPassword = "Password01" #Obviously Change Password
$LocalSecurePassword = $LocalPassword | ConvertTo-SecureString -AsPlainText -Force
$LocalCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $LocalUser, $LocalSecurePassword
#If running on multiple computers / servers etc. - - See Lines 5 and 8
ForEach($ComputerName in $ServerList) {
#Update Windows Something Locally - See Line 2
#$DomainSession = New-PSSession -Computername $RequestingServer -Credential $DomainCredentials
#Update Windows Something Remotely - See Lines 5 and 8
$DomainSession = New-PSSession -Computername $ComputerName -Credential $DomainCredentials
Invoke-Command -Session $DomainSession -ScriptBlock {
#Some commands need the computername currently using localhost...
$GPUpdateServer = $Using:ComputerName
#$GPUpdateServer = $Using:RequestingServer
# enter code of what you plan to do...
Invoke-GPUpdate -Computer $GPUpdateServer -RandomDelayInMinutes 0
}
} End of ForEach Statement
#If running on multiple computers / servers etc. - - See Lines 5 and 8
ForEach($ComputerName in $ServerList) {
#Update Windows Something Locally - See Line 2
#$LocalSession = New-PSSession -Computername $RequestingServer -Credential $LocalCredentials
#Update Windows Something Remotely - See Lines 5 and 8
$LocalSession = New-PSSession -Computername $ComputerName -Credential $LocalCredentials
Invoke-Command -Session $LocalSession -ScriptBlock {
#Some commands need the computername currently using localhost...
$GPUpdateServer = $Using:ComputerName
#$GPUpdateServer = $Using:RequestingServer
# enter code of what you plan to do...
Invoke-GPUpdate -Computer $GPUpdateServer -RandomDelayInMinutes 0
}
} End of ForEach Statement
Facing this problem more in detail, I tested the approach above with the remote PowerShell session. This needs some more preparation in domain for deploying all necessary GPO settings to all clients to make WinRM work.
The remote PowerShell approach works, but I found out that the Invoke-GPUpdate command is only available on clients which have RSAT installed. So only works on a few in clients in IT department.
$Session = New-PSSession -Computername $clientname -Credential $domainAccountWithLocalAdminRights
Invoke-Command -Session $Session -ScriptBlock { Invoke-GPUpdate -Computer $env:ComputerName -RandomDelayInMinutes 0 }
$Session | Remove-PSSession
I switched over to a different approach which worked for me without using remote PS sessions. Completely silent on the client, you will find the triggered gpupdates only in Windows event viewer.
Invoke-Command -ComputerName $clientname -ScriptBlock { gpupdate } -Credential $domainAccountWithLocalAdminRights

Running powershell script fails on windows server salve

I have the below code which runs from Jenkins on windows server 2019 slave:
$Username = $args[0]
$Password = $args[1]
$Env = $args[2]
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
echo "******** Start SQL Deploy ********"
Start-Process -FilePath msbuild -ArgumentList '"Database Services\Database Services.sqlproj"','/t:deploy', '/p:Configuration=Release', '/p:TargetConnectionString=$Env', '/p:BlockOnPossibleDataLoss=True', '/p:TargetDatabase="test_fsdb"','-fl','-flp:logfile=msbuild.log' -wait -LoadUserProfile -credential $cred
Get-Content msbuild.log
echo "******** End SQL Deploy ********"
The parameters comes form Jenkinsfile. I'm using applicative user.
The error is:
Start-Process : This command cannot be run due to the error: The service cannot be started, either because it is
disabled or because it has no enabled devices associated with it.
I was able to run it locally, so I wonder if it's kind of permission issue on the salve...

Powershell remote vistor a share disk by pssession faild on windows server 2016

The system version is WINDOWS SERVER 2016, I use PowerShell to remote the computer then vistor a Shared disk, but it replay to me "The specified server cannot perform the requested operation". It is work on WINDOWS SERVER 2012, is this a problem about remote account right or else?
The Script is like this:
$Password = "xxxxxxxxx"
$UserName= "Jenkinsadmin"
$DestWebServer = "xxx.xxx.xxx.xxx"
$CompanyCode = "xxxxxxxxxxx"
function CreateNasDir($CompanyCode,$NasDir)
{
Write-Host "TT"
if(!(test-path ${NasDir}${CompanyCode}))
{
Write-Host "fff"
new-item -itemtype "directory" -path "${NasDir}${CompanyCode}"
Write-host "HEHE"
Write-Host "DD"
}
Write-Host "YY"
}
$PasswordSecure = ConvertTo-SecureString $Password -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($UserName,$PasswordSecure)
$WebSession = New-PSSession -computername $DestWebServer -credential $Cred
Invoke-Command -Session $WebSession -ScriptBlock ${function:CreateNasDir} -ArgumentList $CompanyCode,"\\xxxxxxxxx\myshare\"
Please check if SMB 1.0 has been configured on the scratched 10.
Run PowerShell as Administrator
Set-SmbClientConfiguration -RequireSecuritySignature 1
Answer Y when prompted to confirm the modification.
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" RequireSecureNegotiate -Value 0 -Force
Then open turn Features on and off to check the SMB 1.0:
Control Panel / Programs and Features / Turn Windows Features On or Off and make sure SMB 1.0/CIFS File Sharing Support is ticked
Check in your windows server 2012r2 whether the SMB checked or not.

run script block as a specific user with Powershell

I am not getting anywhere when using Start-Process / Start-Job cmdlets with -Credential $cred
Problem
I have a service account use in deployment (unattended mode). Previously it has been added to local administrator group. I want to reduce potential damage I could do by removing this user from admin group and explicitly assign folder permissions to this user.
I rather get a permission error than execute something that is reaching out by accident.
Remove-Item "$notdefined\*"
However in this same powershell script i want to be able to elevate to execute things like:
sc.exe
app pool restart
which requires an admin user.
One of my failed attempts
$job = Start-Job -ScriptBlock {
param(
[string]$myWebAppId
)
Import-Module WebAdministration
Write-Host "Will get the application pool of: IIS:\Sites\$myWebAppId and try to restart"
$appPoolName = Get-ItemProperty "IIS:\Sites\$myWebAppId" ApplicationPool
Restart-WebAppPool "$($appPoolName.applicationPool)"
Write-Host "restart of apppool succeeded."
} -Credential $cred -ArgumentList #("appname")
Write-Host "started completed"
Wait-Job $job
Write-Host "wait completed"
Receive-Job $job -Verbose
Write-Host "receive completed"
Hi this might be an example that might work for you let me know if it does.
$global:credentials = new-object -typename System.Management.Automation.PSCredential
$job = Start-Job -ScriptBlock {Get-Service} -Credential $credentials
Wait-Job $job
Receive-Job $job
I ended up enabling WinRM using WinRM quickconfig
I was then able to use Invoke-Command
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
Invoke-Command {
param(
[string]$WebAppName
)
#elevated command here
} -comp $computerName -cred $cred -ArgumentList #("$myWebAppId")
While there's no quick and easy way to do this in PowerShell 2.0, version 3.0 (currently in RC, mostly likely RTW very soon given that Windows 8 RTW will appear on MSDN/Technet tomorrow) supports the notion of configuring remoting endpoints with a custom identity. This would be done with the Register-PSSessionConfiguration cmdlet on the computer where you want the command to run, which may be the local computer. Then, when using Invoke-Command, provide a session with the -Session parameter. The session is created using the New-PSSession cmdlet, which lets you specify the computer and the configuration name (which is tied to the custom identity.)
Clear as mud?