แก้ไข: การเริ่มต้นช้าของคอนโซล PowerShell และสคริปต์

/th/images/powershell-console-takes-30-second-to-open.png

ฉันสังเกตเห็นว่าบางครั้งคอนโซล PowerShell ใช้เวลานานในการเปิด ปัญหานี้เกิดขึ้นในคอมพิวเตอร์ที่แตกต่างกัน ในบางกรณีอาจใช้เวลาหลายนาทีเพื่อให้ PowerShell โหลด สิ่งนี้มีผลต่อการเปิดของเชลล์คำสั่งเอง (powershell.exe หรือ pwsh.exe) และเวลาดำเนินการของสคริปต์ Logon PowerShell ที่เปิดตัวผ่าน GPO หรือสคริปต์ในงานที่กำหนด โพสต์นี้อธิบายวิธีการระบุเหตุผลที่เป็นไปได้สำหรับการเริ่มต้น PowerShell ช้าและลดเวลาในการโหลด

นี่คือเหตุผลทั่วไปที่ PowerShell อาจใช้เวลานานในการโหลด:

  • ฟังก์ชั่นที่ผู้ใช้กำหนดไว้ในไฟล์โปรไฟล์ PowerShell จะถูกโหลดทุกครั้งที่กระบวนการ PowerShell.exe เริ่มต้นขึ้น

  • มีการติดตั้งโมดูล PS จำนวนมากและโหลดโดยอัตโนมัติ

  • โมดูล psreadline โหลดไฟล์ขนาดใหญ่ที่มีประวัติของคำสั่ง PowerShell

  • การชะลอตัวอย่างมีนัยสำคัญใน PowerShell และการโหลดโมดูลเกิดจากความขัดแย้งหรือการทุจริตในส่วนประกอบเฟรมเวิร์ก NET

CMDLET แบบวัดการวัดสามารถใช้ในการวัดเวลาโหลดของกระบวนการ PowerShell ใช้คำสั่งนี้เพื่อตรวจสอบเวลาโหลดของ PowerShell ในโหมดปกติ:

PowerShell-Noprofile-ExecutionPolicy Bypass (Measure-Command {PowerShell" Write-Host 1 "}). Totalseconds

/th/images/powershell-console-takes-30-second-to-open.png

คำสั่งจะแสดงระยะเวลาที่กระบวนการ PowerShell ใช้ในการโหลดและดำเนินการคำสั่งง่ายๆ

เมื่อ PowerShell เริ่มต้นมันอาจรายงานเวลาที่ใช้ในการโหลด


Loading personal and system profiles took XXX ms

/th/images/message-in-powershell-loading-personal-and-system.png

อย่างที่คุณเห็นในตัวอย่างนี้กระบวนการ PowerShell ใช้เวลาโหลด 12 วินาที มันค่อนข้างมาก ข้อความนี้จะปรากฏขึ้นโดยอัตโนมัติหากเวลาโหลดของโปรไฟล์ PowerShell เกิน 500 ms

สิ่งนี้ชี้ให้เห็นว่าไฟล์โปรไฟล์ PowerShell กำลังดำเนินการรหัสช้าทุกครั้งที่กระบวนการเริ่มต้น

เปรียบเทียบความเร็วเริ่มต้นของกระบวนการ PowerShell เมื่อไม่ได้โหลดโปรไฟล์ ในการทำเช่นนี้ให้เรียกใช้กระบวนการเชลล์ด้วยตัวเลือกที่โนโปรเฟลี่:

powershell.exe-noprofile

หรือเพื่อเรียกใช้ PowerShell Core:

pwsh.exe-noprofile

/th/images/run-powershell-without-loading-profiles.png

อย่างที่คุณเห็น PowerShell เริ่มเร็วขึ้นมากเมื่อโปรไฟล์ไม่ได้โหลด โปรไฟล์ PowerShell เป็นไฟล์ PS1 ที่ใช้ในการกำหนดค่าสภาพแวดล้อมผู้ใช้ พวกเขายังอนุญาตให้ผู้ใช้เรียกใช้คำสั่งเฉพาะและโหลดฟังก์ชั่นหรือโมดูลที่กำหนดเอง

โดยค่าเริ่มต้นไฟล์โปรไฟล์ PowerShell จะไม่ถูกใช้ (ไม่มีการสร้างไฟล์โปรไฟล์) คำสั่งต่อไปนี้แสดงรายการไฟล์โปรไฟล์ทั้งหมดที่จะโหลดเมื่อกระบวนการ PowerShell เริ่มต้นขึ้น

$ profile | เลือก *

/th/images/list-powershell-profiles.png

