Powershell: لا يزال Powershell -WindowStyle Hidden يظهر نافذة لفترة وجيزة

تم إنشاؤها على ٢٢ يناير ٢٠١٧  ·  90تعليقات  ·  مصدر: PowerShell/PowerShell

خطوات التكاثر

في مربع حوار Windows Run ، اكتب هذا:
PowerShell.exe -WindowStyle Hidden -Command ping www.microsoft.com

سلوك متوقع

يجب ألا تكون هناك نافذة ، في الوقت الحالي لا يمكنك بدء بوويرشيل بدون وميض النافذة ، مما يجعلها عديمة الفائدة على سبيل المثال للمهام المجدولة.

ملاحظة أعتقد أن هذا سلوك مقصود ، لكنه محير وربما يكون الخيار الجديد مطلوبًا. إذا كنت تبحث عن كيفية تشغيل بوويرشيل في مهمة مجدولة ، فإن الحل البديل هو القيام بنص vbs لجميع الأشياء! مثل:

Dim shell,command
command = "powershell.exe -nologo -File D:\myscript.ps1"
Set shell = CreateObject("WScript.Shell")
shell.Run command,0

هذا ليس شيئًا جيدًا ، فباويرشيل يحتاج إلى هذه الميزة في الصدفة نفسها ، والمهام المجدولة هي ميزة مهمة ووجود وميض في مهمة مجدولة يعد تجربة سيئة حقًا.

السلوك الفعلي

يومض نافذة بوويرشيل لفترة وجيزة.

بيانات البيئة

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Issue-Enhancement OS-Windows WG-Interactive-Console

التعليق الأكثر فائدة

يمكن أن يكون لديك powershellw.exe والذي سيكون تطبيق GUI لا يظهر نافذة وحدة التحكم. مثل ما يفعله javaw.exe و pythonw.exe .

ال 90 كومينتر

powerhell.exe هو تطبيق وحدة التحكم. يتم إنشاء نافذة وحدة التحكم تلقائيًا بواسطة نظام التشغيل عند بدء العملية. يتم تنفيذ التعليمات البرمجية powerhell.exe التي تعالج -WindowStyle Hidden بعد فتح نافذة وحدة التحكم ومن ثم الفلاش. لإصلاح هذا ، سنحتاج إلى ما يعادل wscript ، أي تطبيق مضيف win32 بدلاً من تطبيق مضيف وحدة التحكم.

نظرًا لعدم وجود تغيير في الكود يمكننا القيام به فيowershell.exe لمعالجة هذا الأمر ، فقد قمت بتغيير هذه المشكلة إلى طلب ميزة أن يكون لديك مضيف يشبه wscript لدعم هذا النوع من السيناريو

http://www.f2ko.de/en/p2e.php
و Power Shell Studio لديه مضيف مخصص أيضًا

يمكن أن يكون لديك powershellw.exe والذي سيكون تطبيق GUI لا يظهر نافذة وحدة التحكم. مثل ما يفعله javaw.exe و pythonw.exe .

هل يمكن لـ pwsh.exe الحصول على دعم لهذا أو الحصول على pwshw.exe كما هو مقترح أعلاه؟ مع كون هذا pwsh exe جديدًا ، يبدو أنه وقت رائع لتغيير سلوك -windowstyle hidden . لم يستخدم أحد من قبل hidden وفكر "نعم هذا ما أردت ، وميض بعض الشاشة لثانية واحدة".

من المنطقي أنه لا يمكن تغيير Powershell.exe بعد كل هذا الوقت وإرثه.

سأدعم مساهمة المجتمع لإضافة pwshw.exe

موافق .. سيكون هذا متوافقًا مع البرامج التنفيذية للغات الأخرى ويحل لي الاضطرار حاليًا إلى تغليف نصوص بوويرشيل الخاصة بي في نصوص vbs.

من الناحية الفنية يمكننا فعل مثل https://github.com/AvaloniaUI/Avalonia/wiki/Hide-console-window-for-self-contained-.NET-Core-application
c# editbin.exe /subsystem:windows yourapp.exe

لكنني أتساءل - إذا كان PowerShell Core محمولًا ، فما هو السلوك المتوقع على Unix؟ هل يمكن أن نتحد على جميع المنصات؟
مناقشة ذات صلة https://github.com/dotnet/cli/issues/296 كما يذكر أنه يمكننا استخدام النظام الفرعي GUI.

ربما @ mklement0 لديك أي أفكار؟

iSazonov -WindowStyle غير مدعوم على أنظمة غير Windows

نعم ، أعني - هل لدينا نفس السلوك على Unix من خلال إنشاء وحدة تحكم؟ هل لدينا سيناريوهات لا نريد إنشاء وحدة التحكم فيها على نظام Unix؟

@ iSazonov : أنا لم أبحث في هذا حقًا ؛ الشيء الوحيد الذي يمكنني إخبارك به ، من خلال التجربة الشخصية ، هو أن استدعاء pwsh يعمل بشكل غير مرئي بشكل جيد من المرافق مثل Alfred 3 و TextExpander

ما كنت أستخدمه حتى الآن هو اختصار يسمى PS مع الهدف: C: \ Windows \ System32 \ WindowsPowerShell \ v1.0powershell.exe وخيار التشغيل: تصغير
مثله:
C:\Windows\PS Start-Process .
شريط المهام وميض ولكن لا يوجد المزيد من وحدة التحكم.

يبدو أن -WindowStyle Hidden يجب أن يكون المعلمة الأولى لسطر الأوامر.

لذلك ، بدأنا في دعم Windows PowerShell الآن ؟؟

