Generate and run PowerShell scripts dynamically


In my prior post Use new XML Features of VB to generate dynamic scripts and text files , we generated a simple batch file. It’s difficult to modify the registry or manipulate a COM object


 


PowerShell scripts allow you to manipulate files, registry and COM objects, using a uniform object manipulation metaphor. For example, you can use CD and DIR at a command prompt to navigate the file system, the registry and certificate store too.


 


Here’s a simple sample navigating the registry of Fox: (user typed text in this color)


 


Windows PowerShell


Copyright (C) 2006 Microsoft Corporation. All rights reserved.


 


PS C:\Documents and Settings\calvinh> cd hkcu:


PS HKCU:\> cd Software


PS HKCU:\Software> cd HKCU:\Software\Microsoft\VisualFoxPro


PS HKCU:\Software\Microsoft\VisualFoxPro> dir


 


 


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro


 


SKC  VC Name                           Property


  — —-                           ——–


  5   0 9.0                            {}


 


 


PS HKCU:\Software\Microsoft\VisualFoxPro> cd 9.0


PS HKCU:\Software\Microsoft\VisualFoxPro\9.0> dir


 


 


   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\9.0


 


SKC  VC Name                           Property


  — —-                           ——–


  0   1 ChooseColor                    {(default)}


  0   8 Coverage                       {FrmzoomHeight, FrmzoomTop, FrmzoomWidth, FrmzoomLeft…}


  0   7 Desktop                        {Zoomed, Row, Column, Height…}


  0   0 Fonts                          {}


  4 192 Options                        {LastProject, TALK, StatusBar, NOTIFY…}


 


 


PS HKCU:\Software\Microsoft\VisualFoxPro\9.0>


 


 


 


 


 


This PowerShell script sample modifies the setting of SET SAFETY by directly manipulating the registry, then forcing VFP to reread the registry settings using SYS(3056)


 


ERASE d:\t.txt


*http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx


*Set-ExecutionPolicy remotesigned


SET SAFETY OFF


?”Safety before”,SET(“Safety”)


TEXT TO myvar


#This is a sample powershell script


#get-process > d:\t.txt


#get-psdrive > d:\t.txt


#CD HKCU:\Software\Microsoft\VisualFoxPro\9.0


#getItem * >> d:\t.txt


#can specify path to registry


#get setting of all reg keys starting with “s”:


#get-ItemProperty –path registry::HKCU\Software\Microsoft\VisualFoxPro\9.0\Options s* >> d:\t.txt


#get-ItemProperty –path registry::HKCU\Software\Microsoft\VisualFoxPro\9.0\Options safety >> d:\t.txt


set-ItemProperty –path registry::HKCU\Software\Microsoft\VisualFoxPro\9.0\Options safety ON >> d:\t.txt


 


ENDTEXT


STRTOFILE(myvar,”d:\Myscript.ps1″)


! powershell d:\Myscript


?STRCONV(SUBSTR(FILETOSTR(“d:\t.txt”),3),6)     && convert from Unicode, remove ByteOrderMark


SYS(3056)   && Force VFP to reread registry


 


?”Safety After: “,SET(“safety”)


SET SAFETY OFF    && restore value


 


 


You can even create a VFP COM Object from within a PowerShell script and invoke its methods: (using my favorite VFP COM Object “t1.c1”)


 


Here’s a PowerShell script sample that creates an instance of Excel, and passes it to the VFP COM object for further manipulation: The hardest part of this code was trying to figure out how to close Excel without saving changes!


 


PowerShell variables start with “$”, comments start with “#”


 


SET SAFETY OFF 


sOutputFile=”d:\t.txt”


ERASE (sOutputFile)


ERASE (sOutputFile)


TEXT TO myvar  TEXTMERGE


#create Excel


$oExcel = New-Object -ComObject Excel.Application


#create VFP COM Object


$oVFP = New-Object -ComObject t1.c1


#Pass Excel to VFP object


$oVFP.MyDoCmd(“p2.Visible=1”,$oExcel,0,0,0)


#Get the name of the object


$oVFP.MyEval(“p2.name”,$oExcel,0,0,0) >> <<sOutputFile>>


#Add a workbook


$oVFP.MyDoCmd(“p2.Workbooks.Add”,$oExcel,0,0,0)


$pv=”PowerShell variable”


#Change the 1st cell’s value to a combination of VFP and Powershell vars


$oVFP.MyDoCmd(“p2.Cells(1,1).value=’Hi from VFP ‘+p3”,$oExcel,$pv,0,0)


$oVFP.MyDoCmd(“DECLARE integer MessageBoxA IN WIN32API integer,string,string,integer”,0,0,0,0)


$oVFP.MyEval(“MessageBoxA(0,’Hi From VFP inside PowerShell’,”,0)”,0,0,0,0)


#Close Excel workbook without saving!


$oVFP.MyDoCmd(“p2.ActiveWorkbook.Close(.f.)”,$oExcel,0,0,0)


$oVFP.MyDoCmd(“p2.Visible=0”,$oExcel,0,0,0)


$oVFP.MyDoCmd(“p2.Quit”,$oExcel,0,0,0)


 


ENDTEXT


STRTOFILE(myvar,”d:\Myscript.ps1″)


! powershell d:\Myscript


IF FILE(sOutputFile)


      ?STRCONV(SUBSTR(FILETOSTR(sOutputFile),3),6)    && convert from Unicode, remove ByteOrderMark


ENDIF


 


 


 


You can do this from VB using the new XML features (Use new XML Features of VB to generate dynamic scripts and text files )


 


Module Module1


 


    Sub Main()


        Dim sOutputFile = “d:\t.txt”


        Dim sScriptFile = “d:\t.ps1”


        If My.Computer.FileSystem.FileExists(sOutputFile) Then


            My.Computer.FileSystem.DeleteFile(sOutputFile)


        End If


        Dim PowerShellScriptXML = <myxml>


#create Excel


$oExcel = New-Object -ComObject Excel.Application


#create VFP COM Object


$oVFP = New-Object -ComObject t1.c1


#Pass Excel to VFP object


$oVFP.MyDoCmd(“p2.Visible=1”,$oExcel,0,0,0)


#Get the name of the object


$oVFP.MyEval(“p2.name”,$oExcel,0,0,0) >> <%= sOutputFile %>


#Add a workbook


$oVFP.MyDoCmd(“p2.Workbooks.Add”,$oExcel,0,0,0)


$pv=”PowerShell variable”


#Change the 1st cell’s value to a combination of VFP and Powershell vars


$oVFP.MyDoCmd(“p2.Cells(1,1).value=’Hi from VFP ‘+p3”,$oExcel,$pv,0,0)


$oVFP.MyDoCmd(“DECLARE integer MessageBoxA IN WIN32API integer,string,string,integer”,0,0,0,0)


$oVFP.MyEval(“MessageBoxA(0,’Hi From VFP inside PowerShell’,”,0)”,0,0,0,0)


#Close Excel workbook without saving!


$oVFP.MyDoCmd(“p2.ActiveWorkbook.Close(.f.)”,$oExcel,0,0,0)


$oVFP.MyDoCmd(“p2.Visible=0”,$oExcel,0,0,0)


$oVFP.MyDoCmd(“p2.Quit”,$oExcel,0,0,0)


                 </myxml>


        Console.WriteLine(PowerShellScriptXML.Value)


        My.Computer.FileSystem.WriteAllText(sScriptFile, PowerShellScriptXML.Value, False, Text.Encoding.ASCII)


        Dim proc = System.Diagnostics.Process.Start(“PowerShell”, sScriptFile)


        proc.WaitForExit()


        Dim ss = My.Computer.FileSystem.ReadAllText(sOutputFile)


        MsgBox(“Proc Done “ + ss)


    End Sub


 


End Module


 


 


 


End of code


 


See also


How to create the general purpose “T1.c1” server: Blogs get 300 hits per hour: Visual FoxPro can count.


 

Comments (3)

  1. One of the things I most dearly missed from FoxPro when I moved to VB.NET was the ability to easily dump

  2. Mike McCann says:

    Just used the PowerShell ISE for the first time.  No Intellisense at the command line?? Not even MDI.  Why couldn’t they "walk down the hall" to see Calvin before they released this antique.  Obviously no peer review at that shop.