我有一个如下所示的 PowerShell 脚本:
# Define time for report (default is 1 day)
$startDate = (get-date).AddDays(-10)
# Store successful logon events from security logs with the specified dates and workstation/IP in an array
# foreach ($DC in $DCs){
# $slogonevents = Get-Eventlog -LogName Security -ComputerName $DC.Hostname -after $startDate | where {$_.eventID -eq 4624 }
# }
$slogonevents = Get-Eventlog -LogName Security -after $startDate | where {$_.eventID -eq 4624 }
# Crawl through events; print all logon history with type, date/time, status, account name, computer and IP address if user logged on remotely
$(foreach ($e in $slogonevents){
# Logon Successful Events
# Local (Logon Type 2)
if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 2)){
write-host "Type: Local Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11]
}
# Remote (Logon Type 10)
if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 10)){
write-host "Type: Remote Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11] "`tIP Address: "$e.ReplacementStrings[18]
}
}) *>&1 > D:\Cyber_security\Python\test.txt
我想从 python 运行这个脚本。这个脚本保存在我的D盘中。我的python脚本是:
import subprocess, sys
p = subprocess.Popen(["powershell.exe",
"D:\Cyber_security\Python\login.ps1"],
stdout=sys.stdout)
p.communicate()
但它不起作用。我需要以管理员身份运行 powershell,但我不知道该怎么做。
您需要 nest
powershell.exe
致电:
调用 PowerShell 的
-Verb RunAs
cmdlet 的外部调用,允许使用提升运行 any 可执行文件。
由于您要使用海拔运行的是
.ps1
脚本,因此必须通过 powershell.exe
(Windows PowerShell CLI)调用它,就像您自己的尝试一样,只不过您明确需要合并 Set-Location
调用以确保脚本在同一工作目录中运行。作为调用者(当使用 C:\Windows\System32
时,Start-Process -Verb RunAs
是 Windows PowerShell 中的默认设置)。
pwsh.exe
,跨平台 PowerShell (Core) 7+ 版本的 CLI(现在默认保留工作目录),内部调用可以简化为(在两个地方将 powershell.exe
替换为 pwsh.exe
以使用 PowerShell 7+):powershell.exe -Args '-noprofile -file D:\Cyber_security\Python\login.ps1'
# See bottom section if you also want to get the exit code of
# the elevated process.
p = subprocess.Popen(
[
"powershell.exe",
"-noprofile", "-c",
r"""
Start-Process -Verb RunAs -Wait powershell.exe -Args "
-noprofile -c Set-Location \`"$PWD\`"; & D:\Cyber_security\Python\login.ps1
"
"""
],
stdout=sys.stdout
)
p.communicate()
注:
运行带有海拔的进程:
Start-Process
' -RedirectStandardOutput
/ -RedirectStandardError
参数来完成此操作。CLI 参数
-noprofile
和 -c
:-noprofile
禁止加载 PowerShell 的 配置文件,并且 -c
(-Command
) 明确指示接下来要执行的 PowerShell 命令。
-Wait
已添加到上面的Start-Process
调用中,以便使外部powershell.exe
调用等待提升的进程退出后再继续。
您并不严格需要
powershell.exe
+ Start-Process -Verb RunAs
来启动提升的进程,但这是最方便的选择。
另一种方法是根据需要将
.ps1
文件修改为 self-elevate(或使用帮助器 .ps1
文件来实现此目的) - 请参阅这个答案
还获取提升进程的退出代码的变体:
如果您的
.ps1
脚本使用 exit
语句来故意报告表示成功与失败的(进程)退出代码,并且您想要查询该退出代码,则需要做更多的工作:
Start-Process
-PassThru
开关输出表示新启动进程的进程信息对象,其 .ExitCode
属性报告进程退出代码(终止后)。
由于
-c
/ -Command
CLI 参数的工作方式,内部 powershell.exe
调用必须显式使用 exit $LASTEXITCODE
将脚本的退出代码中继为提升进程的退出代码。
p = subprocess.Popen(
[
"powershell.exe",
"-noprofile", "-c",
r"""
exit (
Start-Process -Verb RunAs -PassThru -Wait powershell.exe -Args "
-noprofile -c Set-Location \`"$PWD\`"; & C:\Users\jdoe\Desktop\pg\pg.ps1; exit `$LASTEXITCODE
"
).ExitCode
"""
],
stdout=sys.stdout
)
p.communicate()
print('Terminated with exit code ' + str(p.returncode))