مجرد تذكير ودود ، إذا كانت هذه مشكلة PowerShell Core؟ يرجى تقديم إصدار PowerShell Core كما هو مطلوب عند إرسال المشكلات.

بخلاف ذلك ، يحتاج Windows PowerShell إلى الانتقال إلى UserVoice على: https://windowsserver.uservoice.com/forums/301869-powershell

لمزيد من المعلومات ، راجع: https://github.com/PowerShell/PowerShell#windows -powershell-vs -owershell-core

:)

aresowj : في حين أن موضع الوسائط مهم عند استدعاء _CLI_ الخاص بـ PowerShell (نظرًا لأن أي شيء يتبع -Command يتم تفسيره كجزء من أمر التنفيذ) ، (أ) تضعه محاولة OP بالفعل قبل -Command و (b) لا يمنعان الوميض ، للأسباب الموضحة في تعليقBrucePay السابق .

MaximoTrinidad : على الرغم من أن هذه المشكلة ربما بدأت على أنها تركز على Windows PowerShell فقط ، فقد تحولت منذ فترة طويلة إلى طلب ميزة PS Core (والذي يستحق أيضًا إعادة النقل إلى Windows PowerShell).

للتلخيص: للحصول على استدعاءات غير مرئية بالكامل عبر PowerShell CLI:

  • في _Windows_ ، يلزم وجود برنامج PowerShell تنفيذي جديد ومنفصل ( pwshw.exe / powershellw.exe ) وهو تطبيق _GUI_ ، يتبع نموذج python.exe / pythonw.exe زوج

  • في نظامي macOS و Linux ، حيث لا توجد المشكلة ، أنا _presume_ ليست هناك حاجة إلى ملف تنفيذي منفصل. للتماثل مع Windows ، يمكن تنفيذ _symlink_ بسيط يشير ببساطة إلى pwsh العادي القابل للتنفيذ.

شكرا @ mklement0!
:)

آسف يا رفاق ، أخطأت في استخدام Powershells وشكرًا للتوضيح. :)

ماذا عن بدء تشغيل Powershell في البداية باستخدام وحدة تحكم غير مرئية ، ثم التحقق من وجود أي وسائط نافذة وحدة التحكم -WindowStyle وتنفيذها.
ولكن ، إذا لم يتم العثور على أي منها ، فيمكن عندئذٍ بدء نافذة وحدة تحكم مرئية.

لقد أنشأت مشكلة في إعادة إصدار فريق وحدة تحكم Windows هنا: https://github.com/Microsoft/console/issues/249

@ zero77 :

يجب أن يظل pwsh.exe تطبيقًا للنظام الفرعي لوحدة التحكم لضمان التنفيذ المتزامن المتصل بالتدفقات القياسية من نافذة وحدة التحكم الحالية.

لذلك نحتاج إلى النظام الفرعي الذي تمت مناقشته سابقًا _separate_ ، واجهة المستخدم الرسومية القابلة للتنفيذ ، pwshw.exe . إذا أردنا أن يدعم هذا الملف القابل للتنفيذ _conditional_ إنشاء نافذة وحدة تحكم (n جديدة دائمًا) ، فإن ارتباط

@ Jawz84 : لا أعتقد أن فريق وحدة التحكم يمكنه المساعدة هنا:

  • يقوم تطبيق _console-subystem_ مثل pwsh.exe بإنشاء نافذة وحدة تحكم جديدة دائمًا ، والتي تحدث قبل أن يرى التطبيق أيًا من وسائطه.

  • الطريقة الوحيدة لإخفاء _ أو _ منع الإنشاء_ لنافذة وحدة التحكم هذه هي أن يكون لديك تطبيق _GUI-subystem_ كنقطة دخول. في أبسط الحالات ، يمكن أن يكون تطبيق النظام الفرعي GUI _stub_ الذي ينقل الوسائط إلى تطبيق وحدة التحكم ، ولكنه يبدأ تشغيله _ المخفي_.

سأترك مشكلة وحدة التحكم مفتوحة ، انظر ماذا يعتقدون. أرى وجهة نظرك ، وأعلم أنه قد يكون مستحيلًا تمامًا. ومع ذلك ، مرة أخرى ، قد يكون شيئًا يودون التفكير فيه.

[تحرير:] لدي إجابة مفادها أن هذا غير ممكن حاليًا لتعويض في وحدة التحكم. سيكون ملف pwshw.exe المنفصل هو السبيل للذهاب الآن.

ييكيس! مفتوح لما يقرب من عامين؟ هذه ميزة مهمة جدًا للمسؤولين.

Chiramisu لا تتردد في تقديم العلاقات العامة - اقتراح في تعليقي أعلاه.

أوافق على طلب الميزة هذا ، السلوك الافتراضي لـ Powershell عند تشغيله كأمر أمر محير

أبدأ في رؤية هذا بعد تطبيق تحديثات Windows. شيء ما تغير مؤخرا؟

هل نظر أي شخص إلى ما يتطلبه هذا في الممارسة؟

أنا أنظر إلى ملف Powershell.exe ، ويبدو الأمر بسيطًا إلى حد ما:

https://github.com/PowerShell/PowerShell/blob/master/src/powershell/Program.cs

الآن ، لجعله بدون وحدة تحكم ، هل هو مجرد إعداد مشروع رتق مثل تغيير نوع الإخراج إلى "تطبيق Windows" بدلاً من تطبيق وحدة التحكم؟

لم يكن هناك قرار لجعل pwsh w .exe و backportowershell w .exe الذي يبدو أنه الخيار المعقول الوحيد بعد ملاحظات فرق وحدة التحكم أعلاه.

