Skip to content

Commit c70f638

Browse files
Add startup troubleshooter (#12557)
* Add startup troubleshooter * Apply suggestions from code review Co-authored-by: Mikey Lombardi (He/Him) <michael.t.lombardi@gmail.com> --------- Co-authored-by: Mikey Lombardi (He/Him) <michael.t.lombardi@gmail.com>
1 parent a85dec2 commit c70f638

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
---
2+
description: How to identify and troubleshoot PowerShell startup issues, including performance problems and crashes.
3+
ms.date: 12/01/2025
4+
title: Troubleshoot PowerShell startup issues
5+
---
6+
# Troubleshoot PowerShell startup issues
7+
8+
Sometimes, PowerShell can have problems before it's even ready to use. Startup issues can be
9+
difficult to troubleshoot, especially when you want to use PowerShell to help. There are three main
10+
phases of startup:
11+
12+
1. Process creation
13+
1. PowerShell SessionState initialization
14+
1. Profile processing
15+
16+
The most common problems include:
17+
18+
- Long startup time or slow performance
19+
- Errors
20+
- Crashes
21+
22+
## The steps of the startup sequence
23+
24+
It's helpful to understand the steps PowerShell goes through during startup. This way, you can
25+
narrow down where the issue is happening.
26+
27+
### Step 1: Process creation
28+
29+
The process creation has a few steps:
30+
31+
1. Create a Host window
32+
33+
On Windows, the Host can be Windows Terminal, the Windows Console Host, Visual Studio Code, or
34+
any other hosting application. Problems that occur here are usually unrelated to PowerShell, but
35+
also extremely rare.
36+
37+
1. Start the process host process
38+
39+
Problems that occur here are usually caused by a corrupted executable or an issue in the
40+
operating system.
41+
42+
1. Prepare .NET
43+
44+
PowerShell is .NET-based and that needs to fully load. Depending on which PowerShell version you
45+
are trying to start, you either get the full, Windows-integrated .NET Framework with Windows
46+
PowerShell 5.1 or the newer .NET included in PowerShell 7.
47+
48+
During first-time startup of PowerShell, PowerShell and .NET run optimization tasks. This
49+
optimization task is only run once, during the first startup after installation, upgrade, or if
50+
the cache is empty. Startup will take longer during this first-time optimization. Failure during
51+
optimization can create a corrupted cache. A corrupted PowerShell cache can cause issues with
52+
command discovery and module loading.
53+
54+
### Step 2: PowerShell SessionState initialization
55+
56+
Loading the PowerShell binaries and initializing the engine involves processing the PowerShell
57+
configuration and some cached data.
58+
59+
1. Process configuration files: `powershell.config.json` and PSSession configuration files used by
60+
JEA and other remoting scenarios. These files may contain settings that can affect the language
61+
mode, available commands and modules, and some policy settings.
62+
1. Check Group Policies and Windows Security policies. Windows Group Policies can override settings
63+
in the `powershell.config.json`. Security Policies can enable features like WDAC (Windows
64+
Defender Application Control), which can also constrain the language mode available.
65+
1. Load the default modules (Microsoft.PowerShell.Core and PSReadLine) and any modules and
66+
assemblies defined in the PSSession configuration.
67+
68+
For more information about PowerShell security features, see the following articles:
69+
70+
- [PowerShell security features][01]
71+
- [about_Language_Modes][03]
72+
73+
### Step 3: Profile processing
74+
75+
Finally, PowerShell runs the available profile files. Profile scripts are run in the
76+
following order:
77+
78+
1. All Hosts All Users
79+
1. Current Host All Users
80+
1. All Hosts Current User
81+
1. Current Host Current User
82+
83+
> [!NOTE]
84+
> Profile scripts aren't run for remote sessions.
85+
86+
For more information about profiles, see [about_Profiles][04].
87+
88+
## Narrow the scope of the issue
89+
90+
It's helpful to remove variables and narrow down the specific scope of where the issue happens. The
91+
easiest variable to eliminate is the profile. The profile often contains custom code, especially in
92+
the user-specific profile scripts.
93+
94+
Try running PowerShell with the profile disabled:
95+
96+
```powershell
97+
# PS 5.1:
98+
powershell -NoProfile
99+
100+
# PS 7.*:
101+
pwsh -NoProfile
102+
```
103+
104+
Next you should see if the problem is version-specific. Try running your profile in both Windows
105+
PowerShell 5.1 and PowerShell 7. Windows PowerShell and PowerShell 7 store the profile in different
106+
locations. Your profile may not be the same for both versions. Compare the files to understand the
107+
differences. You can try installing your PowerShell profile in Windows PowerShell 5.1. However, be
108+
aware that some PowerShell 7 commands and modules aren't compatible with Windows PowerShell 5.1.
109+
110+
You can test your PowerShell 7 profile in Windows PowerShell 5.1 without overwriting your existing
111+
profile.
112+
113+
1. Start Windows PowerShell 5.1 with the profile disabled.
114+
1. Manually dot-source your PowerShell 7 profile file into the Windows PowerShell 5.1 session.
115+
116+
```powershell
117+
. $env:USERPROFILE\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
118+
```
119+
120+
1. Observe whether the issue occurs.
121+
122+
If the issue persists, then you know problem is an environmental issue outside of the profile.
123+
124+
Try running the profile on a different device. If the profile works correctly on another device,
125+
then you know the issue is specific to your original device.
126+
127+
## Troubleshoot common environmental problems
128+
129+
### Crashes during startup
130+
131+
If the PowerShell console crashes during startup, especially early and with no feedback, you could
132+
have a corrupted process cache. This is a rare condition that you can resolve by clearing the
133+
cache. There are two cache locations that can be cleared:
134+
135+
- User Cache: `$env:LOCALAPPDATA\Microsoft\Windows\Caches`
136+
- System Cache: `$env:windir\System32\Config\SystemProfile\AppData\Local\Microsoft\Windows\Caches`
137+
138+
Delete the contents of the user cache folder first, then try starting PowerShell again. If the
139+
problem persists, delete the contents of the system cache and try again.
140+
141+
You may also need to delete the PowerShell analysis cache. You can find the cache files in the
142+
following locations:
143+
144+
- Windows PowerShell:
145+
`$env:windir\System32\Config\SystemProfile\AppData\Local\Microsoft\Windows\PowerShell`
146+
- PowerShell 7: `$env:LOCALAPPDATA\Microsoft\PowerShell`
147+
148+
Delete only the following file patterns:
149+
150+
- `ModuleAnalysisCache-*`
151+
- `StartupProfileData-*`
152+
153+
The cached data is recreated the next time you start PowerShell.
154+
155+
If the problem persists in Windows PowerShell 5.1, you may need to repair the .NET Framework
156+
installation. For more information, see [Repair the .NET Framework][02].
157+
158+
## Troubleshoot common profile problems
159+
160+
This section describes some common problems that can occur during PowerShell startup, and how to
161+
troubleshoot them.
162+
163+
### Profile takes too long to run
164+
165+
First you must define what's _"too long."_ PowerShell is only doing what the scripts tell it to do.
166+
Check all profile paths. There may be multiple profile scripts being run. Review the code to
167+
understand it's trying to do.
168+
169+
- Determine where the delay occurs
170+
171+
If there are profile scripts for the **AllUsers** scope, you might not be able to edit those
172+
files. Work with your system administrator to review those files. For the **CurrentUser** scope
173+
profile scripts, edit those files to add timing messages to help you find where the delay occurs.
174+
For example, you can add the following line at various points in your profile script.
175+
176+
```powershell
177+
Write-Host "$(Get-Date -Format 'HH:mm:ss.fff') | Profile: Step X"
178+
```
179+
180+
- Reduce dependencies
181+
182+
Reduce the number of modules that need to be loaded to execute your profile. Run `Get-Module`
183+
after profile runs to see the modules that were loaded during startup. By default, PowerShell
184+
loads the Microsoft.PowerShell.Core and PSReadLine modules. Any additional modules were loaded
185+
by your profile scripts.
186+
187+
Modules can be loaded explicitly by using `Import-Module` or implicitly by using commands defined
188+
in those modules. Consider whether you need a command or a module loaded during startup.
189+
190+
- Avoid installing modules in a redirected folder
191+
192+
In many situations on Windows, your `Documents` folder can be redirected to a network file share
193+
or to OneDrive. Network file access can be slow, especially if the network is congested or the
194+
server is under heavy load. Depending on how OneDrive is configured, it can also introduce delays
195+
or cause errors during profile exectution.
196+
197+
You have a few options to mitigate this problem:
198+
199+
- Don't redirect your `Documents` folder, but that might not be desired
200+
- Configure your `Modules` folder in OneDrive to _always_ be kept on disk. This prevents errors
201+
and delayed load times.
202+
- Install modules in the **AllUsers** scope, which is outside of the user profile folder.
203+
204+
- Measure the actual performance
205+
206+
If you don't know how long your profile takes to run, you can't determine whether it's too long.
207+
The `Measure-Command` cmdlet can show how long a command or script block takes to run.
208+
209+
Steve Lee, the PowerShell Dev Manager, has a blog post that describes how to measure the
210+
performance of your profile. It includes instructions for establishing a baseline for performance,
211+
how to get detailed timing information, and ways to optimize your profile.
212+
213+
See [Optimizing your $Profile][05].
214+
215+
### PowerShell 7 starts slowing in an isolated network
216+
217+
In this scenario, your Windows computer is on a network that is not connected to the internet. For
218+
interactive PowerShell sessions, PowerShell loads the PSReadLine module automatically. PSReadLine is
219+
a signed module. PowerShell must verify the digital signature of the module. This verification can
220+
cause delays in a disconnected environment. To test this theory, start PowerShell 7 in
221+
_non-interactive_ mode:
222+
223+
```powershell
224+
pwsh.exe -noninteractive
225+
```
226+
227+
If PowerShell starts quickly in non-interactive mode, then the problem is likely caused by
228+
Certificate Revocation List (CRL) checks. As part of the process of verifying a digital signature,
229+
The .NET runtime checks the CRL to ensure that the signing certificate is still valid. In a
230+
disconnected environment, you computer can't access the CRL on internet. The default timeout for CRL
231+
checks is 15 seconds. This means that every time PowerShell loads a signed module, it can take up to
232+
15 seconds to timeout.
233+
234+
There are three possible workarounds for this problem:
235+
236+
- Firewall or proxy exemption
237+
238+
Allowing direct internet access for CRL checking prevents the problem. In an environment where you
239+
can control access to the internet access, you can configure your firewall or proxy to allow
240+
access to the CRL Urls. This is the easiest solution with the least impact. The firewall logs
241+
should show the Url that PowerShell attempted to reach.
242+
243+
- Reduce CRL Timeout
244+
245+
Reducing the CRL lookup timeout is possible, but doing so risks other lookups to fail, that can't
246+
complete in the time specified. For details about how to change the timeout, see [Manage Network
247+
Retrieval and Path Validation][04].
248+
249+
- Remove CRL checking
250+
251+
The CRL checking settings are managed by Group Policy. For more information, see [Manage Trusted
252+
Publishers][03].
253+
254+
> [!WARNING]
255+
> It's possible to disable the CRL check however, it's not recommended. Disabling CRL checking
256+
> prevents you from actually revoking compromised certificates.
257+
258+
### ERROR: Cannot dot-source this command because it was defined in a different language mode
259+
260+
PowerShell works with application control systems, such as AppLocker and Windows Defender
261+
Application Control (WDAC), by automatically running in **ConstrainedLanguage** mode.
262+
ConstrainedLanguage mode restricts some features that are potentially dangerous. However, there are
263+
times when you need **FullLanguage** mode to use certain commands or features. Scripts can run in
264+
**FullLanguage** mode when they're trusted by the policy. Trust can be indicated through file
265+
signing or other policy mechanisms configured in AppLocker or WDAC.
266+
267+
When you start a PowerShell session that's managed under application control, you get the following
268+
error:
269+
270+
```
271+
Cannot dot-source this command because it was defined in a different language mode. To invoke this
272+
command without importing its contents, omit the '.' operator.
273+
```
274+
275+
Under application control, PowerShell is running in **ConstrainedLanguage** mode. This error occurs
276+
when and your profile script is _exempted_ or is _signed_ to run in **FullLanguage** mode. When
277+
PowerShell is running in **ConstrainedLanguage** mode, it can't dot-source code trusted to run in
278+
**FullLanguage** mode.
279+
280+
To resolve the problem, you must remove the exemption or signature from the profile script. If you
281+
need code that must run in **FullLanguage** mode during your profile, move it into another script
282+
file that's exempted or signed. Call (don't dot-source) that script file from within your profile.
283+
284+
For more information on this issue, see
285+
[PowerShell Constrained Language mode and the Dot-Source Operator][06].
286+
287+
## Further reading
288+
289+
- [about_Language_Modes][03]
290+
- [Measure-Command][07]
291+
292+
<!-- link references -->
293+
[01]: ../../security/security-features.md
294+
[02]: /dotnet/framework/install/repair
295+
[03]: /powershell/module/microsoft.powershell.core/about/about_language_modes
296+
[04]: /powershell/module/microsoft.powershell.core/about/about_profiles
297+
[05]: https://devblogs.microsoft.com/powershell/optimizing-your-profile/
298+
[06]: https://devblogs.microsoft.com/powershell/powershell-constrained-language-mode-and-the-dot-source-operator/
299+
[07]: xref:Microsoft.PowerShell.Utility.Measure-Command

reference/docs-conceptual/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ items:
367367
href: dev-cross-plat/performance/module-authoring-considerations.md
368368
- name: Optimize performance using parallel execution
369369
href: dev-cross-plat/performance/parallel-execution.md
370+
- name: Troubleshoot PowerShell startup
371+
href: dev-cross-plat/performance/startup-performance.md
370372
- name: Developing modern modules
371373
items:
372374
- name: Writing portable modules

0 commit comments

Comments
 (0)