3
votes

Incorporer VBScript dans PowerShell Script - Un fichier

J'ai récemment appris beaucoup de choses à jouer avec les scripts hybrides batch + VBScript et même si c'était un excellent apprentissage et que cela fonctionnait, il est temps d'apprendre plus en profondeur PowerShell. Mais ma partie préférée de la solution Batch / VBScript est que je peux créer un seul fichier script.cmd à distribuer.

Existe-t-il une sorte de solution avec PowerShell / VBScript? Idéalement, je pense que je préférerais un script .ps1 avec VBScript intégré, mais je voudrais connaître mes options.

Il semble y avoir une certaine confusion concernant l'objectif.

  • Un seul fichier (c'est la partie la plus importante)
  • Extension soit .ps1 ou .vbs
  • POWERSHELL et VBScript dans un seul fichier
  • Prime:
    • Pas d'écriture dans un fichier externe
    • Préfacer chaque ligne
    • Devoir échapper des caractères spéciaux dans le code
    • Encodage de sections entières de script (opérations gourmandes en ressources processeur)

Voici un exemple théorique:

script.{ps1/vbs} :

<!-- : 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>

Quelque chose comme ça ->

https://stackoverflow.com/a/9074483/5079799

<!-- : 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>


2 commentaires

Pourquoi tho? Je ne peux pas penser à quoi que ce soit que vous puissiez faire dans VBScript que vous ne pouvez pas faire dans Powershell.


J'apprends cela en cherchant davantage à convertir certains de mes scripts. Une première pensée pourrait être de migrer par programmation des sections de mon code tout en utilisant simultanément l'ancien code VB. @ Nick.McDermaid


4 Réponses :


2
votes

Créez le script VBS comme d'habitude. Enregistrez dans un endroit et convertissez-le en Base64. Le codage d'octets est utilisé pour que cela fonctionne également sur les fichiers binaires et surmonte les problèmes de codage de caractères. Ainsi,

# 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 

Ensuite, dans votre script Powershell, incluez la version codée du script VBS. Reconvertissez Base64 en chaîne et écrivez-la dans un fichier. Enfin, appelez cscript pour exécuter le .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 

Une autre option est d'incorporer le VBScript dans une chaîne ici comme ceci,

$Content = Get-Content -Path C:\temp\myScript.vbs -Encoding Byte
$Base64 = [System.Convert]::ToBase64String($Content)
$Base64 | Out-File c:\temp\myScript.b64


1 commentaires

@FreeSoftwareServers Oups, vous avez mal lu la question. Maintenant, il s'agit de PS1 / VBS.



1
votes

Peut-être voulez-vous dire créer un fichier de script .ps1 et l'exécuter à partir de vbscript?

Si tel est le cas, voici un exemple nommé Compress_Archive_by_Extension.vbs

Remarque: Compress-Archive n'est disponible qu'avec PS v4


$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 !'

Deuxième exemple: pour télécharger une image depuis le site: Download_File.vbs

$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

EDIT: 21/08/2020 à 20:45

Voici un "pseudo-hybride" car il utilise un fichier temporaire à exécuter: inspiré de la réponse @vonPryz.

Vous pouvez l'enregistrer sous Test.ps1 et l'exécuter à partir de PowerShell ISE


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
'----------------------------------------------------------------------------------------

Un autre exemple simple:

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
'---------------------------------------------------------------------


4 commentaires

Je ne suis pas sûr de suivre cela, mais j'ai mis à jour ma question pour être plus clair sur l'objectif.


Cela semble prometteur, mais il se passe beaucoup de choses, pouvez-vous simplement utiliser une MsgBox VBS et un ECHO dans PowerShell en disant simplement Hello {VBS/PowerShell}


@FreeSoftwareServers Le dernier code avec seulement MsgBox ne fonctionne pas de votre côté ???


Fonctionne très bien, j'ai adapté / formaté le changement à cscript ou le vôtre a été exécuté simultanément. Honnêtement, je ne sais pas quelle réponse choisir ...



0
votes

Voici ma réponse finale, je n'ai pas testé avec quoi que ce soit de super compliqué, donc je ne sais pas comment cela gérerait des choses comme les caractères spéciaux ...

#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


0 commentaires

0
votes

Vous pouvez intégrer du code VB.NET dans du code PowerShell avec 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();

Pas exactement vbscript mais c'est une bonne solution.


0 commentaires