Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

powershell.exe call from batch file unbearable slow after upgrading to windows 10

I'm having some trouble with a .bat->.ps1 call in my build process after moving from Win7 to Win10 (1607 LTSB) - the call to PowerShell, that took less than 100msec on Win7 now takes 10sec+ on Win10 on certain hosts :-(

The call looks like this: powershell -ExecutionPolicy Bypass -NonInteractive %scriptfile%

Startup-performance of ISE and PowerShell.exe from start-menu is good.

I wasn't able to dig up anything helpful so far...

  • PoSh 5.1 on both, Win7 and Win10, PSProfile is clean apart from a couple of aliases
  • $env:PATH is "clean" apart from a couple of folders that have been added on purpose - removing those didn't improve the situation.
  • already did "ngen update" - problem still occurs.

I've create a little helper script that measures startup-performance of PowerShell from different starting points: https://gist.github.com/mwallner/d3c86794bb74680b0c0cf4e9a9758ab4 no luck with this either, on Win7 and most of my Win10 machines startup-time is way below 1sec.

anybody here who has already solved this riddle?

like image 530
mwallner Avatar asked Jan 03 '23 08:01

mwallner


2 Answers

Solved! - it's been UAC all along :-(

Solution: disable UAC for the user that's running the scriots or make sure the first script that calls the others is being run as administrator / elevated.

Not sure why UAC is causing these delays, and I'm certain there are cases where this is not an option - but for me this is solved by ensuring the first script is elevated + disabling UAC for dev boxes.

like image 63
mwallner Avatar answered Jan 05 '23 17:01

mwallner


I had a similar problem - scripts taking multiple seconds to start.

The problem turned out to be a combination of two factors:

  • I had ExecutionPolicy force-set to RemoteSigned via GPO (run Get-ExecutionPolicy -List and check the value for MachinePolicy)
  • I had quite a few processes running, so that enumerating them was taking a long time

...so it was fixed by a restart. (I think overriding the GPO-set value would also work, but I didn't try it.)


What didn't work:

  • Disabling the loading of my profile (powershell -NoProfile)
  • Running ngen to generate native images for an assembly and its dependencies and install them in the Native Images Cache
  • Disable module autoloading (introduced in v3) with $PSModuleAutoloadingPreference = 'none', i.e. powershell.exe -NoProfile -ExecutionPolicy Bypass -command "$PSModuleAutoloadingPreference = 'none'; & path\to\script.ps1"
  • "Use legacy console" in the shortcut properties
  • Disabling UAC

I noticed that simply running PowerShell was relatively fast, only script execution (via command-line parameters or the & / Call operator) was slow. For instance I could run the script by piping it to powershell's stdin, which didn't incur the slowdown:

type "script.ps1" | powershell.exe -noprofile -nologo -executionpolicy Bypass -file -

At this point I tried troubleshooting with ProcMon, which didn't show any long calls.

Next I tried opening Process Explorer to check the stack of the powershell.exe process while it was loading the script. The top of the stack was:

ntdll.dll!RtlGetNativeSystemInformation+0x14
KERNEL32.DLL!lstrcmpA+0x12d
KERNEL32.DLL!CreateToolhelp32Snapshot+0x108
[Native Frame: IL Method without Metadata]
[Managed to Unmanaged Transition]
System.Management.Automation.dll!System.Management.Automation.PsUtils.GetParentProcess+0x73
System.Management.Automation.dll!System.Management.Automation.Internal.SecuritySupport.GetExecutionPolicy+0x138

which led me to issue #2578 that explained the behavior I was seeing.

like image 35
Nickolay Avatar answered Jan 05 '23 15:01

Nickolay