วิธีเรียกใช้สคริปต์ PowerShell โดยไม่ต้องแสดงหน้าต่าง


127

เป็นไปได้อย่างไรที่จะเรียกใช้สคริปต์PowerShellโดยไม่แสดงหน้าต่างหรือเครื่องหมายอื่นใดให้กับผู้ใช้

กล่าวอีกนัยหนึ่งสคริปต์ควรทำงานอย่างเงียบ ๆ ในพื้นหลังโดยไม่มีสัญญาณใด ๆ กับผู้ใช้

เครดิตเพิ่มเติมสำหรับคำตอบที่ไม่ใช้ส่วนประกอบของบุคคลที่สาม :)


ชำระคำถามนี้หากคุณสนใจที่จะเรียนรู้: stackoverflow.com/questions/573623/powershell-vs-unix-shells
Thomas Bratt

โซลูชันนี้ใช้ได้กับ Task Scheduler เช่นกัน: stackoverflow.com/a/51007810/571591
Hilydrow

คำตอบ:


128

คุณสามารถเรียกใช้เช่นนี้ (แต่จะแสดงหน้าต่างชั่วขณะหนึ่ง):

PowerShell.exe -windowstyle hidden { your script.. }

หรือคุณใช้ไฟล์ตัวช่วยที่ฉันสร้างขึ้นเพื่อหลีกเลี่ยงหน้าต่างที่เรียกว่า PsRun.exe ที่ทำอย่างนั้น คุณสามารถดาวน์โหลดไฟล์ซอร์สและไฟล์ exe เรียกใช้งานตามกำหนดเวลาด้วย WinForm GUI ใน PowerShellPowerShell ฉันใช้สำหรับงานตามกำหนดเวลา

แก้ไข: ตามที่ Marco ตั้งข้อสังเกตพารามิเตอร์ -windowstyle นี้มีให้สำหรับ V2 เท่านั้น


6
ฉันรวบรวม PsRun อย่างไรก็ตามถ้าฉันเพิ่มลงในงานที่กำหนดเวลาไว้มันจะกะพริบหน้าต่างด้วย ...
Ciantic

2
เช่นเดียวกันที่นี่ยังใช้งานไม่ได้เนื่องจากหน้าต่างยังคงปรากฏขึ้นเพื่อเรียกใช้สคริปต์ มันออกอย่างรวดเร็ว แต่เรากำลังพยายามเรียกใช้สิ่งนี้ในพื้นหลังโดยไม่หยุดชะงัก
Nathan McKaskle

1
ใช่นั่นเป็นเหตุผลว่าทำไมจึงมี "แต่นี่แสดงหน้าต่างชั่วขณะหนึ่ง" ในการตอบกลับ
stej

21
@ThomasBratt สำหรับงานที่กำหนดเวลาไว้ฉันพบว่าสคริปต์ PowerShell ทำงานแบบเงียบ ๆ โดย-WindowStyle Hiddenที่งานนั้นถูกตั้งค่าเป็นRun whether user is logged on or notบนแท็บทั่วไปในส่วน "ตัวเลือกความปลอดภัย"
อาดัม

1
การใช้บัญชีผู้ใช้กับระบบยังหลีกเลี่ยงการแสดงหน้าต่าง
Jon Eldridge

28

ฉันมีปัญหาเดียวกันนี้ ฉันพบว่าถ้าคุณไปที่TaskในTask Schedulerที่เรียกใช้สคริปต์powershell.exeคุณสามารถคลิก " Run ไม่ว่าผู้ใช้จะเข้าสู่ระบบหรือไม่ " และจะไม่แสดงหน้าต่าง powershell เมื่องานทำงาน


3
ทางออกที่ดีที่สุดโดยไม่ต้องขึ้นอยู่กับส่วนขยายของบุคคลที่สามไฟล์ปฏิบัติการหรือสคริปต์ wrapper
กลับ

