我认为除了 CodeFuller 所说的没有带有--no-sandbox 选项的沙箱之外,您还应该禁用所有扩展、同步和书签。
最好有一个 Guest session 别名“无需登录即可浏览”,并带有--bwsi 选项。
有趣的是,在测试过程中,我发现在执行--bwsi 之前使用--disable-extensions 明确禁用扩展会更好,得到更好的pdf 打印输出。
我已经对其进行了测试,对我来说它有效。我期待您的反馈。
Edit1 和 Edit3 - 删除 try...catch 并添加用户和密码并添加 psuser 细节
您可能在域上,所以我调整了脚本以在域上以不同用户身份运行(用户必须具有正确的权限!)
首先创建您的凭据文件:
登录到用户,例如psuser
创建密码文件:
# Encrypt user password and save it to file
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'C:\<your_path>\your_secret_password.txt'
然后使用加密凭据运行以下改进的脚本:
$username = 'psuser' # This needs to be adjusted to correct user you are using
$domain = <your_domain> # adjust to your needs
$encrypted_passwd = get-content 'C:\<your_path>\your_secret_password.txt' | ConvertTo-securestring
# Setting process invocation parameters.
$process_start_info = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$process_start_info.CreateNoWindow = $true
$process_start_info.UseShellExecute = $false
$process_start_info.RedirectStandardOutput = $true
$process_start_info.RedirectStandardError = $true
$process_start_info.UserName = $username
$process_start_info.Domain = $domain
$process_start_info.Password = $encrypted_passwd
$process_start_info.Verb = 'runas'
$process_start_info.FileName = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
$process_start_info.Arguments = '--no-sandbox --disable-extensions --bwsi --headless --disable-gpu --print-to-pdf=C:\prg\PowerShell\test\chrome_file.pdf https://www.bing.com'
# Creating process object.
$process = New-Object -TypeName System.Diagnostics.Process
$process.StartInfo = $process_start_info
# Start the process
[Void]$process.Start()
$process.WaitForExit()
# synchronous output - captures everything
$output = $process.StandardOutput.ReadToEnd()
$output += $process.StandardError.ReadToEnd()
Write-Output $output
在脚本调试过程中我遇到了这些错误:
a) 当您想针对 AD 服务器进行验证但它不可用时:
Exception calling "Start" with "0" argument(s): "There are currently no logon servers available to service the logon request"
At C:\prg\PowerShell\test\chrome_print.ps1:56 char:12
+ [Void]$process.Start()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Exception calling "WaitForExit" with "0" argument(s): "No process is associated with this object."
At C:\prg\PowerShell\test\chrome_print.ps1:58 char:12
+ $process.WaitForExit()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:61 char:12
+ $output = $process.StandardOutput.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:62 char:12
+ $output += $process.StandardError.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
b) 脚本中缺少域信息:
Exception calling "Start" with "0" argument(s): "The stub received bad data"
At C:\prg\PowerShell\test\chrome_print.ps1:39 char:12
+ [Void]$process.Start()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Exception calling "WaitForExit" with "0" argument(s): "No process is associated with this object."
At C:\prg\PowerShell\test\chrome_print.ps1:41 char:12
+ $process.WaitForExit()
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:44 char:12
+ $output = $process.StandardOutput.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\prg\PowerShell\test\chrome_print.ps1:45 char:12
+ $output += $process.StandardError.ReadToEnd()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
打印 pdf
和 stderr 消息:
[0313/112937.660:ERROR:gpu_process_transport_factory.cc(1009)] Lost UI shared context.
[0313/112937.662:ERROR:instance.cc(49)] Unable to locate service manifest for metrics
[0313/112937.662:ERROR:service_manager.cc(890)] Failed to resolve service name: metrics
[0313/112938.152:ERROR:instance.cc(49)] Unable to locate service manifest for metrics
[0313/112938.153:ERROR:service_manager.cc(890)] Failed to resolve service name: metrics
[0313/112942.876:INFO:headless_shell.cc(566)] Written to file C:\prg\PowerShell\test\chrom e_file.pdf.
Edit2 使用 ASP.NET
添加 windows 帐户模拟
使用 ASP.NET 模拟 Windows 帐户:
ASP.NET 用户未传递到新线程(默认情况下)。当您想调用 PowerShell 脚本时,它会在具有不同凭据的其他线程中调用(当您有专门的域认证用户来运行上述脚本时,您可以使用上述脚本克服这一点)。默认脚本在内置账号NT AUTHORITY\NETWORK SERVICE下执行。
这些步骤是在ASP.NET 级别克服它:
1) 在 IIS 中启用 Windows 身份验证
a) 先安装(这是windows 2008 R2截图):
b) 在您的 IIS 上启用它:
将其更改为启用:
2) 更改您网站的 web.config 以正确处理模拟
编辑网站目录中的 web.config 文件。为了执行当前用户的安全上下文(AD)的服务器端代码。
找到xml标签:<system.web>并添加两个新元素以启用windows authentication
<authentication mode="Windows" />
<identity impersonate="True" />
3) 正确编写代码以调用进程内 PowerShell 脚本
您需要调整您的 ASP.NET 代码,使您拥有 powershell 运行空间,并在管道中调用运行空间内的脚本
一个简单的例子:
// You need to create a Runspace. Each other pipeline you create will run in the same Runspace
// Do it only once, all others will be pipelined
RunspaceConfiguration powershellConfiguration = RunspaceConfiguration.Create();
var powershellRunspace = RunspaceFactory.CreateRunspace(powershellConfiguration);
powershellRunspace.Open();
// create a pipeline the cmdlet invocation
using ( Pipeline psPipeline = powershellRunspace.CreatePipeline() ){
// Define the command to be executed in this pipeline
Command script = new Command("PowerShell_script");
// Add any parameter(s) to the command
script.Parameters.Add("Param1", "Param1Value");
// Add it to the pipeline
psPipeline.Commands.Add(script);
try {
// Invoke() the script
var results = psPipeline.Invoke();
// work with the results
} catch (CmdletInvocationException exception) {
// Any exceptions here - for the invoked process
}
}
4) 修改aspnet.config 允许模拟跨线程
此步骤允许您以当前的模拟用户身份运行。
您必须修改服务器的 aspnet.config 文件。
在configuration和runtime中添加两个xml元素:
<configuration>
<runtime>
...
<legacyImpersonationPolicy enabled="true" />
<alwaysFlowImpersonationPolicy enabled="false" />
</runtime>
</configuration>