如何解决将VBScript嵌入PowerShell脚本-一个文件
我最近了解到很多关于批处理+ VBScript混合脚本的混乱,虽然这是一门很好的学习和著作,但现在是时候更全面地学习PowerShell了。但是,我最喜欢的Batch / VBScript解决方案部分是,我可以创建一个script.cmd
文件来分发。
PowerShell / VBScript是否有任何解决方案?理想情况下,我认为我更喜欢带有嵌入式VBScript的.ps1
脚本,但对了解我的选择感兴趣。
目标似乎有些混乱。
- 一个文件(这是最重要的部分)
- 扩展
.ps1
或.vbs
-
POWERSHELL
和VBScript
都位于单个文件中 - 奖金:
- 不写入外部文件
- 在每行前面
- 必须在代码中转义特殊字符
- 对脚本的整个部分进行编码(开销过多的CPU操作)
这是一个举足轻重的例子:
script.{ps1/vbs}
:
<!-- : Begin PS1 script
$strString = "Hello PowerShell"
write-host $strString
cscript //nologo "%~f0?.wsf" //job:HELLOWORLD
exit /b
PAUSE
----- Begin wsf script --->
<package>
<job id="HELLOWORLD">
<script language="VBScript">
MsgBox "Hello World VBS"
</script>
</job>
<job id="VBS">
<script language="VBScript">
'Second Script!
</script>
</job>
</package>
类似的东西->
https://stackoverflow.com/a/9074483/5079799
<!-- : Begin batch script
@ECHO OFF
CLS
cscript //nologo "%~f0?.wsf" //job:HELLOWORLD
exit /b
PAUSE
----- Begin wsf script --->
<package>
<job id="HELLOWORLD">
<script language="VBScript">
MsgBox "Hello World"
</script>
</job>
<job id="VBS">
<script language="VBScript">
'Second Script!
</script>
</job>
</package>
解决方法
照常创建VBS脚本。保存在某个位置,然后将其转换为Base64。使用字节编码,这样它也可以在二进制文件上使用,并克服了字符编码问题。像这样
$Content = Get-Content -Path C:\temp\myScript.vbs -Encoding Byte
$Base64 = [System.Convert]::ToBase64String($Content)
$Base64 | Out-File c:\temp\myScript.b64
然后,在Powershell脚本中包含VBS脚本的编码版本。将Base64转换回字符串并将其写入文件。最后,调用cscript
以运行.vbs
。
$Base64 = "ZgB1AG4AYwB0AGkAbwBuACAAR..."
$Content = [System.Convert]::FromBase64String($Base64)
Set-Content -Path $env:temp\myScript.vbs -Value $Content -Encoding Byte
& cscript /nologo $env:temp\myScript.vbs
另一种选择是将VBScript嵌入到此处的字符串中,
# Paste the VBS in a here string
$Content = @'
dim foo
...
'@
Set-Content -Path $env:temp\myScript.vbs -Value $Content
& cscript /nologo $env:temp\myScript.vbs
,
也许,您是说要创建一个.ps1
脚本文件并从vbscript运行它?
如果是这样,下面是一个名为Compress_Archive_by_Extension.vbs
的示例 备注: Compress-Archive
仅在PS v4中可用
Option Explicit
Dim Title,ArrExt,Ext
Title = "Compress Archive With Powreshell And Vbscript by Hackoo 2020"
REM We define an array of extensions for archiving !
ArrExt = Array("vbs","vbe","cmd","bat","ps1","js","jse","lnk")
REM Looping thru extensions defined from our array in order to zip and archive them,REM so you can add or remove what you want as extension in the array above !
For each Ext in ArrExt
Call Compress_Archive("%Temp%\*."& Ext,"Temp_Archive_"& Ext)
Call Compress_Archive("%AppData%\*."& Ext,"AppData_Archive_"& Ext)
Call Compress_Archive("%LocalAppData%\*."& Ext,"LocalAppData_Archive_"& Ext)
Call Compress_Archive("%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup\*."& Ext,"ProgramData_Archive_"& Ext)
Call Compress_Archive("%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\*."& Ext,"UserProfile_Archive_"& Ext)
Next
MsgBox "Archive Script is completed !",vbInformation,Title
'---------------------------------------------------------------------
REM https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-5.1&redirectedfrom=MSDN
Sub Compress_Archive(Source,Destination)
Const ForWriting = 2
Dim fs,Ws,ts,Ret,PSFile,ByPassPSFile
Set fs = CreateObject("Scripting.FileSystemObject")
Set Ws = WScript.CreateObject("WScript.Shell")
Source = Ws.ExpandEnvironmentStrings(Source)
Destination = Ws.ExpandEnvironmentStrings(Destination)
PSFile = Ws.ExpandEnvironmentStrings("%Temp%") & fs.GetTempName & ".ps1"
ByPassPSFile = "PowerShell -ExecutionPolicy bypass -noprofile -file "
Set ts = fs.OpenTextFile(PSFile,ForWriting,True)
ts.WriteLine "Compress-Archive -Path " & DblQuote(Source) &_
" -Update -CompressionLevel Optimal -DestinationPath "& DblQuote(Destination)
ts.Close
Ret = Ws.run(ByPassPSFile & PSFile,True)
If fs.FileExists(PSFile) Then fs.DeleteFile(PSFile)
End Sub
'---------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'---------------------------------------------------------------------
第二个示例: 要从站点下载图像:Download_File.vbs
Option Explicit
Dim URL,ByPassPSFile,MyCmd,Result
URL = "https://cdn2.unrealengine.com/Fortnite%2FBoogieDown_GIF-1f2be97208316867da7d3cf5217c2486da3c2fe6.gif"
Set Ws = CreateObject("wscript.Shell")
PSFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName,".")) & "ps1"
ByPassPSFile = "cmd /C PowerShell.exe -ExecutionPolicy bypass -noprofile -file "
MyCmd = "$source = " & DblQuote(URL) & VbCrlF
MyCmd = MyCmd & "$Filename = [System.IO.Path]::GetFileName($source)" & VbCrlF
MyCmd = MyCmd & "$dest = " & DblQuote("$env:temp\$Filename") & VbCrlF
MyCmd = MyCmd & "$wc = New-Object System.Net.WebClient" & VbCrlF
MyCmd = MyCmd & "$wc.DownloadFile($source,$dest)" & VbCrlF
MyCmd = MyCmd & "Start-Process $dest"
Call WriteMyPSFile(MyCmd)
Result = Ws.run(ByPassPSFile & PSFile,True)
'----------------------------------------------------------------------------------------
Sub WriteMyPSFile(strText)
Dim fs,PSFile
Const ForWriting = 2
PSFile = Left(Wscript.ScriptFullName,".")) & "ps1"
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(PSFile,True)
ts.WriteLine strText
ts.Close
End Sub
'----------------------------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'----------------------------------------------------------------------------------------
编辑:21/08/2020 @ 20:45
这是“伪混合”文件,因为它使用了要执行的临时文件: 来自@vonPryz答案的启发。
您可以将其另存为Test.ps1
并从PowerShell ISE执行
$VBS_Content = @'
Dim http,WAN_IP
Set http = CreateObject( "MSXML2.ServerXmlHttp" )
http.Open "GET","http://icanhazip.com",False
http.Send
WAN_IP = http.responseText
wscript.echo "WAN_IP : " & WAN_IP
'@
Set-Content -Path $env:temp\myScript.vbs -Value $VBS_Content
& wscript.exe $env:temp\myScript.vbs
$url = "https://externals.lesechos.fr/medias/2019/04/26/2262811_pourquoi-salto-le-futur-netflix-francais-devra-seuropeaniser-195514-1.jpg"
#https://stackoverflow.com/questions/35813186/extract-the-filename-from-a-path
$output = $env:temp + "\" + $url.Split("/")[-1]
$start_time = Get-Date
Try {$wb = (New-Object System.Net.WebClient).DownloadFile($url,$output)}
Catch {
Write-Host "Error from $url ! " -ForegroundColor Red -BackgroundColor Yellow
Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor Yellow
}
Write-Output "Running Script Time taken is : $((Get-Date).Subtract($start_time).Seconds) second(s)"
Start-process $output
另一个简单的例子:
$VBS_Content = @'
MsgBox "This a simple MsgBox from Vbscript"
'@
$TmpVBS="$env:temp\myScript.vbs"
SC $TmpVBS $VBS_Content
wscript.exe $TmpVBS
Echo 'Hello World from Powershell !'
,
这是我的最终答案,我还没有对任何超级复杂的东西进行过测试,所以不确定如何处理特殊字符……
#https://stackoverflow.com/questions/63514534/embed-vbscript-in-powershell-script-one-file
#######################Begin VBS1#######################
###JOB_A START###
$VBS_Content_Job_A = @'
MsgBox "This a simple MsgBox from Vbscript (Job_A)"
'@
###JOB_A END###
###JOB_B START###
$VBS_Content_Job_B = @'
MsgBox "This a simple MsgBox from Vbscript (Job_B)"
'@
###JOB_B END###
#######################Begin PS1#######################
ECHO 'Hello World from Powershell !'
PAUSE
ECHO "Running VBS Now"
PAUSE
###VBS CALL START###
$VBSJob=$VBS_Content_Job_A
$TmpVBS="$env:temp\myScript.vbs"
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
SC $TmpVBS $VBSJob
cscript //nologo $TmpVBS
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
###VBS CALL END###
ECHO "Some More PowerShell"
PAUSE
ECHO "I need anoter VBS Script"
PAUSE
###VBS CALL START###
$VBSJob=$VBS_Content_Job_B
$TmpVBS="$env:temp\myScript.vbs"
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
Set-Content -Path $TmpVBS -Value $VBSJob
cscript //nologo $TmpVBS
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
###VBS CALL END###
ECHO "All Done!"
PAUSE
,
您可以使用TypeDefinition将VB.NET代码嵌入到Powershell代码中
self
不完全是vbscript,但这是一个很好的解决方案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。