# encoding: ascii
# api: powershell
# title: Scan VB6 Code
# description: This functions work together to read the code of a Visual Basic Project into a PowerShell Object, which can be easyly scanned for patterns, returning filename, function/subroutine name und the matching line. Great tool you got unmaintained VB6 projects to understand for fixing or migrating (perhaps into PowerShell ;-))
# version: 0.1
# type: function
# license: CC0
# function: Get-VBProject
# x-poshcode-id: 970
# x-archived: 2009-03-27T18:09:47
#
# For examples look at the comments at the end of the code.
#
#requires -version 2
# some PowerShell Functions to scan VB 6 Projects for patterns
# e.g. some SQL calls
# by Bernd Kriszio http://pauerschell.blogspot.com/
function Get-VBProject ($file)
{
# this is developed for use with Visual Basic 6
# to extract the files the contain VB Code
pushd (Split-path $file)
foreach ($line in (gc $file))
{
if ($line -match "Class=\S+;\s+(\S+.cls)")
{
gi $matches[1]
}
elseif ($line -match "Form=(\S+.frm)")
{
gi $matches[1]
}
elseif ($line -match "Module=\S+;\s*(\S+.BAS)")
{
gi $matches[1]
}
}
popd
}
function Get-VBLines ($file)
{
# VB 6 uses _ at end of line as line continuation character
# we build logical VB lines, especially to get complete signatures of functions and subroutines
$oFile = gi $file
$SourceLineNumber = 0
foreach ($line in (gc $file))
{
$SourceLineNumber++
if ($continue)
{
$buffer += "`r`n" + $line
if ($line -notmatch '_$')
{
$continue = $False
$o = New-Object object
Add-Member -InputObject $o -MemberType NoteProperty -Name LineNumber -Value $LineNumber
Add-Member -InputObject $o -MemberType NoteProperty -Name VBLine -Value $buffer
Add-Member -InputObject $o -MemberType NoteProperty -Name file -Value $oFile.Name
Add-Member -InputObject $o -MemberType NoteProperty -Name filepath -Value $oFile.FullName
$o
}
}
else
{
$buffer = $line
$LineNumber = $SourceLineNumber
if ($line -match '_$')
{
$continue = $True
}
else
{
$o = New-Object object
Add-Member -InputObject $o -MemberType NoteProperty -Name LineNumber -Value $LineNumber
Add-Member -InputObject $o -MemberType NoteProperty -Name VBLine -Value $buffer
Add-Member -InputObject $o -MemberType NoteProperty -Name file -Value $oFile.Name
Add-Member -InputObject $o -MemberType NoteProperty -Name filepath -Value $oFile.FullName
$o
}
}
}
}
function Get-VB_CodeObject ()
{
param (
[Parameter(Position = 0, Mandatory=$true, ValueFromPipeline=$True)]
$file
)
PROCESS
{
$inObject = $False
$lines = @()
$comments = @()
$inDeclareations = $True
#write-Host "--- $file ----"
Get-VBLines $file | % {
if ($inObject)
{
if ($_.VBLine -match "^End $end")
{
$lines += $_.VBLine
$inObject = $False
if ($inDeclareations){
$o = New-Object object
Add-Member -InputObject $o -MemberType NoteProperty -Name LineNumber -Value 1
Add-Member -InputObject $o -MemberType NoteProperty -Name Code -Value $comments
Add-Member -InputObject $o -MemberType NoteProperty -Name Comments -Value ''
Add-Member -InputObject $o -MemberType NoteProperty -Name file -Value $_.file
Add-Member -InputObject $o -MemberType NoteProperty -Name filepath -Value $_.filepath
Add-Member -InputObject $o -MemberType NoteProperty -Name acces -Value ''
Add-Member -InputObject $o -MemberType NoteProperty -Name typ -Value ''
Add-Member -InputObject $o -MemberType NoteProperty -Name name -Value 'Declarations'
$inDeclareations = $false
$o
$comments = @()
}
$o = New-Object object
Add-Member -InputObject $o -MemberType NoteProperty -Name LineNumber -Value $LineNumber
Add-Member -InputObject $o -MemberType NoteProperty -Name Code -Value $lines
Add-Member -InputObject $o -MemberType NoteProperty -Name Comments -Value $comments
Add-Member -InputObject $o -MemberType NoteProperty -Name file -Value $_.file
Add-Member -InputObject $o -MemberType NoteProperty -Name filepath -Value $_.filepath
Add-Member -InputObject $o -MemberType NoteProperty -Name acces -Value $acces
Add-Member -InputObject $o -MemberType NoteProperty -Name typ -Value $typ
Add-Member -InputObject $o -MemberType NoteProperty -Name name -Value $name
$o
$lines = @()
}
else
{ # collect lines
$lines += $_.VBLine
}
}
else
{
if ($_.VBLine -match "^(Public|Private)?\s*Property\s+(Get|Set)\s+([^\s\(]+)")
{
$acces = $matches[1]
$typ = 'Property ' + $matches[2]
$name = $matches[3]
$end = 'Property'
$inObject = $True
#$acces + " " + $typ + " " + $name
$comments = $lines
$lines = (, $_.VBLine)
$LineNumber = $_.LineNumber
}
elseif ($_.VBLine -match "^(Public|Private)?\s*(Function|Sub)\s+([^\s\(]+)")
{
$acces = $matches[1]
$typ = $matches[2]
$name = $matches[3]
$end = $matches[2]
$inObject = $True
#$acces + " " + $typ + " " + $name
$comments = $lines
$lines = (, $_.VBLine)
$LineNumber = $_.LineNumber
}
else
{
$lines += $_.VBLine
}
}
}
}
}
filter Select-VBCode_String ($pattern)
{
$o = New-Object object
Add-Member -InputObject $o -MemberType NoteProperty -Name LineNumber -Value $_.LineNumber
Add-Member -InputObject $o -MemberType NoteProperty -Name Comments -Value $_.comments
Add-Member -InputObject $o -MemberType NoteProperty -Name file -Value $_.file
Add-Member -InputObject $o -MemberType NoteProperty -Name filepath -Value $_.filepath
Add-Member -InputObject $o -MemberType NoteProperty -Name acces -Value $_.acces
Add-Member -InputObject $o -MemberType NoteProperty -Name typ -Value $_.typ
Add-Member -InputObject $o -MemberType NoteProperty -Name name -Value $_.name
$patternFound = $False
$lines = @()
foreach ($l in $_.Code)
{
if ($l -match $pattern)
{
$lines += $l
$patternFound = $True
}
}
if ( $patternFound)
{
Add-Member -InputObject $o -MemberType NoteProperty -Name Code -Value $lines
$o
}
}
<#
$myVBProject = 'myDirtyVb6Project.vbp'
$vbp = Get-VBProject $myVBProject | Get-VB_CodeObject
# Now you search your VB Project for patterns
# look for sql SELECT-Statements
$vbp | Select-VBCode_String('"select') |% { $_.code }
# or the location of Vb EXIT Statments
$vbp| Select-VBCode_String('EXIT') | fl
$vbp| select file, acces, typ, name
#>