操作系统:赢取2012 R2
您好,
我尝试设置某些服务,以便在第二次失败时触发powershell脚本,该脚本通过电子邮件发送给某些人。这是通过services > (specific service) > properties > recovery
完成的。
尝试了几乎所有可能的程序组合:
Powershell.exe
,C:\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管理员场景很陌生,user
或service
实际触发了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
为有错误的停靠点启用操作
首次失败:重启服务
第二次失败:运行程序
答案 0 :(得分:1)
您输入的用于在发生故障时运行的脚本似乎并非在服务帐户(也不在您的管理员帐户下)下运行,而是在操作系统的帐户下运行。您可以通过在服务失败后执行脚本中的用户名来验证这一点(使用Write-EventLog
或将其保存到文本文件中)。
以下示例说明如何验证脚本是否在本地系统下运行:
# C:\src\TEMP\ServiceRecovery.ps1
cd C:\src\TEMP\
$ENV:USERNAME | Out-File C:\src\TEMP\ServiceRecovery.txt -Append -Force
您可以按照以下屏幕截图所示配置您的服务:
服务帐户的创建方式如下:
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
。