لن يكون هذا غير عادي نظرًا لوجود C:\windows\System32\taskhostw.exe . يبدو أن هناك بعض العناصر التي تستخدم هذا النمط في النوافذ تبحث عن *w.exe في C:\windows\System32\

أنا شخصياً كنت أعتقد أن مجرد تغيير pwsh.exe لإصلاح -windowstyle دون الرجوع إلى powerhell.exe مقبول لأنه جديد ولكن لا شيء بهذه البساطة كما يبدو.

Ciantic يجب أن يكون العمل هو نسخ powershell-win-core وتحديث ملف .csproj بحيث يكون Assembly pwshw و OutputType winexe . ثم يتغير في build.psm1 حتى نقوم ببناء كليهما.

لقد أنشأت أداة صغيرة لتمرير المكالمة إلى أي أداة وحدة تحكم تريد بدء تشغيلها بدون إطار إلى الملف الأصلي:

https://github.com/Vittel/RunHiddenConsole

بعد التجميع ، أعد تسمية الملف التنفيذي إلى "<targetExecutableName> w.exe" (قم بإلحاق "w") ، ثم ضعه بجوار الملف القابل للتنفيذ الأصلي.
يمكنك بعد ذلك استدعاء eGowershellw.exe أو pwshw.exe بالمعلمات المعتادة ولن تظهر لك نافذة.

إذا كان لدى شخص ما فكرة عن كيفية التحقق مما إذا كانت العملية التي تم إنشاؤها تنتظر الإدخال ، فسيسعدني تضمين الحل الخاص بك :)
تعديل:
وجدت حلا لهذه المشكلة

قم بتجميع إصدار وسأحاول ذلك في وقت ما! حقا عمل عظيم فيتيل :) 👍 💯

قم بتجميع إصدار وسأحاول ذلك في وقت ما! حقا عمل عظيم فيتيل :) 👍 💯

فكره جيده. فعل ذلك.

بالنسبة لمشكلة PowerShell المحددة (التي حدثت في المهام المجدولة) ، انتهيت من استخدام https://github.com/stbrenner/SilentCMD (أيضًا C #) ، سأقوم بتجربة RunHiddenConsole ...

Vittel شكرا لك على المشروع! تحتاج إلى الانتباه إلى إعادة توجيه الإدخال / الإخراج / الخطأ وربما الهروب من الوسيطة.

إذا قمنا بإنشاء مشروع pwshw جديد ، فيجب أن نفكر في الافتراضات: ربما يجب أن يكون -Noprofile .

مجرد تغيير OutputType إلى WinExe ليس كافيًا لأن netcoreapp2x لا يدعم هذا حاليًا. لكل https://github.com/dotnet/core-setup/issues/196#issuecomment -394786860 يبدو أننا بحاجة إلى انتظار netcoreapp30.

كما لمح iSazonov ، فإن مجرد البناء كـ winexe بدلاً من exe لن يكون حلاً كاملاً. لن تعمل بعض المعلمات الحالية التي يسمح بها pwsh.exe بشكل صحيح ضمن pwshw.exe (مثل -NoExit حيث لن تظهر نافذة وحدة التحكم ، إنها فقط للأتمتة). لذا فإن أشياء مثل -NoProfile بشكل افتراضي وغيرها من الإعدادات الافتراضية الخاصة بالأتمتة مقابل التفاعلية سيكون من المنطقي وضعها في الاعتبار.

| المعلمة | الحالة
| - | -
| -ملف |
| -الأمر |
| -ConfigurationName |
| الأمر المشفر |
| -سياسة التنفيذ |
| -InputFormat |
| -تفاعلية | إزالة (غير مستخدم)
| -لا خروج | إزالة (غير مستخدم)
| -NoLogo | إزالة (غير مستخدم)
| غير تفاعلي | إزالة (افتراضيًا)
| -لا الملف الشخصي | إزالة (افتراضيًا)
| -تنسيق الإخراج | إزالة (غير مستخدم)
| الإصدار | إزالة
| -WindowStyle | إزالة (غير مستخدم)
| - دليل العمل |

إذا كان pwshw.exe لسيناريو عدم وجود وحدة تحكم ، فماذا سيكون exe لواجهة المستخدم الرسومية؟

كمرجع. من https://github.com/dotnet/core-setup/pull/3888 :

إمكانية إعادة تسمية المضيف.

لكني لم أجد المستندات حول كيفية إعادة التسمية.

شكرًا لجدول المعلمات المفيد ، @ iSazonov.

أعتقد أن -NonInteractive و -WindowStyle يمكن إزالتهما أيضًا ، لأنهما لهما معنى فقط في سياق نافذة _console_ - والتي لن تتوفر في النظام الفرعي GUI القابل للتنفيذ بحكم التعريف.

إذا كان pwshw.exe لسيناريو عدم وجود وحدة تحكم ، فما هو exe لواجهة المستخدم الرسومية؟

pwshw.exe يمكنه أداء واجب مزدوج:

  • للأتمتة (تشغيل مخفي من مهمة مجدولة ، على سبيل المثال)
  • لإطلاق البرامج النصية للتفاعل المستخدم فقط مع واجهة المستخدم الرسومية بدون نافذة وحدة تحكم غير مرغوب فيها (على سبيل المثال ، البرامج النصية التي تنشئ WinForms UIs).

لبدء تشغيل البرامج النصية للتفاعل بين المستخدم فقط ...

هل يجب أن نحتفظ بـ -WindowStyle أجلهم؟

