我有一个以非管理员权限启动的 Java 应用程序。 我想从我的 Java 应用程序启动不同的 PowerShell 脚本。 PowerShell 脚本具有输入和输出参数。在脚本内部执行 PSRemoting 命令以控制其他 Windows PC。我需要以管理员身份从 Java 启动 PowerShell 脚本。在我的 Java 应用程序中,管理员用户和管理员密码是已知的。
启动 PowerShell 脚本、传递参数并返回返回值,到目前为止确实有效。但我还没有设法以管理员身份启动脚本。
List<String> cmd = new ArrayList<>();
cmd.add("powershell.exe");
cmd.add("-ExecutionPolicy");
cmd.add("Bypass");
cmd.add("-File");
cmd.add(tempScriptPath.toString());
// Add the arguments for the PowerShell file
Iterator<Map.Entry<String, JsonNode>> fields = jsonArgs.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
String key = field.getKey();
String value = field.getValue().asText(); // Get value as text
// Add the key and value to the list
cmd.add("-" + key);
cmd.add(value);
}
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true); // Combine stdout and stderr
// Start the process
Process process = pb.start();
这是一个虚拟的 PowerShell 脚本:
param (
[string]$ip
)
Write-Output "PS INFO: Check if ps remoting is active"
$hostname = Invoke-Command -ComputerName 127.0.0.1 -ScriptBlock { hostname }
Write-Output "PS INFO: Hostname is $hostname"
$result = @{
PsErrorCode = 0
Hostname = $hostname
}
$result | ConvertTo-Json -Depth 10
我想我必须将 runAs 选项以及用户和密码添加到 cmd,但到目前为止我还没有管理它。
也许有人知道如何以管理员身份启动脚本。
我找到了适合我的解决方案。
我的java应用程序在用户A下运行,该用户没有管理员权限。我从 java 启动一个新的 power shell 进程。我使用 -Credentials 参数以具有管理员权限的用户 B 身份运行 power shell 脚本。
在 power shell 脚本中,我首先检查脚本是否以提升的权限执行。因为从来没有出现过这种情况,所以我以提升的权限重新启动脚本(-Verb“runas”)。然后该脚本在具有提升权限的用户 B 下运行。
这些是我的问题以及我如何解决它们。如果有人知道更好的解决方案,请告诉我。
无法以提升的权限从 java(在用户 A 下运行)启动 powershell 脚本 -> 以普通权限但以用户 B 的身份启动 power shell,然后以提升的权限重新启动脚本。
无法从具有提升权限的 powershell 脚本向其调用者(具有非提升权限的 power shell 脚本)返回值。标准输出不可用 -> 我使用日志文件来获取返回值。
只有当用户接受 UAC concent 提示时,才能以提升的权限启动 Power shell 脚本。绕过 UAC concent 提示是不可能的。 -> 我接受这一点。到目前为止我还没有找到解决这个问题的方法。更改通知级别对我来说是没有选择的。
# This example can be used to execute powershell commands with elevated privileges
param (
[string]$logFile, # The logfile is used for logging and returning to the calling process
[string]$ip
)
# Get the current user
$currentActiveUser = whoami
# Get the complete path to this power shell file
$currentScriptPath = $MyInvocation.MyCommand.Definition
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator" = elevated privileges
if ($myWindowsPrincipal.IsInRole($adminRole)) {
Write-Output "PS INFO: Script $currentScriptPath is called by $currentActiveUser in elevated mode" >> $logFile
# This is a PS remoting command to the the hostname of a remote pc
# TODO: Add here the credentials of the remote pc
$hostname = Invoke-Command -ComputerName $ip -ScriptBlock { hostname }
$hostname = $hostname | Out-String # Convert object to string
$hostname = $hostname.Trim() # Remove \r\n
Write-Output "PS INFO: Hostname is $hostname" >> $logFile
# Create a result hash table
$result = @{
PsErrorCode = 0
Hostname = $hostname
}
# Write the result to the log file
$result | ConvertTo-Json -Depth 10 | Out-File -FilePath $logFile -Append
exit
}
else
{
# This is the entry point because the initial time the script is executed with non elevated privileges
Write-Output "PS INFO: Script $currentScriptPath is called by $currentActiveUser not in elevated mode" >> $logFile
# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter
$newProcess.Arguments = "$($myInvocation.MyCommand.Definition) -logFile '$logFile' -ip '$ip'"
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the process and wait for it to finish
Start-Process -FilePath $newProcess.FileName -ArgumentList $newProcess.Arguments -Verb $newProcess.Verb -PassThru -Wait
Write-Output "PS INFO: Exit non elevated mode" >> $logFile
# Exit from the current, unelevated, process
exit
}