1
โปรดทราบว่าตัวเลือกนี้กำหนดให้ผู้ใช้ต้องมีสิทธิ์ "Log on as Batch Job"
gb96

วิธีการแก้ปัญหานี้จะทำให้สคริปต์ของฉันจะไม่ทำงานอย่างถูกต้อง
Martin Argerami

18

คุณสามารถใช้PowerShell Community Extensionsและทำสิ่งนี้:

start-process PowerShell.exe -arg $pwd\foo.ps1 -WindowStyle Hidden

คุณสามารถทำได้ด้วย VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/

(ผ่านทางฟอรัมนี้)


มี NuGet paclage สำหรับสิ่งนี้เพื่อให้ฉันสามารถเรียกใช้จาก Visual Studio ได้หรือไม่
Piotr Kula

13

นี่คือแนวทางที่ไม่ต้องใช้ args บรรทัดคำสั่งหรือตัวเรียกใช้งานแยกต่างหาก ไม่สามารถมองเห็นได้อย่างสมบูรณ์เนื่องจากหน้าต่างแสดงขึ้นชั่วขณะเมื่อเริ่มต้น แต่จากนั้นก็หายไปอย่างรวดเร็ว ฉันคิดว่านี่เป็นวิธีที่ง่ายที่สุดหากคุณต้องการเปิดสคริปต์ของคุณโดยการดับเบิลคลิกใน explorer หรือผ่านทางลัดเมนูเริ่ม (รวมถึงเมนูย่อยของ Startup) และฉันชอบที่มันเป็นส่วนหนึ่งของโค้ดของสคริปต์ไม่ใช่สิ่งภายนอก

วางไว้ที่ด้านหน้าสคริปต์ของคุณ:

$t = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
add-type -name win -member $t -namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)

10

นี่คือซับเดียว:

mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& 'C:\Example Path That Has Spaces\My Script.ps1'"""""", 0 : window.close")

แม้ว่าจะเป็นไปได้ที่สิ่งนี้จะกะพริบหน้าต่างสั้น ๆ แต่ก็น่าจะเป็นเหตุการณ์ที่หายาก


ในกรณีส่วนใหญ่การเรียกใช้ Powershell.exe ในบริบทผู้ใช้ที่ล็อกออนจะแสดงหน้าต่างแบบเต็มหรือแฟลชสั้น ๆ หากคุณใช้ -windowstyle hidden ในการลบหน้าต่างออกทั้งหมดคุณสามารถทำสิ่งใดสิ่งหนึ่งจากสองสิ่ง: 1: เรียกใช้ในบริบทของผู้ใช้อื่นเช่นบัญชีผู้ดูแลระบบ (จะไม่แสดงหน้าต่างใด ๆ สำหรับผู้ใช้ที่เข้าสู่ระบบ) หรือ 2: ใช้ vbscript กับ objshell.run พร้อมแฟล็กหน้าต่างที่ซ่อนอยู่เพื่อเปิด cmd.exe / c powershel.exe -file c: \ script.ps1 เมื่อ powershell ถูกเรียกจาก cmd มันจะทำงานในหน้าต่าง cmd ที่มีอยู่ซึ่งถูกซ่อนไว้แล้วโดย wscript.exe // b / nologo c: \ launcher.vbs
Iconiu

ว้าวทันใดนั้น ฉันไม่ได้สังเกตคำตอบของคุณในตอนแรก ฉันตอบด้วยสคริปต์ที่คล้ายกันมาก ยินดีที่ได้พบผู้รู้ที่ให้คำตอบที่แท้จริง
Gosha

นี่ควรเป็นคำตอบที่ได้รับการยอมรับเป็นวิธีการหนึ่งที่ดูเหมือนจะใช้ได้ในทุกสถานการณ์ (รวมถึงในตัวกำหนดตารางงานซึ่งเป็นปัญหาของฉัน)
Martin Argerami

6

ฉันประสบปัญหานี้เมื่อเรียกใช้จาก c # บน Windows 7 บริการ "Interactive Services Detection" ปรากฏขึ้นเมื่อเรียกใช้หน้าต่าง powershell ที่ซ่อนอยู่ในบัญชี SYSTEM

การใช้พารามิเตอร์ "CreateNoWindow" ป้องกันไม่ให้บริการ ISD ปรากฏคำเตือน

process.StartInfo = new ProcessStartInfo("powershell.exe",
    String.Format(@" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
   WorkingDirectory = executablePath,
   UseShellExecute = false,
   CreateNoWindow = true
};

5

ฉันคิดว่าวิธีที่ดีที่สุดในการซ่อนหน้าจอคอนโซลของ PowerShell เมื่อคุณเรียกใช้สคริปต์พื้นหลังคือรหัสนี้ ( คำตอบ " Bluecakes ")

ฉันเพิ่มรหัสนี้ในตอนต้นของสคริปต์ PowerShell ทั้งหมดของฉันที่ฉันต้องใช้ในพื้นหลัง

# .Net methods for hiding/showing the console in the background
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console
{
    $consolePtr = [Console.Window]::GetConsoleWindow()
    #0 hide
    [Console.Window]::ShowWindow($consolePtr, 0)
}
Hide-Console

หากคำตอบนี้ช่วยคุณได้โปรดให้คะแนน"Bluecakes" ในคำตอบของเขาในโพสต์นี้


สำหรับฉันคอนโซลยังคงแสดงประมาณหนึ่งวินาที
thdoan

3

ps1 ซ่อนจาก Task Scheduler และทางลัดด้วย

    mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")

2

ฉันได้สร้างเครื่องมือขนาดเล็กส่งการโทรไปยังเครื่องมือคอนโซลใด ๆ ที่คุณต้องการเริ่มต้นแบบไม่มีหน้าต่างไปยังไฟล์ต้นฉบับ:

https://github.com/Vittel/RunHiddenConsole

หลังจากคอมไพล์แล้วให้เปลี่ยนชื่อไฟล์ปฏิบัติการเป็น "<targetExecutableName> w.exe" (ต่อท้าย "w") และวางไว้ถัดจากไฟล์ปฏิบัติการดั้งเดิม จากนั้นคุณสามารถเรียกใช้ eG powershellw.exe ด้วยพารามิเตอร์ปกติและจะไม่ปรากฏหน้าต่าง

หากมีใครทราบวิธีตรวจสอบว่ากระบวนการที่สร้างขึ้นกำลังรอการป้อนข้อมูลอยู่หรือไม่ยินดีที่จะรวมโซลูชันของคุณ :)


1
นี่คือคำตอบที่ดีที่สุดถ้าคุณต้องการที่จะเรียกใช้สคริปต์ PowerShell ใช้MessageBoxโดยไม่ต้องใด ๆแฟลชของหน้าต่างในการเริ่มต้น (ต้อง EXE รวบรวมเป็น Winexe, ไม่ได้เป็น app คอนโซลและต้องกำหนดเวลางานจะได้รับการตั้งค่าเป็น "เรียกใช้เฉพาะเมื่อผู้ใช้จะเข้าสู่ระบบ บน "เพื่อให้กล่องโต้ตอบแสดงในเซสชันเดสก์ท็อปปัจจุบัน) ขอบคุณสำหรับการใช้งานนี้ powershellw.exe อยู่ในรายการสิ่งที่อยากได้ของฉันมาหลายปีแล้ว!
Carl Walsh

PS: ฉันได้รวมวิธีแก้ปัญหาสำหรับ "กำลังรอการป้อนข้อมูล" เมื่อสักครู่แล้ว (เช่นเดียวกับการแก้ไขข้อบกพร่องสองสามข้อ)!
คริส

@CarlWalsh ฉันคิดว่าคุณหมายความว่ามันไม่ใช่แอปคอนโซล แต่เป็นแอปแบบชนะแทนซึ่งถูกต้อง มันไม่รวมหน้าต่างใด ๆ แต่ควรกำหนดประเภทโครงการในไฟล์ csproj และคุณไม่จำเป็นต้องตั้งค่าประเภทเอาต์พุตเฉพาะหลังจากเปิดด้วยสตูดิโอภาพ
คริส

