Introduction
Often as I'm coding, I find it necessary to access the output directory of the project I'm working on, or to copy the output file to another location. This is especially true when I'm fixing bugs and need to copy the 'fixed' binary to a test machine or test directory for access by others.
Since most of the projects I work on are convoluted, I get tired of constantly drilling down directories to find what I'm after, so I wrote two macros to help. The first, OpenOutputDir
, searches the current project (dsp) file for the output directory of the current configuration and opens it in Explorer. The second, CopyOutputFile
, does a similar search for the output file and then copies it to a user specified directory.
Using the code
To install the macro file:
- On the Tools menu, click Customize.
- Click the Add-ins and Macro Files tab. The name of the macro file should appear in the window.
- If the name of the macro file does not appear, click the Browse button to locate the file.
Tip: To avoid browsing, store macro files in the Macros subdirectory of the Visual Studio directory (Visual Studio\Common\MSDEV98\Macros). Visual C++ always searches the Macros directory first.
- Load the appropriate macro file by selecting the check box next to its name. Visual C++ adds a check mark, indicating that the file is loaded. This check mark also directs Visual C++ to automatically load the file when you start Visual C++ again.
Alternatively, you can cut and paste the code below into your own macro file.
OpenOutputDir
Sub OpenOutputDir()
Dim strProjFile, strConfigName, strOutputDir, strLine
Dim oFSO, oFile, oShell
Dim bFound, bFoundConfig
Dim nRelativeSteps, nStep
Const ForReading = 1
Const CONFIG_STR = """$(CFG)"" == "
Const OUTPUT_STR = "# PROP Output_Dir "
strProjFile = ActiveProject.FullName
strConfigName = CONFIG_STR + """" + ActiveConfiguration.Name + """"
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.OpenTextFile(strProjFile, ForReading)
bFound = FALSE
bFoundConfig = FALSE
Do While ((oFile.AtEndOfStream <> True) And (Not bFound))
strLine = oFile.ReadLine
If (Not bFoundConfig) Then
If (Instr(strLine, strConfigName) > 0) Then
bFoundConfig = TRUE
End If
Else
If (Instr(strLine, OUTPUT_STR) > 0) Then
bFound = TRUE
End If
End If
Loop
strLine = Replace(strLine, OUTPUT_STR, "")
strLine = Replace(strLine, """", "")
nRelativeSteps = 0
While (Left(strLine, 3) = "..\")
strLine = Mid(strLine, 4)
nRelativeSteps = nRelativeSteps + 1
WEnd
While (Left(strLine, 1) = ".")
strLine = Mid(strLine, 2)
WEnd
strLine = Replace(strLine, "/", "\")
If (Left(strLine, 1) <> "\") Then
strLine = "\" + strLine
End If
For nStep = 0 To nRelativeSteps
strProjFile = Left(strProjFile, InStrRev(strProjFile, "\") - 1)
Next
strOutputDir = strProjFile + strLine
If (oFSO.FolderExists(strOutputDir)) Then
Application.PrintToOutputWindow "Opening folder... " + strOutputDir
Set oShell = CreateObject("WScript.Shell")
oShell.Run("""" + strOutputDir + """")
Else
MsgBox "I couldn't find the output folder!" + vbCrlf _
+ strOutputDir, vbOKOnly, "Macro Error"
End If
End Sub
CopyOutputFile
Sub CopyOutputFile()
Dim strProjFile, strConfigName, strOutputFile, strLine, strDestination
Dim oFSO, oFile, oShell
Dim bFound, bFoundConfig
Dim nStart, nEnd
Dim nRelativeSteps, nStep, nTargType
Const ForReading = 1
Const CONFIG_STR = """$(CFG)"" == "
Const OUT_FILE_STR = "/out:"
Const OUTPUT_STR = "# PROP Output_Dir "
Const TARG_TYPE = "# TARGTYPE "
Const TARG_TYPE_EXE = "Win32 (x86) Application"
Const TARG_TYPE_DLL = "Win32 (x86) Dynamic-Link Library"
Const TARGE_TYPE_LIB = "Win32 (x86) Static Library"
Const TT_EXE = 1
Const TT_DLL = 2
Const TT_LIB = 4
strProjFile = ActiveProject.FullName
strConfigName = CONFIG_STR + """" + ActiveConfiguration.Name + """"
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.OpenTextFile(strProjFile, ForReading)
bFound = FALSE
bFoundConfig = FALSE
Do While ((oFile.AtEndOfStream <> True) And (Not bFound))
strLine = oFile.ReadLine
If (Not bFoundConfig) Then
If (Instr(strLine, strConfigName) > 0) Then
bFoundConfig = TRUE
End If
Else
If (Instr(strLine, OUT_FILE_STR) > 0) Then
bFound = TRUE
End If
End If
Loop
If (Not bFound) Then
oFile.Close
Set oFile = oFSO.OpenTextFile(strProjFile, ForReading)
bFound = FALSE
bFoundConfig = FALSE
nTargType = 0
Do While ((oFile.AtEndOfStream <> True) And (Not bFound))
strLine = oFile.ReadLine
If (InStr(strLine, TARG_TYPE) > 0) Then
If (InStr(strLine, TARG_TYPE_EXE) > 0) Then
nTargType = TT_EXE
ElseIf (InStr(strLine, TARG_TYPE_DLL) > 0) Then
nTargType = TT_DLL
ElseIf (InStr(strLine, TARG_TYPE_LIB) > 0) Then
nTargType = TT_LIB
End If
End If
If (Not bFoundConfig) Then
If (Instr(strLine, strConfigName) > 0) Then
bFoundConfig = TRUE
End If
Else
If (Instr(strLine, OUTPUT_STR) > 0) Then
bFound = TRUE
End If
End If
Loop
strLine = Replace(strLine, OUTPUT_STR, "")
strLine = Replace(strLine, """", "")
If (bFound) Then
Select Case (nTargType)
Case (TT_EXE)
strLine = strLine + "\" + ActiveProject.Name + ".exe"
Case (TT_DLL)
strLine = strLine + "\" + ActiveProject.Name + ".dll"
Case (TT_LIB)
strLine = strLine + "\" + ActiveProject.Name + ".lib"
End Select
End If
Else
nStart = InStr(strLine, OUT_FILE_STR)
nStart = InStr(nStart + 1, strLine, """")
nEnd = InStr(nStart + 1, strLine, """")
strLine = Mid(strLine, nStart + 1, nEnd - nStart - 1)
End If
nRelativeSteps = 0
While (Left(strLine, 3) = "..\")
strLine = Mid(strLine, 4)
nRelativeSteps = nRelativeSteps + 1
WEnd
While (Left(strLine, 1) = ".")
strLine = Mid(strLine, 2)
WEnd
strLine = Replace(strLine, "/", "\")
If (Left(strLine, 1) <> "\") Then
strLine = "\" + strLine
End If
For nStep = 0 To nRelativeSteps
strProjFile = Left(strProjFile, InStrRev(strProjFile, "\") - 1)
Next
strOutputFile = strProjFile + strLine
strDestination = InputBox("Copy file:" + vbCrLf + vbCrLf _
+ strOutputFile + vbCrLf + vbCrLf + "to", "Copy File")
If (strDestination = "") Then
Exit Sub
End If
If (oFSO.FolderExists(strDestination)) Then
If (Right(strDestination, 1) <> "\") Then
strDestination = strDestination + "\"
End If
Application.PrintToOutputWindow "Copying file... " + strOutputFile
Application.PrintToOutputWindow "to... " + strDestination
oFSO.CopyFile strOutputFile, strDestination, True
Else
MsgBox "I couldn't find the destination folder!" + vbCrlf _
+ vbCrlf + strDestination, vbOKOnly, "Macro Error"
End If
End Sub
To make best use of these macros, you'll probably want to assign them to a toolbar button, or shortcut key sequence. This can be done as follows:
To assign a macro to a toolbar button:
- On the Tools menu, click Customize.
- Click the Commands tab.
- In the Category box, click Macros.
- From the Commands box, drag the macro's name to the toolbar where you want a button for the macro.
- In the Button Appearance dialog box, select an image for the toolbar button, and then click OK. Visual C++ adds a button with that image to the toolbar.
To assign a macro to a key sequence:
- On the Tools menu, click Customize.
- Click the Keyboard tab.
- In the Category box, click Macros.
- In the Commands box, select the macro you want to assign.
- Click in the Press new shortcut key box.
- Press the key sequence you want to use for the macro.
- Click the Assign button. Visual C++ assigns that key sequence to the macro.
Points of Interest
I don't much like the InputBox
in CopyOutputFile
, it feels clumsy. I wanted to just copy the file to the clipboard so that I could CTRL+V it into any directory I wanted. However, I don't think this can be done without a 'clipboard ActiveX DLL' (which I couldn't be bothered to write).
History
- 13-Apr-2005 v1.0
I don't anticipate anymore versions, unless you clever CPians know something I don't.
- 26-Apr-2005 v1.1
OK, I lied! A couple of tweaks:
- Fixed both searches to account for relative paths (..\..\Blah\Foo\Bar).
- For
CopyOutputFile
, I found a project where the "/out:" item wasn't present in the project file. In that case, the function uses the project name and type to create a default file name in the output directory (found as per OpenOutputDir
).