P2V - Visual FoxPro 9 application server

August 8, 2019

P2V - Visual FoxPro 9 application server

Client has a legacy Visual FoxPro application running on a Windows Server 2008 R2. The application is no longer being used, but it contains valuable historical data that they want to retain. I could run Disk2vhd and be done. However, it is on a production server that has two large file shares and other services running on the server. I really don't want to copy all the things that aren't needed for the application.

I checked for ODBC connection, and there wasn't any. So, let's just copy the application folder and its dependencies to a new VM named LegacyVM.

Here is what we're looking at

New Server: LegacyVM
VM Host   : VHOST01

Create a new Windows Server 2008 R2 VM
Open an elevated PowerShell ISE
Connect to the newly created Hyper-V Server 2019, which is named HOST01

Enter-PSSession -ComputerName HOST01 -Credential domain-admin

Find the VMSwitch name that we will use for this VM


I'm getting this output
Name                    SwitchType NetAdapterInterfaceDescription
----                    ---------- ------------------------------
externalSwitch          External   Broadcom NetXtreme Gigabit Ethernet #1

So externalSwitch is what I will use.

I'm going to create a script for creating Hyper-V VM on this brand new Hyper-V Server 2019.

New-Item 'D:\Scripts' -ItemType Directory
New-Item 'D:\Scripts\LegacyApp.ps1' -ItemType file
Edit this script in PowerShell ISE
PSEdit D:\Scripts\NewVM.ps1
I would need to specify the VM to be Generation 1 since I will install Windows Server 2008 R2 on it.
# Set VM Name, Switch Name, and Installation Media Path.
$VMName = 'LegacyApp'
$Switch = 'externalSwitch'
$InstallMedia = 'D:\ISO\W2008R2.ISO'
$VMPath = 'D:\Hyper-V\'
$VHDPath = 'Virtual Hard Disks'

# Create New Virtual Machine and store all files in the same directory
New-VM -Name $VMName -MemoryStartupBytes 4GB -Generation 1 -Path "$VMPath" `
-NewVHDPath "$VMPath\$VMName\$VHDPath\$VMName.vhdx" -NewVHDSizeBytes 150GB -SwitchName $Switch

# Specify ISO to boot the VM
Add-VMDvdDrive -VMName $VMName -Path $InstallMedia

#Start the VM
Start-VM -VMName $VMName

Post Operating System Installation

I'm going to run the following PowerShell commands

#Enable Ping
Set-NetFirewallRule -DisplayName “File and Printer Sharing (Echo Request – ICMPv4-In)” -enabled True

#Get InterfaceIndex value
Get-NetAdapter -Name * | Format-Table –AutoSize

#Configure static IP - Use the InterfaceIndex value from the command above.
New-NetIPAddress –InterfaceIndex 5 –IPAddress -PrefixLength 24 -DefaultGateway

#Configure DNS - Again, use the same InterfaceIndex value as above
Set-DnsClientServerAddress -InterfaceIndex 6 -ServerAddresses ("","")

#Enable Remote PowerShell

#Rename computer and join domain
Add-Computer -Credential Admin-Username -DomainName dccb.net -NewName LegacyApp; Restart-Computer -force

After the server VM has restarted, I'm going to copy over the files from the old server to C:\LegacyApp on the new VM.

New-Item C:\LegacyApp -ItemType Directory
robocopy \\OLDSERVER\LegacyApp\ C:\LegacyApp /E /ZB /COPYALL /R:1 /log:C:\Robocopy.log
The script ran in 1 second. That is just too fast. Let's view the Robocopy log
Get-Content -Path C:\Robocopy.log
I'm seeing this
2019/10/31 10:04:02 ERROR 5 (0x00000005) Accessing Source Directory \\OLDSERVER\LegacyApp\
Access is denied.
I'm going to open another elevated PowerShell and log into OLDSERVER
Enter-PSSession OLDSERVER -Credential domain-admin
I'm getting an error message
Enter-PSSession : Connecting to remote server Loki failed with the following error message : WinRM cannot complete the
This means PowerShell remoting is not enabled on OLDSERVER.
Well, let's RDP into it then. Then open an elevated PowerShell and type in
Since I'm already on the server, let's check to see if the application folder is being shared and accessible across network. Since this is a Windows 2008 R2 box, I can't use the Get-SmbShare cmdlets. So I will use WMI
Get-WmiObject -Class Win32_Share
Well, the share is there.
I'm going to take ownership and assign permission
takeown "D:\LegacyApp" /F /R /D y
icacls "D:\LegacyApp" /grant domain-admin:F /T
I'm seeing
Successfully processed 45242 files; Failed processing 0 files
Alt + Tab and went back to my other PowerShell and run robocopy again.
robocopy \\OLDSERVER\LegacyApp\ C:\LegacyApp /E /ZB /COPYALL /R:1 /log:C:\Robocopy.log
Now I have all the files on the new VM in C:\LegacyApps
Let's RDP into LegacyVM to run the app.
I opened up the main exe in Dependencies Walker, but it's only shows 4 DLLs.
Well, looks like I will have a lot of clicking to do.
Clicking ignore about 30 times got me in.
I wrote down the full path and name of all the OCX and DLL files, substitute system32 for SysWOW64
I saved that file as DLLs.txt and copied it to C:\Temp on OLDSERVER
RDP into OLDSERVER and run an elevated PowerShell console
Get-Content -Path C:\Temp\DLLs.txt | foreach {Copy-Item -Path $_ -Destination \\LegacyApp\c$\Windows\SysWOW64}
Open up C:\Temp\DLLs.txt and do a search for C:\Windows\SysWOW64 and replace that with regsvr32
Then I rename it as DLL.bat and copy it to \\LegacyApp\c$\Windows\SysWOW64\
Then RDP into LegacyApp and right click on that bat file and run as an administrator to register all the DLLs.
That's it. I now have a virtualized instance of the application.