Оставляя мой оригинальный ответ ниже, но с тех пор я нашел более эффективный способ без копии файла:
# 2>NUL & @powershell -nop -ep bypass "(gc '%~f0')-join[Environment]::NewLine|iex" && @EXIT /B 0
Это должно быть включено в качестве первой строки сценария powershell, сохраненного как .cmd
файл.
Разбивка:
# 2>NUL &
Это обрабатывает пакетную часть нашего файла, чтобы мы могли получить эту функцию исполнения клика.Поскольку #
не является именем файла или командой, он выдает ошибку, которую мы игнорируем с помощью 2>NUL
, и переходим к следующей команде с помощью &
.
@powershell ...
Это наш вызов powershell , захват содержимого файла (gc
: Get-Content
) и выполнение их (iex
: Invoke-Expression
).Мы используем @
, чтобы команда не отображалась в кли.
&& EXIT /B 0
Это корректно завершит работу сценария, если не было выдано ошибок.
Если ваша единственная цельчтобы у пользователя была возможность щелкнуть по ярлыку для запуска сценария powershell, это можно сделать с помощью вставки содержимого сценария в этот заголовок (сохраненный как myscript.cmd
или как вы хотите его назвать):
::<#
@ECHO OFF
REM /3360348/sozdanie-ispolnyaemogo-faila-exe-iz-skripta-powershellanswer-4629494
REM https://blogs.msdn.microsoft.com/zainala/2008/08/05/using-0-inside-the-batch-file-to-get-the-file-info/
SET "pwsh=%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe"
SET "args=-NoProfile -NoLogo -ExecutionPolicy Bypass -Command"
SET "cmd="@(Get-Content -Path '%~f0') -replace '^^::'^|Set-Content -Path '%~dpn0.ps1';. '%~dpn0.ps1' %*""
%pwsh% %args% %cmd%
DEL "%~dpn0.ps1" /Q /F
EXIT
::#>
Проще говоря, он обрабатывает политику выполнения и сохраняет себя как скрипт powershell после замены частей пакета в качестве комментария блока.