وماذا عن وحدة التحكم في واجهة المستخدم الرسومية؟

هل يجب أن نحتفظ بـ -WindowStyle أجلهم؟

لا أعتقد أن هذا مفيد ، لأنه لا يوجد إخبار مسبقًا في أي نقطة ومن خلال الآلية التي سيتم إنشاء نافذة واجهة المستخدم الرسومية - إن وجدت - وسيتعين على الكود الذي ينشئها الاستعلام عن PowerShell عن معلمات بدء التشغيل الخاصة به بطريقة ما بالترتيب لاحترام القيمة.

ماذا تقصد بوحدة تحكم واجهة المستخدم الرسومية_؟

iSazonov pwshw حسب التعريف لن يحتوي على وحدة تحكم تفاعلية. -WindowStyle مخصص لنافذة وحدة التحكم. البرامج النصية التي تستفيد من WinForms / WPF مستقلة عن مضيف pwshw.

شكر! تم تحديث الجدول أعلاه.

أفضل تجنب إنشاء مضيف جديد لهذا ، وأنا أفضل كثيرًا حل هذا مع PTYs حيث تكون متاحة.

إليك الحل الآن - الشيء الوحيد الذي يظهر هو مثيل PowerShell في شريط المهام الذي يختفي بسرعة - لا مزيد من وميض conhost.exe على الشاشة.

$WshShell = New-Object -ComObject 'WScript.Shell'
$ShortcutPath = Join-Path -Path $ENV:Temp       -ChildPath 'Temp.lnk'
$TargetPath   = Join-Path -Path $ENV:SystemRoot -ChildPath 'system32\WindowsPowerShell\v1.0\powershell.exe'
$Arguments    = '-ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Temp\ScriptIWantToRunWithHiddenWindow.ps1"'

$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath  = $TargetPath
$Shortcut.Arguments   = $Arguments
$Shortcut.WindowStyle = 7
$Shortcut.Save()

& explorer.exe $ShortcutPath

يمكن للأفراد المغامرين دمج هذه التقنية مع psexec.exe -i لتشغيل البرامج النصية عن بُعد في جلسة المستخدمين المسجلين حاليًا.

  • لا يزال هذا يعرض نافذة فلاش مرئية سريعة على أنظمتي
  • لقد جربت silentCMD أعلاه ولكن هذا يتطلب net3.5 وهو غير مثبت على بعض أنظمة الطرف الثالث التي قمت بتشغيلها عليها

لا يبدو أن هناك حلًا على ما أعتقد

هل قمت بفحص مشروع GitHub الخاص بوحدة التحكم المخفية؟
لقد استخدمت عن قصد أقل المتطلبات الممكنة. يجب أن يعمل على جميع إصدارات windows تقريبًا

كما ذكر Ciantic ، فإن أفضل طريقة لحل هذه المشكلة هي استخدام برنامج نصي VB:

في ، قل ps-run.vbs put

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
    objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

ثم استخدمه لتشغيل الأمر الذي تريده ، على سبيل المثال من مهام Windows المجدولة مثل ذلك

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

أستخدم شيئًا كهذا لتشغيل مهمة بشكل متكرر دون رؤية أي نوافذ وامضة.

هل قمت بفحص مشروع GitHub الخاص بوحدة التحكم المخفية؟
لقد استخدمت عن قصد أقل المتطلبات الممكنة. يجب أن يعمل على جميع إصدارات windows تقريبًا