ตรวจสอบเนื้อหาของไฟล์โปรไฟล์ทั้งหมดสำหรับผู้ใช้ด้วยตนเองหรือใช้คำสั่งต่อไปนี้เพื่อแสดง:

`get-content $ profile.allusersallhosts

get-content $ profile.alluserscurrenthost

get-content $ profile.currentuserallhosts

get-content $ profile.currentusercurrenthost `

ในกรณีของฉันมีการเพิ่มคำสั่งบางคำลงในไฟล์ผู้ใช้ Microsoft.PowerShell_profile.ps1 ตรวจสอบไฟล์โปรไฟล์เพื่อให้แน่ใจว่าจำเป็นต้องใช้คำสั่งและฟังก์ชั่นทั้งหมด หากเป็นไปได้ให้ลบคำสั่งที่ไม่จำเป็นและเพิ่มประสิทธิภาพรหัส /th/images/list-used-powershell-profile-files.png

การติดตั้งโมดูลจำนวนมากอาจเป็นอีกเหตุผลที่เป็นไปได้สำหรับการเริ่มต้น PowerShell ที่ช้า PowerShell โหลดโมดูลโดยอัตโนมัติจากโฟลเดอร์ต่อไปนี้:


C:\Users\%username%\Documents\WindowsPowerShell\ModulesC:\Program Files\WindowsPowerShell\ModulesC:\Windows\system32\WindowsPowerShell\v1.0\Modules

รายการของพวกเขาสามารถแสดงดังนี้:

$ env: psmodulepath-split ';'

/th/images/list-used-ps-module-paths.png

แสดงรายการโมดูล PS ที่โหลดลงในเซสชัน

get-module-listavailable

แสดงรายการโมดูลบุคคลที่สามที่ติดตั้ง

get-installedModule

/th/images/get-installedmodule.png

ตรวจสอบรายการเพื่อดูว่าคุณต้องการโมดูลทั้งหมดหรือไม่ ถอนการติดตั้งโมดูล PowerShell ที่ไม่ได้ใช้งาน:

`remove-mody-name burnttoast

ถอนการติดตั้ง-ชื่อชื่อการเผาไหม้-allversions-force `

ในการวิเคราะห์เวลาในการโหลดของแต่ละโมดูลให้ใช้คำสั่งต่อไปนี้:

`การวัด-คอมมิวนิส

หรือตรวจสอบเวลาโหลดของโมดูล PS ทั้งหมดเป็นกลุ่ม:

`$ modules = get-installedModule | เลือกชื่อ-exproperty ชื่อ unique

foreach ($ mod ใน $ modules) {

$ TIME = MEAMENT-COMMAND {Import Module $ mod-Force}

pscustomobject@{

โมดูล = $ mod

loadtimesec = $ time.totalseconds

/th/images/measure-powershell-module-load-time.png

ดูว่าโมดูลใดใช้เวลานานที่สุดในการโหลด

เพื่อป้องกันไม่ให้โมดูล PS ทั้งหมดโหลดโดยอัตโนมัติเพิ่มบรรทัดต่อไปนี้ในไฟล์โปรไฟล์:

`$ psmoduleautoLoadingPreference = ‘ไม่มี’

ในกรณีนี้คุณสามารถโหลดโมดูลที่ต้องการด้วยตนเองโดยใช้คำสั่งต่อไปนี้:

การนำเข้าโมดูล modulename

ตรวจสอบให้แน่ใจว่าได้เพิ่มโมดูลทั่วไปต่อไปนี้ในไฟล์โปรไฟล์ของคุณ:

`การนำเข้าโมดูล microsoft.powershell.utility

การนำเข้าโมดูล Microsoft.powershell.Management `

นอกจากนี้ยังมีปัญหาที่ทราบกันดีเมื่อโหลดโมดูลการจัดการโครงสร้างพื้นฐาน VMware PowerShell ซึ่งเป็นที่รู้จักกันในชื่อ VMware PowerCLI โมดูลอาจใช้เวลาหลายนาทีในการโหลดบนคอมพิวเตอร์ที่ไม่ได้เชื่อมต่อกับอินเทอร์เน็ต ปัญหาคือเมื่อโหลดโมดูลพยายามตรวจสอบรายการภายนอกของใบรับรองที่ถูกเพิกถอน (CRL, รายการการเพิกถอนใบรับรอง) เนื่องจากขาดการเชื่อมต่ออินเทอร์เน็ตกระบวนการนี้จึงหมดเวลา วิธีแก้ปัญหาคือการปิดใช้งานการตรวจสอบ CRL ใน Windows คุณสามารถปิดการตรวจสอบ CRL ผ่านรีจิสทรี:

reg เพิ่ม hklm \ system \ currentcontrolset \ services \ sstpsvc \ parameters/v nocerTrevocationCheck/t reg\_dword/d 0x00000001/f

หรือในแอปเพล็ตคุณสมบัติอินเทอร์เน็ต: inetcpl.cpl-> ขั้นสูง-> ยกเลิกการตรวจสอบตัวเลือกสำหรับการเพิกถอนใบรับรองผู้เผยแพร่ (เซิร์ฟเวอร์)

/th/images/disable-checking-for-publisher-server-certificat.png

เหตุผลที่ PowerShell อาจใช้เวลานานในการเริ่มต้นมักจะเป็นซอฟต์แวร์ป้องกันไวรัสที่ติดตั้งบนคอมพิวเตอร์ คุณสามารถตรวจสอบ DLL และโมดูลภายนอกที่โหลดได้เมื่อกระบวนการ PowerShell เริ่มต้นขึ้น

  1. เปิด cmd.exe และเรียกใช้คำสั่ง: powershell.exe-c" การเขียน $ pid; start-leep-s 60 " `

  2. คำสั่งนี้ส่งคืนรหัสกระบวนการ (PID) ของกระบวนการ PowerShell.exe คัดลอก

PID

และวางลงในคำสั่งต่อไปนี้ในเซสชั่น PowerShell ใหม่:

`get-process | โดยที่ {$ _. id-eq } | เลือกโมดูล ExpandProperty ``

  1. คุณจะได้รับรายการ DLL ที่โหลดเมื่อกระบวนการ PowerShell เริ่มต้นขึ้น ตรวจสอบว่าห้องสมุดป้องกันไวรัสของคุณอยู่ในรายการหรือไม่ ถ้าเป็นเช่นนั้นให้ลองเพิ่ม pwsh.exe และ powerShell.exe กระบวนการลงในข้อยกเว้น Antivirus ของคุณ /th/images/list-dlls-loaded-when-the-powershell-process-start.png

ตัวอย่างเช่นคุณสามารถใช้คำสั่งด้านล่างเพื่อเพิ่มการยกเว้นใน Windows Defender Antivirus ในตัว:

add-mppreference-exclusionProcess" c: \ windows \ system32 \ windowspowershell \ v1.0 \ powershell.exe "," c: \ program files \ powershell \ 7 \ pwsh.exe "

หากคุณสงสัยว่าการเริ่มต้นที่ช้าของ PowerShell นั้นเกิดจากการทำงานของไลบรารี Slow.net Framework คุณสามารถรวบรวมแอสเซมบลีที่ใช้ทั้งหมดลงในรหัสเครื่องจักรดั้งเดิมโดยใช้เครื่องมือ ngen.exe (เครื่องกำเนิดภาพดั้งเดิม) สิ่งนี้จะปรับปรุงประสิทธิภาพของแอปพลิเคชัน NET อย่างมีนัยสำคัญรวมถึง PowerShell:

`$ env: path = runtime.interopservices.runtimeenvironment :: getRuntimedirectory ()

appdomain :: currentdomain.getAssemblies () | Foreach-Object {

$ path = $ _. ตำแหน่ง

ถ้า ($ path) {

$ name = split-path $ path-leaf

WRITE-HOST-FORUNGERCOLOR YELLOUL

/th/images/ngen-exe-regenerates-native-images-to-compiled.png

เครื่องมือตรวจสอบกระบวนการคลาสสิกยังสามารถใช้ในการวิเคราะห์เวลาเริ่มต้น PowerShell ( https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx) เรียกใช้ procmon64.exe เปิดใช้งานตัวกรองในกระบวนการ powershell.exe เปิดเปลือก PS และระบุการดำเนินการที่ทำให้เกิดความล่าช้ามากที่สุด

/th/images/use-process-monitor-to-identify-the-cause-of-the-s.png

ในตัวอย่างของฉันการอ่านไฟล์ประวัติคำสั่ง PowerShell ที่ดูแลโดยโมดูล PSReadline ใช้เวลาประมาณ 30 วินาที (c: \ users \ username \ AppData \ Roaming \ Microsoft \ Windows \ PowerShell \ psReadline \ consolehost\_history.txt) ปัญหาเกิดจากไฟล์ consolehost_history.txt เกินขนาด 2 GB การทำความสะอาดไฟล์ประวัติลดเวลาเริ่มต้นของ PowerShell อย่างมีนัยสำคัญ

*ลิงค์แหล่งที่มา:

สคริปต์ Logon PowerShell เปิดตัวผ่าน GPO, สคริปต์ในงานที่กำหนดเวลาประวัติของคำสั่ง PowerShell, PowerShell Core, Antivirus ผู้พิทักษ์ Windows ผู้พิทักษ์ Windows ในตัว ] ( https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx)