windows powershell batch-file cmd

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