لقد جربته هذا الأسبوع وهو يعمل دون ظهور متطلبات net3.5. شكر! لطيف. سوف تضع VBS واحد في الاعتبار أيضًا.

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
    exit;
}
Copy-Item -Path ($PSScriptRoot + "\powershellw.exe") -Destination "c:\windows\system32\WindowsPowerShell\v1.0" 
New-Item -ItemType File -Path ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
Copy-Item -Path ($PSScriptRoot + "\check.ps1") -Destination ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
$tasks = Get-ScheduledTask
foreach($task in $tasks) {
    $taskexec = $task.actions.Execute -replace '.*\\'
    $taskname = $task.TaskName
    if ($taskexec.ToLower() -eq 'powershellw.exe' -or $taskexec.ToLower() -eq 'silentcmd.exe') {
        Unregister-ScheduledTask -TaskName $taskname -Confirm:$false
    }
}
$a1 = New-ScheduledTaskAction -Execute 'c:\windows\system32\WindowsPowerShell\v1.0\powershellw.exe'`
    -Argument ('-windowstyle hidden -executionpolicy bypass -file "C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1"')    
$t1 = New-ScheduledTaskTrigger -Daily -At 01:00
$t2 = New-ScheduledTaskTrigger -Once -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Hours 23 -Minutes 55) -At 01:00
$t1.Repetition = $t2.Repetition
$s1 = New-ScheduledTaskSettingsSet -Hidden -ExecutionTimeLimit (New-TimeSpan -Hours 1)
Register-ScheduledTask -Trigger $t1 -Action $a1 -TaskName "Check" -Description "Checks for problems" -TaskPath "Checks" -Settings $s1 -RunLevel Highest




PTY؟ ما هذا؟

Envoyé de mon iPhone

Le 18 مارس 2019 ، 21:51 ، Joey Aiello [email protected] a écrit:

أفضل تجنب إنشاء مضيف جديد لهذا ، وأنا أفضل كثيرًا حل هذا مع PTYs حيث تكون متاحة.

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

نسخة مبسطة من VBScript @ Roy-Orbison:

CreateObject("Wscript.Shell").Run("powershell -Command ""& '<PS command/script path>'"""),0

تم اختباره على جهازي باستخدام برنامج نصي أعمل عليه ، ويبدو أنه يعمل عند التشغيل باستخدام wscript من موجه PS أو مهمة مجدولة.

الإيجابيات:

  • لا تحتاج إلى وضع مسار البرنامج النصي على سطر الأوامر wscript .
  • لا يتم تعيين ExecutionPolicy على Bypass .

سلبيات:

  • تحتاج إلى برامج نصية VBScript منفصلة لكل أمر PowerShell.

أنا شخصياً أفضل حل VBScript على RunHiddenConsole ، لأنه لا يتضمن نشر ملف تنفيذي غير موقع إلى دليل النظام. ومع ذلك ، من الواضح أن الحصول على pwshw.exe / powershellw.exe سيكون أفضل من أي منهما.

أنا شخصياً أفضل حل VBScript على RunHiddenConsole ، لأنه لا يتضمن نشر ملف تنفيذي غير موقع إلى دليل النظام.

التوقيع لا ينبغي أن يكون مشكلة كبيرة. يمكنك حتى القيام بذلك بنفسك مع القليل من الجهد لبناء ذلك بنفسك
ملاحظة: لقد أضفت أيضًا خيار نشر الأداة بجوار البرامج النصية التي تريد تنفيذها مباشرةً. لذلك ليس مطلوبًا بعد الآن إعداده في النظام بجوار بوويرشيل القابل للتنفيذ

من الجيد أن يكون لديك حلول بديلة وحل من جهة خارجية ، ولكن للتأكيد على

هناك حاجة إلى حل يأتي مع PowerShell.


بالنسبة إلى الحلول البديلة: لاحظ أن الحل المستند إلى VBScript ممكن حتى بدون ملف نصي مساعد ، لكنه غامض:

ما يلي ، الذي يمكنك تشغيله من مربع الحوار Run (أو cmd.exe ) ، يُنشئ مثيل PowerShell غير مرئي ينبثق من مربع رسالة (بدون إظهار نافذة وحدة التحكم):

mshta.exe vbscript:(CreateObject("WScript.Shell").Run("pwsh -c (New-Object -Com Wscript.Shell).Popup('hi')",0))(Window.Close)

تحذير : يلاحظ alexbuzzbee أن "[هذا] الحل يولد تنبيهات في نظام حماية نقطة نهاية ATP للمدافع [...] لذلك قد لا يكون مناسبًا في بيئة مؤسسة".

هل سيكون من غير المعقول تحويل حل Vittel إلى حل رسمي؟ لا ينبغي أن يكون من الصعب نقل الكود إلى مستودع PowerShell ، وتعديله لإطلاق powershell.exe أو pwsh.exe ، وإنشاءه / توزيعه باستخدام PowerShell.

يدعم .NET Core 3.0 إنشاء winexe الذي لن يظهر وحدة التحكم. لدي بالفعل نموذج أولي عملي ، فقط أحتاج إلى تنظيفه كعلاقات عامة.

لدي بالفعل نموذج أولي يعمل

كنت في الطريق أيضًا :-) آمل أن تبسط CommandLineParameterParser (هل تريد إزالة EarlyParse؟).

يُنشئ حل @ mklement0 تنبيهات في نظام حماية نقطة النهاية ATP لـ Defender (لا يحب تشغيل رمز PowerShell mshta ) ، لذلك قد لا يكون مناسبًا في بيئة المؤسسة.

شكرًا ، alexbuzzbee ، لقد أضفت التنبيه إلى تعليقي السابق. أعتقد أن مكالمة VBScript CreateObject() / JScript new ActiveXObject() التي تطلق التنبيه ؛ على ما يبدو ، تم استخدام mshta.exe في البرامج الضارة في الماضي.

يبدو أن ATP @ mklement0 مريب على وجه التحديد من mshta بدءًا من pwsh ، بدلاً من المكالمة CreateObject() .

من الجيد معرفةalexbuzzbee.

لقد استندت في تعليقي إلى حقيقة أن تنفيذ ما يلي (على سبيل المثال من cmd.exe ) ينتج عنه Access is denied error. ويطلق تنبيه Windows Defender.

mshta vbscript:Execute("CreateObject(\"WScript.Shell\"): Window.Close")

خلاصة القول هي أن الحل البديل ربما يستفيد من ثغرة ، والتي - كما ذكرت - يمكنها تشغيل برامج الأمان الحالية ، وربما يتم إغلاقها تمامًا في المستقبل.

ياي لمحاولة @ SteveL-MSFT لتنفيذ حل مناسب.

@ SteveL-MSFT، 2018-02-20

سأدعم مساهمة المجتمع لإضافة pwshw.exe

@ SteveL-MSFT، 2019-10-31

يدعم .NET Core 3.0 إنشاء winexe الذي لن يظهر وحدة التحكم. لدي بالفعل نموذج أولي عملي ، فقط أحتاج إلى تنظيفه كعلاقات عامة.

لقد مر وقت طويل وسيكون رائعًا للبرمجة النصية ، خاصة مع Task Scheduler ، (ربما cron؟) ، وما إلى ذلك نظرًا لأن PowerShell Core متعدد الأنظمة الأساسية ، فهل سيعمل هذا أيضًا على الأنظمة الأساسية المدعومة الأخرى؟ ماذا عن WSL؟

عمل النموذج الأولي لـ winexe ولكنه كان خشنًا للغاية حول الحواف لجعله 7.0. على سبيل المثال ، إذا ارتكبت خطأً في سطر الأوامر ، فلن تعرف لأنه لا توجد نافذة إخراج. إذا اتبعنا أدوات أخرى مثل wscript.exe ، فيجب أن نعرض مربع حوار به رسالة الخطأ المناسبة.

بالنسبة لغير Windows ، لا يحتاج Linux و macOS إلى ما يعادل winexe لأنني أعتقد أنه يمكن بدء عملية pwsh دون إنشاء نافذة وحدة تحكم ، بينما يتطلب Windows ذلك لأنه يفرق صراحة بين تطبيقات وحدة التحكم و windows. يمكنك بالتأكيد استخدام pwsh مع Task Scheduler اليوم أو cron ، إلخ ... بالفعل.

نسخة أخرى من VBScript shim مع التحسين: دعم تمرير الحجج إلى Powershell Script. سيعطينا هذا مزيدًا من المرونة بشأن النص المطلوب استدعاؤه. كل ذلك بدون نافذة منبثقة!

بوويرشيل vbs:

Set args = CreateObject("System.Collections.ArrayList")
For Each oItem In Wscript.Arguments: args.Add oItem: Next

CreateObject("Wscript.Shell").Run("powershell -windowstyle hidden -File """ & Join(args.ToArray, """ """) & """"),0

على سبيل المثال ، لدي برنامج نصي بوويرشيل يستمع إلى حدث معين في Windows ، واستخدم برنامج جدولة المهام لاستخراج بيانات الحدث واستدعاء برنامج PowerShell النصي لإرسال إشعار حول الحدث. لقد أنشأت مهمة مجدولة مخصصة باستخدام EventTrigger مخصص (راجع منشور من Technet ):

    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription><!-- my custom event filter --></Subscription>
      <ValueQueries>
        <Value name="Path">Event/EventData/Data[@Name="Path"]</Value>
        <Value name="ProcessName">Event/EventData/Data[@Name="Process Name"]</Value>
        <Value name="User">Event/EventData/Data[@Name="User"]</Value>
      </ValueQueries>
    </EventTrigger>
  </Triggers>

بعد ذلك ، يمكننا استخدام المتغير $(Path) $(ProcessName) $(User) داخل إجراء الحدث. في هذه الحالة ، يمكننا استدعاء البرنامج النصي على النحو التالي. سيقوم Windows باستدعاء notifier.ps1 عند حدوث حدث ما.

wscript.exe "C:\path\to\powershell.vbs" "C:\path\to\notifier.ps1" -User $(User) -ProcessName $(ProcessName) -Path $(Path)

powershell.vbs قابل لإعادة الاستخدام تمامًا. 😏

الأصل: https://github.com/PowerShell/PowerShell/issues/3028#issuecomment -522375489

كما ذكر Ciantic ، فإن أفضل طريقة لحل هذه المشكلة هي استخدام برنامج نصي VB:

في ، قل ps-run.vbs put

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
  objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

ثم استخدمه لتشغيل الأمر الذي تريده ، على سبيل المثال من مهام Windows المجدولة مثل ذلك

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

أستخدم شيئًا كهذا لتشغيل مهمة بشكل متكرر دون رؤية أي نوافذ وامضة.

يمكنك استخدام QB64 لإنشاء EXE صغير لإخفاء البرنامج النصي. QB64 هو مترجم C ++ يأخذ كود QBASIC ويجمعه في C ++ exe. إذا كنت تستخدم الأمرين _SHELLHIDE أو SHELL _HIDE ، فيمكنك استدعاء برنامج نصي PowerShell من داخل EXE دون إظهار نافذة PowerShell على الإطلاق. أستخدم هذا جنبًا إلى جنب مع -WindowStyle Hidden فقط لأكون آمنًا ولكني لم أواجه أي مشاكل معه. مثال: SHELL$ = "PowerShell -WindowStyle Hidden -ExecutionPolicy Bypass " + CHR$(34) + "&'" + _STARTDIR$ + "\GetNewDate.ps1';exit $LASTEXITCODE" + CHR$(34): a = _SHELLHIDE(SHELL$)
يمكنك أيضًا إخفاء EXE بالكامل الذي جمعته باستخدام $SCREENHIDE حتى لا يضطروا إلى رؤية أي جزء من البرنامج.
إذا كان لديك رمز خروج تريد تمريره مرة أخرى إلى منطقة أخرى من التعليمات البرمجية ، فيمكنك استخدام exit $LASTEXITCODE عند استدعاء برنامج PowerShell النصي لإعادة تمريره إلى QB64 EXE. إذا كنت ترغب في تمرير الرمز من QB64 EXE ، فيمكنك استخدام الأمر SYSTEM متبوعًا بالرمز الذي ترغب في تمريره إلى باقي البرنامج / البرنامج النصي. أمل أن هذا يساعد شخصاما.

باستخدام هذا الآن حتى يحصل كل استدعاء على جميع الوسائط ، بدلاً من أن تكون كل وسيطة نصًا منفصلاً ، مثل ttimasdf ولكن باستخدام مصفوفة بسيطة:

Dim args()
Redim args(Wscript.Arguments.Count - 1)
For i = 0 To UBound(args): args(i) = Wscript.Arguments.Item(i): Next
CreateObject("Wscript.Shell").Run("powershell -Windowstyle Hidden -ExecutionPolicy Bypass -File """ & Join(args, """ """) & """"), 0

احتفظت بـ -ExecutionPolicy Bypass لأنني أحصل على إخفاقات صامتة ما لم أستخدم أيضًا Set-ExecutionPolicy . لا يمكن أن تنتظر pwshw.exe .

https://github.com/SeidChr/RunHiddenConsole/releases/download/1.0.0-alpha.2/hiddenw.exe

@ روي أوربيسون
ها أنت ذا. فقط يحتاج إلى إعادة تسمية 😉😅
(Srsly. قم بتسميته pwshw.exe ، ضعه في طريقك ، ويجب أن يعمل فقط)

حقًا لا أعرف ما الذي يستغرقه فريق pwsh وقتًا طويلاً.
إنها ليست صفقة كبيرة

حقًا لا أعرف ما الذي يستغرقه فريق pwsh وقتًا طويلاً.

قلة الموارد. نحن بحاجة إلى المزيد من المراجعين والمساهمين الكود.

لقد قمت بتكوين برنامج نصي PowerShell ليتم تشغيله من Elgato Stream Deck ، وفتح نافذة. حاولت استخدام -Noninteractive و -WindowStyle hidden ، لكن لا يزال يظهر لفترة وجيزة.

pwsh -Noninteractive -WindowStyle hidden -Command "...."

أتوقع أن نحصل على pwshw في المعاينة التالية.

لقد قمت بتكوين برنامج نصي PowerShell ليتم تشغيله من Elgato Stream Deck ، وفتح نافذة. حاولت استخدام -Noninteractive و -WindowStyle hidden ، لكن لا يزال يظهر لفترة وجيزة.

pwsh -Noninteractive -WindowStyle hidden -Command "...."

يمكنك بسهولة الالتفاف على تلك النافذة المنبثقة باستخدام الأداة التي نشرتها أعلاه. استخدامه كل يوم مع منصة Steam الخاصة بي ونصوص بدء التشغيل

لمعلوماتك: على فريق وحدة التحكم ، نقترح طريقة للتطبيقات المستقبلية (والإصدارات المستقبلية من التطبيقات الحالية) للتعامل مع هذا الأمر. سيكون هناك القليل من النفقات العامة [1] ، لكنه سيعطي PowerShell القدرة على اختيار ما إذا كان سيتم تخصيص نافذة وحدة التحكم عند إطلاقه في سياق واجهة المستخدم الرسومية.

طلب سحب المواصفات: https://github.com/microsoft/terminal/pull/7337

DHowett سعيد للغاية لأنني اكتشفت هذا قبل دمج العلاقات العامة الخاصة بي! سيكون من الأفضل للعميل أن يكون لديه ملف exe واحد ولا يقلق بشأن إصدارات winexe ، ناهيك عن تكاليف الصيانة للفريق.

ولكن ماذا لو اتصلت بـ PowerShell بدون Windows Terminal؟ على سبيل المثال ، أتصل بـ pwsh.exe مباشرة من Elgato Stream Deck. الخيار المقترح من فريق Terminal لن يحل هذا السيناريو ، أو غيره مثله ، أليس كذلك؟

@ pcgeek86 لا تدع الاسم يخدعك! أنا وفريقي نملك النظام الفرعي لوحدة تحكم windows بالكامل ، بما في ذلك كيفية تشغيل تطبيقات وحدة التحكم والتحدث مع بعضها البعض.

DHowett أعتبر أن هذا يعني أن الوظيفة ستكون متاحة فقط في الإصدارات المستقبلية من Windows؟ إذن أي شخص لا يزال يستخدم إصدارات Windows ذات المستوى الأدنى هو في الأساس محظوظ؟ 🤔

لن يقدم التطبيق الموجود في النظام الفرعي لوحدة التحكم باستخدام consoleAllocationPolicy الخاص بالوراثة فقط وحدة تحكم عند تشغيلها من Explorer .

ما هو سلوك برنامج جدولة المهام؟

DHowett لـ pwsh ، سيحتاج إلى علامة لتحديد أننا نريد تخصيص فارغ بحيث تظل البرامج النصية التي تستدعي واجهات برمجة تطبيقات وحدة التحكم تعمل

قد ترغب تطبيقات مثل PowerShell في الاحتفاظ بتخصيص وحدة التحكم "التلقائي" ، ولن يكون التوريث مناسبًا لها إلا.

إذن لا تحل السياسة جميع سيناريوهات PowerShell وينبغي على PowerShell استخدام حل بديل مرة أخرى؟

هذا يذكرني بعلاقات عامة حيث حاولت استخدام AllocConsole مباشرة.

المستوى الأدنى (@ vexx32)

لسوء الحظ ، هذا قيد على أي شيء ينتجه فريقي ويكون جزءًا من النظام الفرعي لوحدة التحكم ولا يمكن شحنه كجزء من Terminal. نحن نحاول العمل على ذلك 😉

ما هو سلوك Task Scheduler (iSazonov)

كان قول "Explorer" طريقة مناسبة لقول "أي سياق لا يحتوي بالفعل على وحدة تحكم" في كلمات أقل. كن مطمئنًا ، _ أي شيء يقوم بتشغيل تطبيق inheritOnly بدون وحدة تحكم لن يتسبب في تخصيص وحدة تحكم ._

ستحتاج إلى علامة لتحديد (@ SteveL-MSFT)

لحسن الحظ ، يحتوي PowerShell بالفعل على هذا في شكل WindowStyle . يمكن أن يكون الوضع الافتراضي "_i يجب استدعاء AllocConsole() _" (والذي سيخدم جميع احتياجات واجهة برمجة تطبيقات وحدة التحكم!) ، ما لم يطلب المستخدم التشغيل المخفي. المواصفات تنقل فقط مسؤولية تخصيص وحدة التحكم إلى (pwsh) حتى تتمكن من التحكم بشكل نهائي في ما إذا كان هناك مضيف أم لا. نظرًا لأنه تم إعداد بوويرشيل بالفعل للتعامل مع هذه الحالة ، فهي مجرد بضعة أسطر من دلتا قبل / بعد الاختيار "المخفي".

لا يحل جميع سيناريوهات PowerShell (iSazonov)

توضح المواصفات أيضًا كيف سيتعامل بوويرشيل مع هذا (انظر أعلاه ، ردي على ستيف). وبقدر ما أفهمه ، فإن هذا يحل جميع السيناريوهات الواردة في هذه المشكلة والمشكلات المرتبطة.

الاختلاف الأساسي بين استدعاء AllocConsole() / AttachConsole() كما فعلت في PR الخاص بك والاتصال بـ AllocConsole() عندما يتم عرض تطبيقك لسياسة تخصيص وحدة تحكم مختلفة هو أن بت النظام الفرعي يشير إلى ذلك يجب أن تنتظر قذيفة التفريخ (cmd ، pwsh ، bash ، ish) للخروج من الصدفة المولدة ( pwshw ) ، مما يقلل التداخل على مقابض الإدخال / الإخراج لوحدة التحكم.

إذا كان لديك تطبيق نظام فرعي لـ Windows يستدعي AttachConsole() للرجوع إلى وحدة تحكم الاستضافة الخاصة به ، فإن الصدفة التفريضية والتطبيق الجديد سيتقاتلان حول من يمكنه قراءة الإدخال / الكتابة المخرجات. هذا هو السبب في أن استدعاء Attach _never_ قابل للتطبيق من تطبيق نظام فرعي لـ Windows ، إلا إذا كان بإمكانك التحكم بشكل كامل في الصدفة التي أنتجتك (لا يمكنك ذلك).

DHowett شكرا! لتوضيح الاقتراح الخاص بـ PowerShell هو استخدام SUBSYSTEM_GUI وراثة فقط؟

أعتقد أن SUBSYSTEM_CUI و inheritOnly سيكونان صحيحين لـ PowerShell. يمنحك السلوكيات التالية:

  1. cmd ( $SHELL ) سينتظر pwsh للخروج قبل العودة ( SUBSYSTEM_CUI )
  2. عند تشغيله من المستكشف / المهام المحددة ، يمكن لـ pwsh اتخاذ القرار بشأن إنشاء نافذة وحدة تحكم جديدة ( inheritOnly )
  3. عند تشغيله من cmd / pwsh / (غلاف وحدة التحكم) ، ستتلقى pwsh تلقائيًا نافذة وحدة التحكم

عند تشغيله من المستكشف / المهام ، يمكن لـ pwsh اتخاذ القرار بشأن إنشاء نافذة وحدة تحكم جديدة (ترث فقط)

حسنًا ، كيف يمكن أن يعرف PowerShell أن هو مالك العملية - المستكشف أو المهام؟

لا أعتقد أنه يحتاج إلى معرفة.

إليكم السبب (C ++):

int main() {
    auto a{ _parseArgs() };
    if (a.WindowStyle != WindowStyle::Hidden)
    {
        AllocConsole();
    }
}

يعرف PowerShell

يوفر ذلك منصة جيدة لبناء المزيد من السلوك الجديد.

DHowett كما ذكر @ vexx32 أنه لا يزال هناك الكثير من Server 2012 / R2 & 2016 في البرية ، لذا بينما بالنسبة لمتغيرات Win10 & Server 2019 OS ، يبدو هذا رائعًا للمضي قدمًا ، أعتقد أنه بالنسبة لـ PowerShell ، نحتاج إلى التفكير في طريقة حول هذا أكثر أناقة من الحل الحالي المقترح @ SteveL-MSFT

ما لم يكن بإمكانك أيضًا نقل هذا التغيير إلى نظام التشغيل ذي المستوى الأدنى كجزء من تصحيح الأمان ، لأنك لا تقوم بتحديثات الميزات لهم ، (والتي أشك بشدة في أنك ستفعلها)

أن بت النظام الفرعي يشير إلى أن غلاف التفريخ (cmd ، pwsh ، bash ، ish) يجب أن ينتظر حتى يخرج القشرة المولدة (pwshw) ، مما يقلل التداخل على مقابض الإدخال / الإخراج لوحدة التحكم.

يجب أن يعمل مع PowerShell أيضًا. أعني أنه إذا قام PowerShell باستدعاء تطبيق وحدة تحكم خارجي ، فيجب أن يتبع السياسة الجديدة أيضًا. هل سيحصل PowerShell على هذا تلقائيًا أم أننا بحاجة إلى إضافة أي شيء في PowerShell؟

سيتعين على PowerShell الاشتراك كما هو مذكور في المواصفات. لقد طرحت نقطة رائعة ، على الرغم من ذلك: أعتقد أن التطبيقات التي ولدت _by_ تطبيق "وراثي فقط" سيظهر نوافذ وحدة التحكم ، وهذا أمر رهيب. سأعيد النظر في هذا في المواصفات ، لأنني أعتقد أنني أعرف كيف يمكننا معالجة ذلك.

ما لم يكن بإمكانك أيضًا نقل هذا التغيير إلى نظام تشغيل ذي مستوى أدنى

يجب إنجاز الميزة قبل أن نتمكن من تقييمها من أجل النقل الخلفي 😉 لكني أوافق بنسبة 100٪ على أن هذا يحد من فائدتها.

فقط أريد أن أقول أنه إذا كنت تطلق powerhell من برنامج آخر ، فهناك احتمال أن يدعم إخفاء العمليات الفرعية. على سبيل المثال ، يحتوي Autohotkey على علامة "إخفاء" لأمر التشغيل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات