0

I am running the following code from VBScript:

Set objShell = CreateObject("Wscript.shell")
objShell.run("powershell.exe -Command ""Start-Process PowerShell -Verb RunAs""")
objShell.run("powershell.exe ""Add-MpPreference -ExclusionPath C:\Windows\Test1\Sub1','C:\Test2'""")

I receive an elevation prompt. After allowing, the last line of code doesn't run.

Separately, the following lines of code work fine in PowerShell. The second line requires elevation, received from line 1,
Powershell -Command "Start-Process PowerShell -Verb RunAs" Add-MpPreference -ExclusionPath 'C:\Test1\Sub1','C:\Test2'

How can I combine these together in a script to run in VBScript? I then want the PowerShell window to close or not open in the first place.

Tried combining them into one line and I also separated them. Neither way works.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 3
    Your first `objShell.run` does not include `bWaitOnReturn` set to `True`, so the second `objShell.run` fires off immediately. But even with that parameter, the second `objShell.run` is not going to run elevated, as it's a separate process. It all has to be done as one command. – LesFerch Jul 08 '23 at 18:54

1 Answers1

0
  • Fundamentally, no (non-persisted) state is preserved across separate calls to powershell.exe, the Windows PowerShell CLI.

  • Therefore, you need a single call to powershell.exe that both (a) creates an elevated process (using Start-Process -Verb RunAs) and (b) executes a command in that process.

    • To that end, you must nest powershell.exe calls, i.e., you must use Start-Process -Verb RunAs to invoke another powershell.exe inside of which you can perform the call that requires elevation.

This answer explains the required techniques in principle, but there's an additional escaping requirement here to make the call robust:

  • On powershell.exe's command line, " chars. that should be preserved as part of the command to execute being passed to -Command must be \-escaped; combined with VBScript's escaping: \"".

  • Due to using nested powershell.exe calls, another layer of \-escaping is required in order to preserve " chars. as part of the command in the nested call, if you want to pass your file paths enclosed in "..." : combined with VBScript's escaping: \\\""

    • Note: While "..." enclosure isn't strictly necessary here, it is generally required for robustly passing arbitrary file-system paths; while '...' enclosure is syntactically easier, because it doesn't require escaping, it breaks with paths that happen to contain ' themselves)

Applying all the techniques from the linked answer - hidden, synchronous execution with exit-code capturing - to your use case:

Set objShell = CreateObject("WScript.Shell")

exitCode = objShell.Run("powershell.exe -Command exit (Start-Process -PassThru -Wait -WindowStyle Hidden -Verb RunAs powershell.exe 'Add-MpPreference -ExclusionPath \\\""C:\Windows\Test1\Sub1\\\"", \\\""C:\Test2\\\""').ExitCode", 0, true)

WScript.Echo "The PowerShell call reported the following exit code: " & exitCode
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • @user692942, to my own bafflement - given how recently I wrote the linked answer - I had forgotten about it, otherwise I wouldn't have rewritten the overlapping content from scratch here. I've removed the overlapping content in favor of linking to the previous answer, focusing on what's specific to this question. – mklement0 Jul 09 '23 at 14:23
  • @user692942, it feels like we've had the discussion about sign posts vs. legitimate variations that warrant their own answer before, and I understand that your preference is to make everything a duplicate https://stackoverflow.com/q/15770599/45375. To me that does a disservice to the community, given the complexities of the PowerShell CLI, both alone and in combination with VBScript. – mklement0 Jul 09 '23 at 14:24