windows - Convierta una secuencia de comandos PS pequeña en una línea larga en un archivo.BATch
powershell batch-file (3)
Hubo un tema en DosTips hace un tiempo que abordó esto. Puede hacer un lote / Powershell híbrido con un encabezado simple:
<# :
:: Header to create Batch/PowerShell hybrid
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=/"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( ''$input = $_; $_ = /"/"; $args = @( &{ $args } %POWERSHELL_BAT_ARGS% );'' + [String]::Join( [char]10, $( Get-Content /"%~f0/" ) ) )"
:: Any batch code that gets run after your PowerShell goes here
goto :EOF
#>
Simplemente arroje su código de Powershell después del
#>
y guarde el archivo como un script .bat normal.
En tu caso:
<# :
:: Header to create Batch/PowerShell hybrid
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=/"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( ''$input = $_; $_ = /"/"; $args = @( &{ $args } %POWERSHELL_BAT_ARGS% );'' + [String]::Join( [char]10, $( Get-Content /"%~f0/" ) ) )"
goto :EOF
#>
$WindowFunction,$RectangleStruct = Add-Type -MemberDefinition @''
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
''@ -Name "type$([guid]::NewGuid() -replace ''-'')" -PassThru
$MyWindowHandle = (Get-Process -Id (Get-WmiObject Win32_Process -Filter "ProcessId=$PID").ParentProcessId).MainWindowHandle
$WindowRect = New-Object -TypeName $RectangleStruct.FullName
$null = $WindowFunction::GetWindowRect($MyWindowHandle,[ref]$WindowRect)
Write-Host $WindowRect.Left $WindowRect.Top $WindowRect.Right $WindowRect.Bottom
Tengo este código de PowerShell que obtuve de la respuesta a esta pregunta ; muestra la ubicación / dimensiones de la ventana cmd.exe donde se ejecuta el código PS:
$WindowFunction,$RectangleStruct = Add-Type -MemberDefinition @''
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
''@ -Name "type$([guid]::NewGuid() -replace ''-'')" -PassThru
$MyWindowHandle = (Get-Process -Id (Get-WmiObject Win32_Process -Filter "ProcessId=$PID").ParentProcessId).MainWindowHandle
$WindowRect = New-Object -TypeName $RectangleStruct.FullName
$null = $WindowFunction::GetWindowRect($MyWindowHandle,[ref]$WindowRect)
Write-Host $WindowRect.Left $WindowRect.Top $WindowRect.Right $WindowRect.Bottom
Cuando ejecuto este código en un script .ps1 desde la línea de comando, funciona correctamente:
C:/Users/Antonio/Documents/test> powershell Set-ExecutionPolicy -ExecutionPolicy
Unrestricted -Scope Process; ./test.ps1
26 -7 943 738
Quiero insertar este código en un archivo .BATch para no tener un archivo .ps1 separado, por lo que debo escribir el mismo código en una línea larga como parámetros del comando
powershell
.
Sin embargo, para mantener la legibilidad, quiero usar líneas separadas en el archivo .bat y terminar cada una con el carácter de continuación Batch
^
;
Este fue mi primer intento:
@echo off
PowerShell ^
$WindowFunction,$RectangleStruct = Add-Type -MemberDefinition ''^
[DllImport("user32.dll", SetLastError = true)] ^
[return: MarshalAs(UnmanagedType.Bool)] ^
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); ^
[StructLayout(LayoutKind.Sequential)] ^
public struct RECT ^
{ ^
public int Left; ^
public int Top; ^
public int Right; ^
public int Bottom; ^
} ^
'' -Name "type$([guid]::NewGuid() -replace ''-'')" -PassThru; ^
$MyWindowHandle = (Get-Process -Id (Get-WmiObject Win32_Process -Filter "ProcessId=$PID").ParentProcessId).MainWindowHandle; ^
$WindowRect = New-Object -TypeName $RectangleStruct.FullName; ^
$null = $WindowFunction::GetWindowRect($MyWindowHandle,[ref]$WindowRect); ^
Write-Host $WindowRect.Left $WindowRect.Top $WindowRect.Right $WindowRect.Bottom
%End PowerShell%
Cuando ejecuto este archivo Batch, se informan varios errores:
C:/Users/Antonio/Documents/test> test.bat
Add-Type : c:/Users/Antonio/AppData/Local/Temp/yhd4ckqv.0.cs(8) : El nombre
''user32'' no existe en el contexto actual
c:/Users/Antonio/AppData/Local/Temp/yhd4ckqv.0.cs(7) : {
c:/Users/Antonio/AppData/Local/Temp/yhd4ckqv.0.cs(8) : >>>
[DllImport(user32.dll, SetLastError = true)] [return:
MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr
hWnd, ref RECT lpRect); [StructLayout(LayoutKind.Sequential)] public struct
RECT { public int Left; public int Top; public int Right; public int Bottom; }
c:/Users/Antonio/AppData/Local/Temp/yhd4ckqv.0.cs(9) :
En línea: 1 Carácter: 36
+ $WindowFunction,$RectangleStruct = Add-Type -MemberDefinition ''
[DllImport(user3 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : InvalidData: (c:/Users/Antoni...contexto actual:
CompilerError) [Add-Type], Exception
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
AddTypeCommand
Add-Type : No se puede agregar el tipo. Hubo errores de compilación.
En línea: 1 Carácter: 36
+ $WindowFunction,$RectangleStruct = Add-Type -MemberDefinition ''
[DllImport(user3 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
and a long et cetera....
Traté de pasar el apóstrofe a la línea de abajo, cambié los apóstrofos entre comillas y viceversa, eliminé espacios adicionales al comienzo de cada línea y varias otras modificaciones, pero no pude encontrar la forma correcta de escribir este código. Escribí varios segmentos de código PS antes mucho más grandes que este de la misma manera sin ningún problema. Aunque soy un programador experimentado, soy novato en PowerShell y sus múltiples idiosincrasias siempre me han confundido ...
¿Cuál es la forma correcta de escribir este código PS en un archivo Batch? Lo agradeceré si también se incluye una explicación simple de la causa del problema ...
Iría por la opción
-EncodedCommand
aquí.
Simplemente Base64 codifica todo el script de PowerShell y luego pasa la cadena de
Base64
como argumento a
powershell.exe
:
(suponiendo que el script esté aquí:
C:/Path/To/Script.ps1
)
PS C:/> $ScriptText = Get-Content C:/Path/To/Script.ps1 -Raw
PS C:/> $ScriptBytes = [System.Text.Encoding]::Unicode.GetBytes($ScriptText)
PS C:/> $EncCommand = [System.Convert]::ToBase64String($ScriptBytes)
$EncCommand
ahora contiene el comando codificado Base64, listo para usar dentro de
cmd.exe
(o su archivo por lotes):
C:/>powershell -EncodedCommand JABXAGkAbgBkAG8AdwBGAHUAbgBjAHQAaQBvAG4ALAAkAFIAZQBjAHQAYQBuAGcAbABlAFMAdAByAHUAYwB0ACAAPQAgAEEAZABkAC0AVAB5A
HAAZQAgAC0ATQBlAG0AYgBlAHIARABlAGYAaQBuAGkAdABpAG8AbgAgAEAAJwANAAoAWwBEAGwAbABJAG0AcABvAHIAdAAoACIAdQBzAGUAcgAzADIALgBkAGwAbAAiACwAIABTAGUAd
ABMAGEAcwB0AEUAcgByAG8AcgAgAD0AIAB0AHIAdQBlACkAXQANAAoAWwByAGUAdAB1AHIAbgA6ACAATQBhAHIAcwBoAGEAbABBAHMAKABVAG4AbQBhAG4AYQBnAGUAZABUAHkAcABlA
C4AQgBvAG8AbAApAF0ADQAKAHAAdQBiAGwAaQBjACAAcwB0AGEAdABpAGMAIABlAHgAdABlAHIAbgAgAGIAbwBvAGwAIABHAGUAdABXAGkAbgBkAG8AdwBSAGUAYwB0ACgASQBuAHQAU
AB0AHIAIABoAFcAbgBkACwAIAByAGUAZgAgAFIARQBDAFQAIABsAHAAUgBlAGMAdAApADsADQAKAFsAUwB0AHIAdQBjAHQATABhAHkAbwB1AHQAKABMAGEAeQBvAHUAdABLAGkAbgBkA
C4AUwBlAHEAdQBlAG4AdABpAGEAbAApAF0ADQAKAHAAdQBiAGwAaQBjACAAcwB0AHIAdQBjAHQAIABSAEUAQwBUAA0ACgB7AA0ACgAgACAAIAAgAHAAdQBiAGwAaQBjACAAaQBuAHQAI
ABMAGUAZgB0ADsADQAKACAAIAAgACAAcAB1AGIAbABpAGMAIABpAG4AdAAgAFQAbwBwADsADQAKACAAIAAgACAAcAB1AGIAbABpAGMAIABpAG4AdAAgAFIAaQBnAGgAdAA7AA0ACgAgA
CAAIAAgAHAAdQBiAGwAaQBjACAAaQBuAHQAIABCAG8AdAB0AG8AbQA7AA0ACgB9AA0ACgAnAEAAIAAtAE4AYQBtAGUAIAAiAHQAeQBwAGUAJAAoAFsAZwB1AGkAZABdADoAOgBOAGUAd
wBHAHUAaQBkACgAKQAgAC0AcgBlAHAAbABhAGMAZQAgACcALQAnACkAIgAgAC0AUABhAHMAcwBUAGgAcgB1AA0ACgANAAoAJABNAHkAVwBpAG4AZABvAHcASABhAG4AZABsAGUAIAA9A
CAAKABHAGUAdAAtAFAAcgBvAGMAZQBzAHMAIAAtAEkAZAAgACgARwBlAHQALQBXAG0AaQBPAGIAagBlAGMAdAAgAFcAaQBuADMAMgBfAFAAcgBvAGMAZQBzAHMAIAAtAEYAaQBsAHQAZ
QByACAAIgBQAHIAbwBjAGUAcwBzAEkAZAA9ACQAUABJAEQAIgApAC4AUABhAHIAZQBuAHQAUAByAG8AYwBlAHMAcwBJAGQAKQAuAE0AYQBpAG4AVwBpAG4AZABvAHcASABhAG4AZABsA
GUADQAKAA0ACgAkAFcAaQBuAGQAbwB3AFIAZQBjAHQAIAA9ACAATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAJABSAGUAYwB0AGEAbgBnAGwAZQBTAHQAc
gB1AGMAdAAuAEYAdQBsAGwATgBhAG0AZQANAAoAJABuAHUAbABsACAAPQAgACQAVwBpAG4AZABvAHcARgB1AG4AYwB0AGkAbwBuADoAOgBHAGUAdABXAGkAbgBkAG8AdwBSAGUAYwB0A
CgAJABNAHkAVwBpAG4AZABvAHcASABhAG4AZABsAGUALABbAHIAZQBmAF0AJABXAGkAbgBkAG8AdwBSAGUAYwB0ACkADQAKAA0ACgBXAHIAaQB0AGUALQBIAG8AcwB0ACAAJABXAGkAb
gBkAG8AdwBSAGUAYwB0AC4ATABlAGYAdAAgACQAVwBpAG4AZABvAHcAUgBlAGMAdAAuAFQAbwBwACAAJABXAGkAbgBkAG8AdwBSAGUAYwB0AC4AUgBpAGcAaAB0ACAAJABXAGkAbgBkA
G8AdwBSAGUAYwB0AC4AQgBvAHQAdABvAG0A
100 -2 1257 748
Los literales de comillas dobles se deben escapar como
/"
@echo off
PowerShell^
$WindowFunction,$RectangleStruct = Add-Type -MemberDefinition ''^
[DllImport(/"user32.dll/", SetLastError = true)]^
[return: MarshalAs(UnmanagedType.Bool)]^
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);^
[StructLayout(LayoutKind.Sequential)]^
public struct RECT^
{^
public int Left;^
public int Top;^
public int Right;^
public int Bottom;^
}^
'' -Name /"type$([guid]::NewGuid() -replace ''-'')/" -PassThru;^
$MyWindowHandle = (Get-Process -Id (^
Get-WmiObject Win32_Process -Filter /"ProcessId=$PID/"^
).ParentProcessId).MainWindowHandle;^
$WindowRect = New-Object -TypeName $RectangleStruct.FullName;^
$null = $WindowFunction::GetWindowRect($MyWindowHandle,[ref]$WindowRect);^
Write-Host $WindowRect.Left $WindowRect.Top $WindowRect.Right $WindowRect.Bottom