目前,我有一个批处理脚本,它有几个函数,其中一个是调用PowerShell脚本。 PS_script基本上是&过滤来自outlook的邮件并将某些数据存储到excel文件中。
BS中的某些功能需要管理员权限才能成功运行。每当使用具有提升访问权限的BS调用PS_Script时,它都会出错。
new-object : Retrieving the COM class factory for component with CLSID {...} failed due to following error: 8008005 Server execution failed {......
无论如何,即使BS使用管理员权限运行,也无需提升访问权限从BS调用PS_script?
目前,我在我的BS中使用以下命令来调用PS_script Test.PS1:
Powershell.exe -ExecutionPolicy RemoteSigned -File C:\Users\%UserName%\Desktop\Test.PS1
答案 0 :(得分:0)
如果您确定您的问题来自管理员权限,您可以尝试使用您正在执行脚本的用户名(或具有您所需要的任何其他用户)运行您的PowerShell脚本
RunAs /u:domain/username "Powershell.exe -File C:\Users\%UserName%\Desktop\Test.PS1"
似乎runas不接受密码。但还有其他用途可以做到这一点: Unable to supply password to runas from commandline
答案 1 :(得分:0)
这是我到目前为止所得到的。
Wscript.Shell
的{{3}}会让您提示.ShellExecute
method。如果您可以将依赖于管理员的函数分解为帮助程序脚本并将此BatchGotAdmin代码粘贴在每个函数的顶部,那么您可以在普通用户的上下文中运行其余部分;但它仍然需要用户为每个帮助程序脚本运行单击“允许”。
在硬币的另一面,使用Wscript.Shell
的{{3}}来做:
runas /env /netonly /noprofile %userdomain%\%username% "command to run"
...导致绕过密码和提示,导致命令以未经身份验证的方式运行。这是非常有趣和意想不到的行为。因为绕过了“输入密码”提示,但命令在单独的控制台中运行,我认为它以普通用户身份运行。但是,我还没有找到任何有价值的测试来确认。
我遇到的问题是以这种方式调用的runas
似乎是非阻塞的,因此很难处理输出和时序。如果它有帮助,我会在我的答案底部包括我的便笺簿测试损坏的代码。
另一种方法是创建一个UAC elevation来解压缩PowerShell代码段。
还有.Exec
method可以让你.SendKeys
密码,让你绕过UAC提示,但它也不会阻止,并要求你存储密码你的剧本。
我担心我已经将所有的聪明才智应用于问题,但没有找到任何不会产生其他问题的解决方案 - 除了可能的预定任务解决方案。
以下是第2项中引用的不完整WshShell.Exec
解决方案:
@if (@CodeSection==@Batch) @then
@echo off
setlocal
call :runAsNonAdmin "cmd /c dir"
goto :EOF
:runAsNonAdmin <command to run>
setlocal enabledelayedexpansion
cscript /nologo /e:JScript "%~f0" "%userdomain%\%username%" "%~1"
endlocal & goto :EOF
@end // end batch / begin JScript chimera
var args = {
user: WSH.Arguments(0),
cmd: WSH.Arguments(1)
},
runas = 'runas /env /netonly /noprofile /user:' + args.user + ' "' + args.cmd + '>stdout 2>stderr"',
osh = WSH.CreateObject('wscript.shell'),
fso = WSH.CreateObject('scripting.filesystemobject'),
proc = osh.Exec(runas),
read = '', file, out = ['stdout','stderr'];
// note: proc.StdOut and proc.StdErr refer *only* to the runas command itself,
// not to the command spawned by it. The spawned command is essentially sandboxed.
while (!proc.Status || !proc.StdErr.AtEndOfStream || !proc.StdOut.AtEndOfStream) {
if (!proc.StdErr.AtEndOfStream) {
WSH.StdErr.WriteLine(proc.StdErr.ReadLine());
} else if (!proc.StdOut.AtEndOfStream) {
WSH.StdOut.Write(proc.StdOut.Read(1));
}
}
for (var i in out) {
if (fso.fileExists(out[i])) {
if (fso.GetFile(out[i]).Size) {
file = fso.OpenTextFile(out[i], 1);
WSH[out[i]].Write(file.ReadAll());
file.Close();
}
var del = osh.Exec('cmd /c del ' + out[i]);
while (!proc.Status) WSH.Sleep(10);
}
}
WSH.Echo(proc.ProcessID + ': status ' + proc.Status + '; exit ' + proc.ExitCode);
WSH.Quit(0);
// Inactive code. Since .exec skips authentication, the following code results in a broken pipe error.
while (!proc.Status || !proc.StdErr.AtEndOfStream || !proc.StdOut.AtEndOfStream) {
if (!proc.StdOut.AtEndOfStream) {
read += proc.StdOut.Read(1);
if (/Enter the password for .*?:/.test(read)) {
proc.StdIn.WriteLine(args.pass);
}
} else if (!proc.StdErr.AtEndOfStream) WSH.Echo(proc.StdErr.ReadLine());
else WSH.Sleep(10);
}