2

นี่คือโซลูชันการทำงานใน windows 10 ที่ไม่มีส่วนประกอบของบุคคลที่สาม ทำงานโดยการรวมสคริปต์ PowerShell ลงใน VBScript

ขั้นตอนที่ 1: เราจำเป็นต้องเปลี่ยนคุณสมบัติบางอย่างของ windows เพื่อให้ VBScript เรียกใช้ PowerShell และเปิดไฟล์. ps1 ด้วย PowerShell ตามค่าเริ่มต้น

-go เพื่อเรียกใช้และพิมพ์ "regedit" คลิกที่ตกลงจากนั้นอนุญาตให้ทำงาน

- วางเส้นทางนี้ "HKEY_CLASSES_ROOT \ Microsoft.PowerShellScript.1 \ Shell" แล้วกด Enter

- ตอนนี้เปิดรายการทางด้านขวาและเปลี่ยนค่าเป็น 0

- เปิด PowerShell ในฐานะผู้ดูแลระบบและพิมพ์ "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned" กด Enter และยืนยันการเปลี่ยนแปลงด้วย "y" จากนั้นป้อน

ขั้นตอนที่ 2: ตอนนี้เราสามารถเริ่มตัดสคริปต์ของเราได้แล้ว

- บันทึกสคริปต์ Powershell ของคุณเป็นไฟล์. ps1

- สร้างเอกสารข้อความใหม่และวางสคริปต์นี้

Dim objShell,objFSO,objFile

Set objShell=CreateObject("WScript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")

'enter the path for your PowerShell Script
 strPath="c:\your script path\script.ps1"

'verify file exists
 If objFSO.FileExists(strPath) Then
   'return short path name
   set objFile=objFSO.GetFile(strPath)
   strCMD="powershell -nologo -command " & Chr(34) & "&{" &_
    objFile.ShortPath & "}" & Chr(34)
   'Uncomment next line for debugging
   'WScript.Echo strCMD

  'use 0 to hide window
   objShell.Run strCMD,0

Else

  'Display error message
   WScript.Echo "Failed to find " & strPath
   WScript.Quit

End If

- เปลี่ยนเส้นทางไฟล์ไปยังตำแหน่งของสคริปต์. ps1 ของคุณและบันทึกเอกสารข้อความ

- ตอนนี้คลิกขวาที่ไฟล์แล้วไปที่เปลี่ยนชื่อ จากนั้นเปลี่ยนนามสกุลไฟล์เป็น. vbs แล้วกด Enter จากนั้นคลิกตกลง

ทำ! หากตอนนี้คุณเปิด. vbs คุณจะไม่เห็นหน้าต่างคอนโซลในขณะที่สคริปต์ของคุณกำลังทำงานอยู่เบื้องหลัง

อย่าลืมโหวตเพิ่มถ้าสิ่งนี้เหมาะกับคุณ!


1

นี่คือการสาธิตสนุก ๆ ในการควบคุมสถานะต่างๆของคอนโซลรวมถึงย่อและซ่อน

Add-Type -Name ConsoleUtils -Namespace WPIA -MemberDefinition @'
   [DllImport("Kernel32.dll")]
   public static extern IntPtr GetConsoleWindow();
   [DllImport("user32.dll")]
   public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'@

$ConsoleMode = @{
 HIDDEN = 0;
 NORMAL = 1;
 MINIMIZED = 2;
 MAXIMIZED = 3;
 SHOW = 5
 RESTORE = 9
 }

$hWnd = [WPIA.ConsoleUtils]::GetConsoleWindow()

$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MAXIMIZED)
"maximized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.NORMAL)
"normal $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MINIMIZED)
"minimized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.RESTORE)
"restore $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.HIDDEN)
"hidden $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.SHOW)
"show $a"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.