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

#get-Item * >> 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.