Nhúng VBScript trong PowerShell Script - Một tệp
Gần đây tôi đã học được rất nhiều điều rắc rối với các tập lệnh kết hợp batch + VBScript và mặc dù nó rất hiệu quả và học tập, đã đến lúc tìm hiểu PowerShell kỹ lưỡng hơn. Tuy nhiên, phần yêu thích của tôi trong giải pháp Batch / VBScript là tôi có thể tạo một script.cmdtệp duy nhất để phân phối.
Có loại giải pháp nào với PowerShell / VBScript không? Tốt nhất, tôi nghĩ tôi thích một .ps1tập lệnh có VBScript được nhúng, nhưng muốn biết các tùy chọn của tôi.
Dường như có một số nhầm lẫn liên quan đến mục tiêu.
- Một tệp duy nhất (Đây là phần quan trọng nhất)
- Tiện ích mở rộng
.ps1hoặc.vbs - Cả hai
POWERSHELLvàVBScriptbên trong một tệp duy nhất - Tặng kem:
- Không ghi vào tệp bên ngoài
- Mở đầu mỗi dòng
- Phải thoát các ký tự đặc biệt trong mã
- Mã hóa toàn bộ các phần của tập lệnh (các hoạt động chuyên sâu của CPU)
Đây là một ví dụ rõ ràng:
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>
Một cái gì đó như thế này ->
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>
Trả lời
Tạo tập lệnh VBS như bình thường. Lưu ở một số vị trí và sau đó chuyển đổi nó thành Base64. Mã hóa byte được sử dụng để điều này cũng sẽ hoạt động trên các tệp nhị phân và khắc phục các vấn đề mã hóa ký tự. Như vậy,
$Content = Get-Content -Path C:\temp\myScript.vbs -Encoding Byte $Base64 = [System.Convert]::ToBase64String($Content) $Base64 | Out-File c:\temp\myScript.b64
Sau đó, trong tập lệnh Powershell của bạn, hãy bao gồm phiên bản mã hóa của tập lệnh VBS. Chuyển đổi Base64 trở lại thành chuỗi và ghi nó vào một tệp. Cuối cùng, hãy gọi cscriptđể chạy .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
Một tùy chọn khác là nhúng VBScript trong một chuỗi ở đây như vậy,
# 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
Có lẽ, ý bạn là tạo một .ps1tệp script và chạy nó từ vbscript?
Nếu vậy, đây là một ví dụ có tên là Compress_Archive_by_Extension.vbs
Ghi chú: Compress-Archive chỉ khả dụng với 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,0,True)
If fs.FileExists(PSFile) Then fs.DeleteFile(PSFile)
End Sub
'---------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'---------------------------------------------------------------------
Ví dụ thứ hai: Để tải xuống một hình ảnh từ trang web:Download_File.vbs
Option Explicit
Dim URL,Ws,ByPassPSFile,PSFile,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,0,True)
'----------------------------------------------------------------------------------------
Sub WriteMyPSFile(strText)
Dim fs,ts,PSFile
Const ForWriting = 2
PSFile = Left(Wscript.ScriptFullName, InstrRev(Wscript.ScriptFullName, ".")) & "ps1"
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(PSFile,ForWriting,True)
ts.WriteLine strText
ts.Close
End Sub
'----------------------------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'----------------------------------------------------------------------------------------
CHỈNH SỬA: 21/08/2020 @ 20:45
Đây là "giả kết hợp" vì nó sử dụng tệp tạm thời để được thực thi: lấy cảm hứng từ câu trả lời @vonPryz.
Bạn có thể lưu nó dưới dạng Test.ps1và thực thi từ 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
Một ví dụ đơn giản khác:
$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 !'
Đây là câu trả lời cuối cùng của tôi, tôi chưa thử nghiệm với bất kỳ thứ gì siêu phức tạp, vì vậy không chắc nó sẽ xử lý những thứ như ký tự đặc biệt như thế nào ...
#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
Bạn có thể nhúng mã VB.NET vào mã powershell với TypeDefinition:
$code = @" Imports System Namespace MyNameSpace Public Class Responder Public Shared Sub StaticRespond() Console.WriteLine("Static Response") End Sub Public Sub Respond() Console.WriteLine("Instance Respond") End Sub End Class End Namespace "@ # Check the type has not been previously added within the session, otherwise an exception is raised if (-not ([System.Management.Automation.PSTypeName]'MyNameSpace.Responder').Type) { Add-Type -TypeDefinition $code -Language VisualBasic;
}
[MyNameSpace.Responder]::StaticRespond();
$instance = New-Object MyNameSpace.Responder; $instance.Respond();
Không chính xác vbscript nhưng là một giải pháp tốt.