简体   繁体   English

具有管理员权限的批处理脚本调用PowerShell失败

[英]Batch Script with admin rights Calling PowerShell ends in Error

Currently, I have a Batch Script which has several functions, one among them is to invoke a PowerShell script. 当前,我有一个具有多个功能的批处理脚本,其中之一是调用PowerShell脚本。 The PS_script basically reads & filters mails from outlook and stores certain data into an excel file. PS_script基本上从Outlook中读取和过滤邮件,并将某些数据存储到excel文件中。

Certain functions in the BS needs admin rights to run successfully. BS中的某些功能需要管理员权限才能成功运行。 Whenever the PS_Script is invoked with BS with elevated access it gives error. 每当通过具有更高访问权限的BS调用PS_Script时,都会产生错误。

new-object : Retrieving the COM class factory for component with CLSID {...} failed due to following error: 8008005 Server execution failed {......

Is there anyway to invoke PS_script from BS without elevated access even if the BS is run with admin rights ? 无论如何,即使具有管理员权限的BS都可以在没有提升访问权限的情况下从BS调用PS_script?

Currently, i use following command in my BS to invoke the PS_script Test.PS1 : 当前,我在BS中使用以下命令来调用PS_script Test.PS1:

Powershell.exe -ExecutionPolicy RemoteSigned -File  C:\Users\%UserName%\Desktop\Test.PS1

If you are sure your problem comes from admin rights you can try to run your powershell script with the username your are executing the script from (or any other user that has the rigths you need) 如果您确定问题来自管理员权限,则可以尝试使用执行脚本的用户名(或具有所需权限的其他任何用户)运行Powershell脚本。

RunAs /u:domain/username "Powershell.exe -File  C:\Users\%UserName%\Desktop\Test.PS1"

Seems that runas doesn't accept the password. 似乎runas不接受密码。 But there are other utilites to do that: Unable to supply password to runas from commandline 但是还有其他实用程序可以执行此操作: 无法从命令行向runas提供密码

Here's what I've got so far. 这是到目前为止我得到的。

  • Wscript.Shell 's .ShellExecute method would let you prompt for UAC elevation . Wscript.Shell.ShellExecute方法将让您提示UAC提升 If you could break your admin-dependent functions into helper scripts and stick this BatchGotAdmin code at the top of each, that would let you run the rest in the context of a normal user; 如果您可以将依赖于管理员的功能分解为帮助程序脚本,并将此BatchGotAdmin代码粘贴在每个脚本的顶部,则可以让其余代码在普通用户的上下文中运行; but it'd still require the user to click "Allow" for each helper script run. 但仍然需要用户为每次运行的帮助程序脚本单击“允许”。

  • On the opposing side of the coin, using Wscript.Shell 's .Exec method to do: 在硬币的另一侧,使用Wscript.Shell.Exec方法执行以下操作:

    runas /env /netonly /noprofile %userdomain%\\%username% "command to run"

    ... results in bypassing the password and prompt, resulting in the command to be run unauthenticated. ...导致绕过密码和提示,导致该命令未经身份验证而运行。 This is very interesting and unexpected behavior. 这是非常有趣和意外的行为。 Because the "Enter password" prompt is bypassed but the command runs in a separate console anyway, I think it runs as a normal user. 因为绕过了“输入密码”提示,但是该命令无论如何仍在单独的控制台中运行,因此我认为它以普通用户身份运行。 However, I haven't found any worthwhile tests with which to confirm. 但是,我没有找到任何值得确认的测试。

    The problem I've run into with this is that runas called in this way seems to be non-blocking, so it's hard to deal with the output and timing. 我遇到的问题是,以这种方式调用的runas似乎是非阻塞的,因此很难处理输出和时序。 In case it helps, I'm including my scratch pad test broken code at the bottom of this answer. 如果有帮助,我将在此答案的底部包含我的暂存器测试损坏的代码。

  • Another alternative would be to create a Scheduled Task to run your PowerShell snippet un-elevated. 另一种选择是创建一个计划任务以不加高权限地运行您的PowerShell代码段。

  • There's also Wscript.Shell 's .Run method that would let you .SendKeys the password which would let you get around the UAC prompt, but it doesn't block either, and requires you to store a password in your script. 还有Wscript.Shell的.Run方法 ,该方法可以让您.SendKeys使用口令来绕过UAC提示符,但它也不会阻塞,并且要求您在脚本中存储口令。

I'm afraid I've applied all my ingenuity to the problem but haven't found any solution which doesn't create another problem -- other than possibly the Scheduled Task solution. 恐怕我已经尽全力解决了这个问题,但是没有找到任何不会造成其他问题的解决方案,除了“计划任务”解决方案之外。


Here's the incomplete WshShell.Exec solution referenced in item 2 above: 这是上面第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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM