We recently upgrad开发者_运维技巧ed from Delphi 2006 to Delphi 2007, and the project files changed from .bdsproj
to .dproj
.
My research so far indicates that in order to create the .dproj
, an existing project needs to be opened in the D2007 IDE. We have over 400 .bdsproj
files so doing this manually is not really practical.
The process I came up with was to open all the projects from the command line using:
find . -name *.bdsproj -exec bds.exe -pDelphi -ns -m "{}" ";"
This isn't ideal because it is quite slow (wait for BDS to load, wait for compile to happen, wait while BDS closes, ...).
Is there an efficient way to convert multiple .bdsproj
to .dproj
?
Note: The 'find' in the above command line is a UNIX-like find (e.g. MKS or GNU) which searches for files, not the Windows find which searches for text within files.
You can open several projects at once. Even using drag and drop.
- Select 40 projects
- Drag them to the IDE
- Click yes 40 times
- Save all
- close all
- Repeat until finished.
Here is a fancier version of the find
solution using PowerShell. It searches for bdsproj
files under a specified directory and produces a bdsgroup
containing all of the projects.
After the script is run, open the bdsgroup
with D2007 to convert the projects to dproj
. D2007 also produces a groupproj
, which seems to be the D2007 equivalent of bdsgroup
.
Hints:
- Run the script with
-help
to see instructions. - Start D2007 before opening the
bdsgroup
, it seems to process the projects quicker. - You don't need to save the projects, opening them is enough to create the
dproj
.
Thanks to:
- Ulrich Gerhardt for suggesting the bdsgroup approach.
- dangph for help with the PowerShell script.
Here's the script. It works for me :o)
Param(
$path = ".",
$exclude = "",
[switch]$help
)
Set-PSDebug -Strict
$ErrorActionPreference = 'Stop'
# Ensure path is fully qualified and ends with a path delimiter
$path = Join-Path (Resolve-Path $path) ""
# Output file full name ($path\scriptname.bdsproj)
$outfile = Join-Path $path ([IO.Path]::ChangeExtension($MyInvocation.MyCommand.Name, "bdsgroup"))
# Bdsgroup template
$groupXml = [xml]@"
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
<PersonalityInfo>
<Option>
<Option Name="Personality">Default.Personality</Option>
<Option Name="ProjectType"></Option>
<Option Name="Version">1.0</Option>
<Option Name="GUID">{$([guid]::NewGuid().ToString())}</Option>
</Option>
</PersonalityInfo>
<Default.Personality>
<Projects>
<Projects Name="Targets"></Projects>
</Projects>
<Dependencies/>
</Default.Personality>
</BorlandProject>
"@
### Functions ###
function ShowUsage()
{
$myName = Split-Path -Leaf $MyInvocation.ScriptName
Write-Host "Usage:"
Write-Host "`t$myName [-path <Path>] [-exclude <Exclude>] [-help]"
Write-Host
Write-Host "`t-path <Path>"
Write-Host "`t`tSpecifies the directory to begin searching for *.bdsproj."
Write-Host "`t`tPath:" $path
Write-Host
Write-Host "`t-exclude <Exclude>"
Write-Host "`t`tSpecifies a directory to exclude from the search."
Write-Host "`t`tExclude:" $exclude
Write-Host
Write-Host "`t-help"
Write-Host "`t`tDisplays this message."
Write-Host
Write-Host "Output will be written to:"
Write-Host "`t" $outfile
Write-Host
Write-Host "Limitations:"
Write-Host "`tDoes not support multiple directories for Path or Exclude."
}
# Get the target name.
# e.g. "D:\dev\src\foo.bdsproj" returns "foo.exe"
function GetTarget($bdsproj)
{
$mainSource = GetMainSource($bdsproj)
$ext = GetTargetExt($mainSource)
Split-Path -Leaf ([IO.Path]::ChangeExtension($mainSource, $ext))
}
# Get the relative project path.
# e.g. If path is "D:\dev" then "D:\dev\src\foo.bdsproj" returns "src\foo.bdsproj"
function GetProject($bdsproj)
{
$prefixLen = $path.Length
$suffixLen = $bdsproj.Length - $prefixLen
$bdsproj.Substring($prefixLen, $suffixLen)
}
# Get the fully qualified MainSource (dpr/dpk) path.
# e.g. "D:\dev\src\foo.bdsproj" returns "D:\dev\src\foo.dpr"
function GetMainSource($bdsproj)
{
$projXml = [xml](Get-Content $bdsproj)
$mainSource = $projXml.BorlandProject."Delphi.Personality".Source.Source |
Where-Object { $_.Name -eq "MainSource" }
$result = Join-Path (Split-Path -Path $bdsproj) $mainSource.InnerText
if (-not (Test-Path $result))
{
throw "No MainSource (dpr/dpk) found for $bdsproj"
}
$result
}
# Get the target extension depending on the source type.
function GetTargetExt($mainSource)
{
$targets = @{"package"="pkg"; "library"="dll"; "program"="exe"}
$targetType = GetTargetType($mainSource)
$targets[$targetType]
}
# Read the target type out of the dpr.
function GetTargetType($mainSource)
{
$name = [IO.Path]::GetFileNameWithoutExtension($mainSource)
$pattern = "^\s*(package|library|program)\s+$name;$"
$matches = (Select-String -Path $mainSource -Pattern $pattern)
if ($matches -eq $null)
{
throw "Unknown target type (pkg/dll/exe) for $mainSource"
}
$matches.Matches[0].Groups[1].Value
}
# Add a project entry to groupXml.
# e.g. <Projects Name="foo.exe">src\foo.bdsproj</Projects>
function AddProject($target, $project)
{
$node = $groupXml.CreateElement("Projects")
$node.SetAttribute("Name", $target)
$node.InnerText = $project
$groupXml.BorlandProject."Default.Personality".Projects.AppendChild($node) | Out-Null
$targets = $groupXml.BorlandProject."Default.Personality".Projects.Projects |
Where-Object { $_.Name -eq "Targets" }
$targets.InnerText = $targets.InnerText + " " + $target
}
### Main ###
if ($help)
{
ShowUsage
}
else
{
Get-ChildItem -Path $path -Include "*.bdsproj" -Recurse |
Where-Object { $exclude -eq "" -or $_.FullName -notmatch $exclude } |
ForEach-Object { AddProject (GetTarget $_.FullName) (GetProject $_.FullName) }
$groupXml.OuterXml | Out-File -Encoding "UTF8" $outfile
}
Maybe you could use a command line similar to your find
(and maybe a little Delphi programm) to create a *.bdsgroup file with all projects and open that in D2007.
精彩评论