Windows服务恢复,无法执行PS脚本

时间:2017-03-10 19:52:07

标签: powershell windows-services windows-server-2012-r2

操作系统:赢取2012 R2

您好,

我尝试设置某些服务,以便在第二次失败时触发powershell脚本,该脚本通过电子邮件发送给某些人。这是通过services > (specific service) > properties > recovery完成的。

尝试了几乎所有可能的程序组合: Powershell.exeC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,与上一个相同,但有资本" P"。

命令行参数:-NoProfile -Executionpolicy bypass C:\users\username\appdata\local\myscript.ps1,脚本路径之后的参数。

脚本未签名。

现在我的脚本使用Send-MailMessage并使用ConvertFrom-SecureString保存密码,我认为实际运行脚本的服务/用户可能无法解密密码,因为它是使用我的管理员帐户创建。

我尝试以运行我要监控的流程的相同服务帐户登录,并从用户创建加密密码文件并将其保存在不要求该用户为admin的路径中(即%localappdata%)但是当我在pskill上使用PID时,脚本仍无法触发。

在PS中手动执行命令时,一切正常,我不会被提示输入任何内容。它完全应该做它。

现在我对Windows管理员场景很陌生,userservice实际触发了PowerShell脚本?它是否与运行服务的身份相同,即我指定的特定服务帐户?还是别的什么?

我很乐意在这里发布代码,但它在我的另一台计算机上,我稍后会用它来更新。谷歌搜索几个小时,几乎尝试了一切,但它可能是我所缺少的基本内容。

非常感谢你的帮助 - TheSwede86

编辑:这是代码,我还尝试了Ronald Rink&#f; d-fens'建议并在我手动执行脚本时显示用户(使用我的用户名显示事件)但不是在我尝试时模拟服务失败。

$PSEmailServer = "<address to smtp-server>"
$SMTPPort = <port>
$SMTPUsername = "<email-address to send from>"
$EncryptedPasswordFile = "<path and filename to pwd-file, currently on C:\>.securestring"
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString
$EmailCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPUsername,$SecureStringPassword
$MailTo = "<email-address to mail to>"
$MailFrom = $SMTPUsername
$hostname = Hostname
$service = Get-Service -Name "<Servicename*>" | Where-Object {$_.Status -eq "Stopped"}
$MailSubject = "ALERT: Service on $hostname has stopped and failed to restart after one attempt"
$MailBody = "$service"
$OtherEmail = "<Other email-address to send to>"
$whoami = whoami
Send-MailMessage -From $MailFrom -To $MailTo -Bcc $OtherEmail -Subject $MailSubject -Body $MailBody -Port $SMTPPort -Credential $EmailCredential -UseSsl -Priority High
Write-EventLog –LogName Application –Source “PowerShell Script Debug” –EntryType Information –EventID 1 -Message $whoami

经过编辑的电子邮件地址,SMTP服务器等。

编辑1:添加了尝试记录执行脚本的用户。

编辑2:@Ronald Rink&#39; d-fens&#39;

我尝试了以下内容:

$PlainPassword = "<passwordForEmailToSendFrom>"
$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force | Out-File -FilePath C:\temp\<filename>.securestring

我让服务失败一次,因此它会将明文密码转换为我在脚本中调用的securestring文件;这不起作用。

如果我尝试你的建议:

1)

$password = "<passwordForEmailToSendFrom>" | ConvertTo-SecureString -asPlainText -Force
$username = "<domain\serviceAccountWhichRunsTheService>" 
$credential = New-Object System.Management.Automation.PSCredential($username,$password)

$credential | Export-CliXml C:\temp\credential.xml

它成功创建了&#34; credential.xml&#34;在我选择的道路上

2)

$credential = Import-CliXml C:\temp\credential.xml
$decryptedCredential = "{0} - {1}" -f $credential.UserName, $credential.GetNetworkCredential().Password
$decryptedCredential | Out-File C:\temp\ServiceRecovery.txt -Append -Force

我在&#34; ServiceRecovery.txt&#34;中得到了未加密的密码。而不是SYSTEM。

我添加了#34; SYSTEM&#34;到本地&#34;管理员&#34; -group再次尝试; 它只是为&#34; ServiceRecovery.txt&#34;添加了另一行。使用我在&#34; 1&#34;中指定的用户名;和未加密的密码。

然而,当我尝试使用哪个用户实际运行脚本并且确实是&#34; SYSTEM&#34;。

时,我确实成功了。

对不起我的错误解释,已经坐了好几个小时试图让这个最后一点排序但无法这样做。

编辑3:

感谢@Ronald Rink&#39; d-fens&#39;我这样解决了:

New-Object System.Management.Automation.PSCredential("<EmailAddressToSendFrom>", (ConvertTo-SecureString -AsPlainText -Force "<PasswordForAboveEmailAccount>")) | Export-CliXml C:\temp\MyCredential.xml

上面将未加密的密码转换为使用API​​(DPAPI)加密,仅可用于创建它的帐户/机器!

使用上述脚本让服务失败一次,以使用SERVICE帐户生成文件

$PSEmailServer = "<smtp-address>"
$SMTPPort = <port>
$SMTPUsername = "<EmailAddressToSendFrom>"
$credpath = Import-Clixml -Path C:\temp\MyCredential.xml
$MailTo = "<EmailAddressToSendTo>"
$MailFrom = $SMTPUsername
$hostname = Hostname
$service = Get-Service -Name "<Servicename(s)>" | Where-Object {$_.Status -eq "Stopped"} | Select-Object -Property DisplayName | Out-String
$MailSubject = "ALERT: Service on $hostname has stopped and failed to restart after one attempt"
$MailBody = $service
$OtherEmail = "<AnotherEmailAddressToSendTo>"
Send-MailMessage -From $MailFrom -To $MailTo -Bcc $OtherEmail -Subject $MailSubject -Body $MailBody -Port $SMTPPort -Credential $credpath -UseSsl -Priority High

以上是服务失败时将运行的实际脚本

服务中的参数&gt;恢复是:

程序:C:\ Windows \ System32 \ WindowsPowerShell \ v1.0 \ powershell.exe

命令行参数: -File C:\ temp \ myscriptname.ps1

为有错误的停靠点启用操作

首次失败:重启服务

第二次失败:运行程序

1 个答案:

答案 0 :(得分:1)

您输入的用于在发生故障时运行的脚本似乎并非在服务帐户(也不在您的管理员帐户下)下运行,而是在操作系统的帐户下运行。您可以通过在服务失败后执行脚本中的用户名来验证这一点(使用Write-EventLog或将其保存到文本文件中)。

以下示例说明如何验证脚本是否在本地系统下运行:

# C:\src\TEMP\ServiceRecovery.ps1

cd C:\src\TEMP\
$ENV:USERNAME | Out-File C:\src\TEMP\ServiceRecovery.txt -Append -Force

您可以按照以下屏幕截图所示配置您的服务:

Service Settings LogOn

Service Recovery

服务帐户的创建方式如下:

PS > net user ServiceAccount P@ssw0rdP@ssw0rd /ADD
PS > net localgroup Administrators ServiceAccount /ADD

如果我然后通过调用Stop-Process -Name teamviewer_service -Force停止该过程,我可以在生成的文本文件中看到以下名称:

SYSTEM

这意味着您必须通过SYSTEM帐户加密安全字符串,而不是通过您的个人用户或服务用户帐户加密,否则您必须采取其他方式来阅读加密密码。

通过创建脚本来创建密码并以加密形式存储密码,可以通过服务帐户加密密码。将此脚本放入服务恢复设置中,并使此服务失败一次。然后删除脚本并插入原始脚本,然后该脚本将能够导入加密密码。

在这里,您可以找到我测试过的脚本:

(1)加密凭证的脚本

# Creating a PS Credential from a Clear Text Password in Powershell
# https://blogs.technet.microsoft.com/gary/2009/07/23/creating-a-ps-credential-from-a-clear-text-password-in-powershell/

$password = "P@ssw0rdP@ssw0rd" | ConvertTo-SecureString -asPlainText -Force
$username = ".\ServiceAccount" 
$credential = New-Object System.Management.Automation.PSCredential($username,$password)

$credential | Export-CliXml C:\src\TEMP\credential.xml

(2)解密凭证的脚本

$credential = Import-CliXml C:\src\TEMP\credential.xml
$decryptedCredential = "{0} - {1}" -f $credential.UserName, $credential.GetNetworkCredential().Password
$decryptedCredential | Out-File C:\src\TEMP\ServiceRecovery.txt -Append -Force

现在生成的文本文件包含

.\ServiceAccount - P@ssw0rdP@ssw0rd

注意:第一个&#34;加密&#34;脚本包含纯文本密码,仅用一次进行加密。我们必须采用这种方式,才能在SYSTEM帐户下运行。另一种方法可能是使用来自SysInternals的RunAs