Move macro forward when caught/stuck in process - windows

I have written a macro that uses the paping.exe program to cycle through a list of device IP addresses by sending pings and recording their return values. While the macro works as intended for the majority of the time, there are spare moments when the ping command appears to be stuck or caught up and stops moving forward. This causes me to have to manually break the execution and start the process over.
From a more broad perspective, is there a way to handle this runtime error. My thought was to break the list of devices into groupings, and if the program becomes stuck, I could tell the macro to move forward to the next grouping. While just an idle idea, I wanted to reach out to the community for advice, tips and ideas on ways I could more eloquently handle this issue. The list of devices that I am pinging is set to grow in time as well.
Public Sub getPingStatusCode(IPvalue As String, portValue As String)
ret = WshShell.Run("C:\Users\*******\paping.exe " & IPvalue & " -p " & portValue & " -c " & pingCount & " -t " & pingTime, 0, True) 'CHANGEEEEEEE
totalCounter = totalCounter + 1
Select Case ret
Case 0: strResult = "Connected"
Case 1: strResult = "Fail"
Case 11001: strResult = "Buffer too small"
Case 11002: strResult = "Destination net unreachable"
Case 11003: strResult = "Destination host unreachable"
Case 11004: strResult = "Destination protocol unreachable"
Case 11005: strResult = "Destination port unreachable"
Case 11006: strResult = "No resources"
Case 11007: strResult = "Bad option"
Case 11008: strResult = "Hardware error"
Case 11009: strResult = "Packet too big"
Case 11010: strResult = "Request timed out"
Case 11011: strResult = "Bad request"
Case 11012: strResult = "Bad route"
Case 11013: strResult = "TTL expired transit"
Case 11014: strResult = "TTL expired reassembly"
Case 11015: strResult = "Parameter problem"
Case 11016: strResult = "Source quench"
Case 11017: strResult = "Option too big"
Case 11018: strResult = "Bad destination"
Case 11032: strResult = "Negotiating IPSEC"
Case 11050: strResult = "General failure"
Case Else: strResult = "Unknown host"
End Select
'if statement on return value for bolding and font color
'and counters
If ret = 0 Then 'CONNECTED
With pingSheet.Cells(i, 4)
.Value = strResult
End With
totalOn = totalOn + 1
onOff = 1
'set the rawDataSheet value to connected status...assumes that the sheet starts with all rawdata values as "connected"
rawDataSheet.Cells(4, i).Value = strResult
ElseIf ret = 1 Then 'FAILED
With pingSheet.Cells(i, 4)
.Value = strResult
.Font.Color = vbRed
.Font.bold = True
End With
failCounter = failCounter + 1
onOff = 0
'give RawData sheet a "down since" date value
If rawDataSheet.Cells(4, i).Value = "Connected" Then
rawDataSheet.Cells(4, i).Value = Now
End If
''''''''''''''
pdfDeviceDump
Else
With pingSheet.Cells(i, 4)
.Value = strResult
.Font.Color = vbRed
.Font.bold = True
End With
failCounter = failCounter + 1
onOff = 0
End If
End Sub

I could not get paping.exe to run on my machine so I wrote some code using ping.exe instead.
In principle one can shell out and redirect output to file and then pick up the file later when finished. We use Windows API calls to wait for a process to finish.
Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Const INFINITE = &HFFFF
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Sub TestShellAndRedirectPingToFile()
Dim vIPAddresses As Variant
vIPAddresses = Array("bbc.co.uk", "wikipedia.org", "cnn.com")
Dim dicFilesToPickUp As Scripting.Dictionary
Set dicFilesToPickUp = ShellAndRedirectPingToFile(vIPAddresses)
Dim vKeyLoop As Variant
For Each vKeyLoop In dicFilesToPickUp.Keys
Dim lPID As Long
lPID = dicFilesToPickUp.Item(vKeyLoop)
Dim hProc As Long
hProc = OpenProcess(PROCESS_ALL_ACCESS, 0&, lPID)
Debug.Print "Waiting on " & vKeyLoop & " (" & lPID & ")"
WaitForSingleObject hProc, INFINITE
CloseHandle hProc '* be nice and close handles
Next
Debug.Print "Done! Files ready to read."
End Sub
Function ShellAndRedirectPingToFile(ByVal vIPAddresses As Variant) As Scripting.Dictionary
Dim dicFilesToPickUp As Scripting.Dictionary
Set dicFilesToPickUp = New Scripting.Dictionary
Dim sTempFolder As String
sTempFolder = Environ$("TEMP")
If Right$(sTempFolder, 1) <> "\" Then sTempFolder = sTempFolder & "\"
Dim vAddressLoop As Variant
For Each vAddressLoop In vIPAddresses
Dim sTempFile As String
sTempFile = sTempFolder & vAddressLoop & ".txt"
Dim sCmd As String
sCmd = Environ$("comspec") & " /S /C ping.exe " & vAddressLoop & " > " & sTempFile
Dim lPID As Long
lPID = VBA.Shell(sCmd)
dicFilesToPickUp.Add sTempFile, lPID
Next
Set ShellAndRedirectPingToFile = dicFilesToPickUp
End Function

Related

Check for existing DSN before creating it with vb6 code

i have done a connection using DSN, in which i have created a DSN throgh program. In that i have called a function to create a DSN, I dont want to call that function ecerytime i run the software, Instead i want to check whether dsn with the same name is already exist in the system or not, if it is not exist then only call to the function`
Public Sub ConnectDB(Con As ADODB.Connection)
Call CreatSQLDSN("TRDSN", VarSrvNm, VarDbName)
If Cn.State = 1 Then Cn.Close
On Error Resume Next
Con.ConnectionString = "Provider=MSDASQL.1;Persist Security Info=False;User ID=sa;Data Source=TRDSN;Initial Catalog='" & VarDbName & "'"
Con.Open Con.ConnectionString
If Err.Number <> 0 Then
If Err.Number = -2147467259 Then
If MsgBox(ServerName & " Server not Found. Connect to Other Server?", vbQuestion + vbDefaultButton2 + vbYesNo, "") = vbYes Then
PrintFile = Trim(Left(FindWindowPath, 3) & "DosPrint.Bat")
FileSystemObject.CreateTextFile PrintFile, True
Set TextStream = FileSystemObject.OpenTextFile(PrintFile, ForAppending)
TextStream.WriteLine "Del " & Left(FindWindowPath, 3) & "ServerName.dat"
TextStream.Close
Shell PrintFile, vbHide
End If
End
Else
If MsgBox(Err.Description, vbQuestion + vbOKOnly, "") = vbOK Then
Cancel = True
Exit Sub
End If
End If
End If
0
End Sub
Public Function CreatSQLDSN(SqlDsnName As String, SqlServerName As String, SqlDataName As String)
Dim Ret%, Driver$, Attributes$
Driver = "SQL Server" & Chr(0)
Attributes = "Server=" & SqlServerName & Chr(0)
Attributes = Attributes & "DSN=" & SqlDsnName & Chr(0)
Attributes = Attributes & "Database=" & SqlDataName & Chr(0)
Ret = SQLConfigDataSource(vbAPINull, ODBC_Add_User_DSN, Driver, Attributes)
'ret is equal to 1 on success and 0 if there is an error
If Ret <> 1 Then
MsgBox "User DSN Creation Failed"
End If
End Function`
A couple of options come to mind when needing to know if a DSN exists. You could either read through the Registry, or leverage your existing API call. I prefer the second option. It seems like a cleaner way to check for the existence of the DSN. Here is an example of what I am talking about:
Option Explicit
Private Declare Function SQLConfigDataSource Lib "ODBCCP32.DLL" (ByVal hwndParent As Long, ByVal fRequest As Long, ByVal lpszDriver As String, ByVal lpszAttributes As String) As Long
Private Const ODBC_ADD_DSN = 1
Private Const ODBC_CONFIG_DSN = 2
Private Const ODBC_REMOVE_DSN = 3
Private Const ODBC_ADD_SYS_DSN = 4
Private Const ODBC_CONFIG_SYS_DSN = 5
Private Const ODBC_REMOVE_SYS_DSN = 6
Private Const ODBC_REMOVE_DEFAULT_DSN = 7
Private Sub cmdCreate_Click()
Dim VarSrvNm As String
Dim VarDbName As String
VarSrvNm = "MyServer"
VarDbName = "MyDB"
If Not SQLDSNExists("TRDSN", VarSrvNm, VarDbName) Then
If Not CreateSQLDSN("TRDSN", VarSrvNm, VarDbName) Then
MsgBox "User DSN Creation Failed"
End If
End If
End Sub
Public Function CreateSQLDSN(SqlDsnName As String, SqlServerName As String, SqlDataName As String) As Boolean
Dim Ret%, Driver$, Attributes$
Driver = "SQL Server" & Chr(0)
Attributes = "Server=" & SqlServerName & Chr(0)
Attributes = Attributes & "DSN=" & SqlDsnName & Chr(0)
Attributes = Attributes & "Database=" & SqlDataName & Chr(0)
Ret = SQLConfigDataSource(0&, ODBC_ADD_DSN, Driver, Attributes)
'ret is equal to 1 on success and 0 if there is an error
CreateSQLDSN = (Ret = 1)
End Function
Public Function SQLDSNExists(SqlDsnName As String, SqlServerName As String, SqlDataName As String) As Boolean
Dim Ret%, Driver$, Attributes$
Driver = "SQL Server" & Chr(0)
Attributes = "Server=" & SqlServerName & Chr(0)
Attributes = Attributes & "DSN=" & SqlDsnName & Chr(0)
Attributes = Attributes & "Database=" & SqlDataName & Chr(0)
Ret = SQLConfigDataSource(0&, ODBC_CONFIG_DSN, Driver, Attributes)
'ret is equal to 1 on success and 0 if there is an error
SQLDSNExists = (Ret = 1)
End Function
The main idea here is to try to modify the DSN you want to add. If the call fails, then the DSN does not exist.

VBScript MapNetworkDrive Error Handling

I am attempting to write a small script in VBScript just purely for my home use, which is run prior to a scheduled backup in Macrium Reflect.
I am stuck on one seemingly small issue and that is error handling when the Network Drive is physically disconnected, i.e. the cable is not attached.
At the moment the script check to see if the Drive is already attached, if the drive is not attached then a message is displayed telling the user to connect the cable and press YES.
Now, all things being well the user would have connected the cable as asked and then pressed the YES button but I want to catch the times when YES was pressed before attaching the drive's cable.
Within the code there's an 'On Error Resume Next' which masks this eventuality, so I comment out this line & indeed I get an Error 'The Network Path Was Not Found' on line 40:
objNetwork.MapNetworkDrive strDriveLetter, strRemotePath, _
I want to use this caught error to display an alert to the user that the drive has not yet been connected, please connect and retry & KEEP RETRYING until the drive is actually connected.
My problem is I cannot seem to find where to add any error handling code to display this message.
Here's my code:
Option Explicit
Dim strDriveLetter, strRemotePath, strUser, strPassword, strProfile, strName, objNetwork, objShell, CheckDrive, AlreadyConnected, intDrive
' The section sets the variables.
strDriveLetter = "X:"
strRemotePath = "\\192.168.1.1\shared"
strUser = "user"
strPassword = "password"
strProfile = "true"
strName = "Backup Drive"
' This sections creates two objects:
' objShell and objNetwork and counts the drives
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
Set CheckDrive = objNetwork.EnumNetworkDrives()
' This section deals with a For ... Next loop
' See how it compares the enumerated drive letters
' with strDriveLetter
On Error Resume Next
AlreadyConnected = False
For intDrive = 0 To CheckDrive.Count - 1 Step 2
If CheckDrive.Item(intDrive) =strDriveLetter _
Then AlreadyConnected = True
Next
If AlreadyConnected = False Then
Dim result
result = MsgBox("A Backup Is Now Due But The Drive Is Not Connected." & vbNewLine & vbNewLine & "Please Connect The Drive & Press YES To Continue." & vbNewLine & vbNewLine & "If You Wish To Postpone Backup Then Press NO Now.", 4 + 32, "BACKUP DRIVE NOT CONNECTED")
If result = 7 Then
WScript.Quit
Else
Call MapDRV
End If
Sub MapDRV()
Set objNetwork = WScript.CreateObject("WScript.Network")
objNetwork.MapNetworkDrive strDriveLetter, strRemotePath, _
strProfile, strUser, strPassword
Set objShell = CreateObject("Shell.Application")
objShell.NameSpace(strDriveLetter).Self.Name = strName
End Sub
WScript.Quit
The error handling code is something along these lines:
If Err.Number <> 0 Then
'error handling:
'ALERT USER HERE
Err.Clear
End If
Any help would be appreciated
Err Object (VBScript) reference does not give useful guide. You need to trap an error or success separate for every run-time error prone action.
Common rule (best practice): keep error handling disabled via On Error GoTo 0 and enable it only for suspected actions.
For instance, there could me more than one reason why MapNetworkDrive method could fail (server off-line, user blocked, wrong/changed password etc.):
Sub MapDRV
Dim errResult
Set objNetwork = WScript.CreateObject("WScript.Network")
errResult = ""
On Error Resume Next
objNetwork.MapNetworkDrive strDriveLetter, strRemotePath _
, strProfile, strUser, strPassword
If Err.Number = 0 Then
On Error GoTo 0
Set objShell = CreateObject("Shell.Application")
objShell.NameSpace(strDriveLetter).Self.Name = strName
Else
errResult = Err.Number & " 0x" & Hex(Err.Number) & " " & Err.Source
errResult = errResult & vbNewLine & Err.Description
On Error GoTo 0
MsgBox errResult, vbOKOnly + vbCritical, "Error occurred"
End If
End Sub
The whole script then could look as follows:
Option Explicit
On Error GoTo 0
Dim strResult: strResult = Wscript.ScriptName
Dim strDriveLetter, strRemotePath, strUser, strPassword, strProfile , strName _
, objNetwork, objShell, CheckDrive, AlreadyConnected, intDrive
' The section sets the variables.
strDriveLetter = "X:"
strRemotePath = "\\192.168.1.1\shared"
strUser = "user"
strPassword = "password"
strProfile = "true"
strName = "Backup Drive"
' This sections creates two objects:
' objShell and objNetwork and counts the drives
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
' This section deals with a For ... Next loop
' See how it compares the enumerated drive letters with strDriveLetter
Dim result, toShare
AlreadyConnected = False
Do While AlreadyConnected = False
strResult = strResult & vbNewLine & "--- new check"
AlreadyConnected = False
Set CheckDrive = objNetwork.EnumNetworkDrives()
For intDrive = 0 To CheckDrive.Count - 1 Step 2
If CheckDrive.Item(intDrive) = strDriveLetter Then
AlreadyConnected = True
toShare = CheckDrive.Item(intDrive + 1)
End If
strResult = strResult & vbNewLine & CheckDrive.Item(intDrive)
strResult = strResult & vbTab & CheckDrive.Item(intDrive + 1)
Next
If AlreadyConnected Then Exit Do
result = MsgBox("A Backup Is Now Due But The Drive Is Not Connected." _
& vbNewLine & vbNewLine & "If you wish to ..." _
& vbNewLine & vbTab & "... postpone backup then press ABORT." _
& vbNewLine & vbTab & "... backup to " & strRemotePath & " then press RETRY." _
& vbNewLine & "Otherwise, please connect the drive & press IGNORE to continue." _
, vbAbortRetryIgnore + vbQuestion, "BACKUP DRIVE NOT CONNECTED")
Select Case result
Case vbAbort
Call scriptQuit
Case vbRetry
Call MapDRV
Case Else
' The Case Else clause is not required
End Select
Loop
strResult = strResult & vbNewLine & "copy here to " & toShare
Sub MapDRV
' no need to redefine: WshNetwork Object is already defined
' Set objNetwork = WScript.CreateObject("WScript.Network")
Dim errResult
On Error Resume Next
objNetwork.MapNetworkDrive strDriveLetter, strRemotePath _
, strProfile, strUser, strPassword
If Err.Number = 0 Then
On Error GoTo 0
Set objShell = CreateObject("Shell.Application")
objShell.NameSpace(strDriveLetter).Self.Name = strName
Else
errResult = Err.Number & " 0x" & Hex(Err.Number) & " " & Err.Source
errResult = errResult & vbNewLine & Err.Description
On Error GoTo 0
MsgBox errResult, vbOKOnly + vbCritical, "Error occurred"
strResult = strResult & vbNewLine & vbNewLine & errResult
End If
End Sub
Call scriptQuit
Sub scriptQuit
Wscript.Echo strResult
Wscript.Quit
End Sub
Please note that strResult variable is there merely for debugging purposes to see next output:
==> cscript D:\VB_scripts\SO\37776762.vbs
37776762.vbs
--- new check
Y: \\S-PC\VB_scripts_help
-2147024843 0x80070035 WSHNetwork.MapNetworkDrive
The network path was not found.
--- new check
Y: \\S-PC\VB_scripts_help
--- new check
Y: \\S-PC\VB_scripts_help
X: \\S-PC\test
copy here to \\S-PC\test
==>
Above output corresponds to next actions:
run script
1st --- new check found Y: mapped disk; then invoked Retry action failed (network path was not found);
2nd --- new check found Y: mapped disk again; then mapped disk X: manually and then invoked Ignore action;
3rd --- new check found Y: and X: mapped disks;
Do While loop exited and script continues to next action.
For completeness, following output shows invoked Abort action:
==> net use x: /delete
x: was deleted successfully.
==> cscript D:\VB_scripts\SO\37776762.vbs
37776762.vbs
--- new check
Y: \\S-PC\VB_scripts_help
==>

VBS: How to get the filesize with special FileDialog?

Function FileDialog()
Dim oExec1: Set oExec1=CreateObject("WScript.Shell").Exec( "mshta.exe ""about:" & "<" & "input type=file id=FILE" & ">" & "<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>""" )
Dim sPathfile: sPathfile = oExec1.StdOut.ReadAll
sPathfile = Replace( sPathfile, vbCRLF, "" )
FileDialog = sPathfile
End Function
change to:
Function FileDialog(filesize)
filesize will return the value of bytes of the selected file
Read Function Statement (VBScript) document and pass the argument by reference as follows:
option explicit
On Error GoTo 0
Dim strResult: strResult = Wscript.ScriptName
Dim nFileSize: nFileSize = -1 ' for test that `byRef` declaration works
strResult = strResult & vbNewLine & FileDialog( nFileSize)
strResult = strResult & vbNewLine & nFileSize
Wscript.Echo strResult
Wscript.Quit
Function FileDialog( byRef xSize)
Dim oExec1
Set oExec1=CreateObject("WScript.Shell").Exec( "mshta.exe ""about:" & "<" & "input type=file id=FILE" & ">" & "<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>""" )
Dim sPathfile: sPathfile = oExec1.StdOut.ReadAll
sPathfile = Replace( sPathfile, vbCRLF, "" )
If Len(sPathfile) > 0 Then
With CreateObject("Scripting.FileSystemObject").GetFile(sPathfile)
xSize = .Size ' the size, in bytes, of the specified file
End With
Else
' No file chosen: red "×" or Esc or Cancel pressed
xSize = 0
End If
FileDialog = sPathfile
End Function
Read ByRef and ByVal Parameters article as well.

Killing Previous Instance of VB6 Application

I've searched around for the proper way to kill a previous Instance of a VB6 application to no avail. If our main service dies, we need to terminate the previous instance of the running application and then, when the service comes back up only the new instance should be loaded. I am trying to exit this code in the following function:
Private Sub g_cServerInterface_FatalError(Error As enSvrReturns, ErrorString As String)
Dim sMsg As String
Dim result As VbMsgBoxResult
m_bFatalError = True
UnFreeze
If m_cLanguageText Is Nothing Then
GoTo TheEnd 'Form not yet loaded - not yet logged on
End If
' m_NumFatalErrors = m_NumFatalErrors + 1
' If m_NumFatalErrors > 5 Then
' Functions.DevInfo "Unable to restart Manitou.", g_cLangText_General
' End
' End If
If Error <> SVRERR_NOT_CONNECTED Or RunningInDebugger() Then
sMsg = g_cLangText_General.GetText("A system error has occurred")
If ErrorString <> "" Then
sMsg = sMsg & ":" & vbCrLf & vbCrLf & ErrorString & vbCrLf & vbCrLf
Else
sMsg = sMsg & ". "
End If
sMsg = sMsg & g_cLangText_General.GetText("Press OK to attempt to restart or Cancel to quit.")
result = DevAskOkCancel(sMsg, Nothing)
Else
' Since we've been disconnected, attempt immediately to reconnect
result = vbOK
End If
If (result = vbOK) Then
On Local Error Resume Next
If InStr(g_CommandLine, "-U") = 0 Then
g_CommandLine = g_CommandLine & " -U" & g_cUser.id
End If
If InStr(g_CommandLine, "-P") = 0 Then
g_CommandLine = g_CommandLine & " -P" & g_cUser.Password
End If
Shell App.Path & "\" & App.EXEName & " " & g_CommandLine & " -X", vbNormalFocus
DoEvents
End If
TheEnd:
If (Not RunningInDebugger()) Then
' Running as compiled executable
' Specifies the exit code for the process, and for all threads that
' are terminated as a result of this call. Use the GetExitCodeProcess
' function to retrieve the process's exit value. Use the GetExitCodeThread
' function to retrieve a thread's exit value.
CoUninitialize
ExitProcess 0
Else
' Running from the IDE
End
End If
End Sub
Note that I added the CoUninitialize and ExitProcess 0 API calls to this. How can I correctly terminate the previously loaded instance when the service comes back up? thanks Larry
Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" _
Alias "PostMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Const WM_CLOSE = &H10
Private Sub Form_Load()
Dim strCap As String
Dim lngHwnd As Long
Dim lngRet As Long
strCap = Me.Caption
Me.Caption = "*" & strCap
lngHwnd = FindWindow(ByVal vbNullString, ByVal strCap)
If lngHwnd <> 0 Then
PostMessage lngHwnd, WM_CLOSE, 0&, 0&
End If
Me.Caption = strCap
End Sub

Need Visual Studio macro to add banner to all C# files

Can someone post a Visual Studio macro which goes through all C# source files in a project and adds a file banner? Extra credit if it works for any type of source file (.cs, .xaml, etc).
Here you go, I provide an example for .cs and .vb but shouldn't be hard for you to adjust it to your other file type needs: Edited to recursively add header to sub-folders
Sub IterateFiles()
Dim solution As Solution = DTE.Solution
For Each prj As Project In solution.Projects
IterateProjectFiles(prj.ProjectItems)
Next
End Sub
Private Sub IterateProjectFiles(ByVal prjItms As ProjectItems)
For Each file As ProjectItem In prjItms
If file.SubProject IsNot Nothing Then
AddHeaderToItem(file)
IterateProjectFiles(file.ProjectItems)
ElseIf file.ProjectItems IsNot Nothing AndAlso file.ProjectItems.Count > 0 Then
AddHeaderToItem(file)
IterateProjectFiles(file.ProjectItems)
Else
AddHeaderToItem(file)
End If
Next
End Sub
Private Sub AddHeaderToItem(ByVal file As ProjectItem)
DTE.ExecuteCommand("View.SolutionExplorer")
If file.Name.EndsWith(".cs") OrElse file.Name.EndsWith(".vb") Then
file.Open()
file.Document.Activate()
AddHeader()
file.Document.Save()
file.Document.Close()
End If
End Sub
Private Sub AddHeader()
Dim cmtHeader As String = "{0} First Line"
Dim cmtCopyright As String = "{0} Copyright 2008"
Dim cmtFooter As String = "{0} Footer Line"
Dim cmt As String
Select Case DTE.ActiveDocument.Language
Case "CSharp"
cmt = "//"
Case "Basic"
cmt = "'"
End Select
DTE.UndoContext.Open("Header Comment")
Dim ts As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
ts.StartOfDocument()
ts.Text = String.Format(cmtHeader, cmt)
ts.NewLine()
ts.Text = String.Format(cmtCopyright, cmt)
ts.NewLine()
ts.Text = String.Format(cmtFooter, cmt)
ts.NewLine()
DTE.UndoContext.Close()
End Sub
Visual Studio macro to add file headers
Here is the jist of it. No, I have not debugged this, that is an excercise for the reader. And, this is done off the top of my head. (Except the File commenter...That's a real Macro that I use).
function CommentAllFiles
option explicit
Dim ActiveProjectFullName
Dim dte80 As EnvDTE80.Solution2
ActiveProjectFullName = dte80.Projects.Item(0).FullName
If ActiveProjectFullName = "" Then
MsgBox("No project loaded!")
Exit Sub
End If
Err.Number = 0
doc.Open(ActiveProjectFullName, "Text", True)
If Err.Number <> 0 Then
MsgBox("Open " + ActiveProjectFullName + " failed: " & Hex(Err.Number))
Exit Sub
End If
ActiveDocument.Goto(1, 1, vsMovementOptions.vsMovementOptionsMove)
' Build search string
Dim SearchString
Dim vsFindOptionsValue As Integer
SearchString = "^SOURCE=.*" + dn + "$"
while ActiveDocument.Selection.FindText(SearchString, vsFindOptions.vsFindOptionsFromStart + vsFindOptions.vsFindOptionsRegularExpression)
Dim TheFile
TheFile = ActiveDocument.Selection.Text
TheFile = Mid(TheFile, 8)
doc.Open(TheFile)
wend
ActiveDocument.Close()
end function
Tried and true "Flower Box" adder:
Function IsClassDef()
Dim ColNum
Dim LineNum
Dim sText
sText = ActiveDocument.Selection.ToString()
If sText = "" Then
'ActiveDocument.Selection.WordRight(dsExtend)
'sText = ActiveDocument.Selection
'sText = ucase(trim(sText))
End If
If (sText = "CLASS") Then
IsClassDef = True
Else
IsClassDef = False
End If
End Function
Sub AddCommentBlock()
'DESCRIPTION: Add Commecnt block to header, CPP files and Class Defs
AddCPPFileDesc()
End Sub
Sub AddCPPFileDesc()
'DESCRIPTION: Add File desc block to the top of a CPP file
Dim selection As EnvDTE.TextSelection
ActiveDocument.Selection.StartOfLine()
Dim editPoint As EnvDTE.EditPoint
selection = DTE.ActiveDocument.Selection()
editPoint = selection.TopPoint.CreateEditPoint()
Dim bOk, sExt, IsCpp, IsHdr, sHeader, IsCSharp
bOk = True
IsCpp = False
IsCSharp = False
If ActiveDocument.Selection.CurrentLine > 10 Then
If MsgBox("You are not at the top of the file. Are you sure you want to continue?", vbYesNo + vbDefaultButton2) = vbNo Then
bOk = False
End If
End If
If (bOk) Then
sExt = ucase(right(ActiveDocument.Name, 4))
IsCpp = sExt = ".CPP"
IsHdr = Right(sExt, 2) = ".H"
IsCSharp = sExt = ".CS"
If (IsCpp) Then
sHeader = left(ActiveDocument.Name, len(ActiveDocument.Name) - 3) + "h"
FileDescTopBlock(1)
editPoint.Insert("#include " + Chr(34) + "StdAfx.h" + Chr(34) + vbLf)
editPoint.Insert("#include " + Chr(34) + sHeader + Chr(34) + vbLf)
ElseIf (IsCSharp) Then
FileDescTopBlock(1)
Else
If IsHdr Then
'If IsCLassDef() Then
'AddClassDef()
'Else
AddHeaderFileDesc()
'End If
Else
FileDescTopBlock(1)
End If
End If
End If
End Sub
Sub AddHeaderFileDesc()
FileDescTopBlock(0)
Dim selection As EnvDTE.TextSelection
ActiveDocument.Selection.StartOfLine()
Dim editPoint As EnvDTE.EditPoint
selection = DTE.ActiveDocument.Selection()
editPoint = selection.TopPoint.CreateEditPoint()
editPoint.Insert("#pragma once" + vbLf)
End Sub
Sub FileDescTopBlock(ByVal HasRevHistory)
'DESCRIPTION: Add File desc block to the top of a CPP file
Dim selection As EnvDTE.TextSelection
ActiveDocument.Selection.StartOfLine()
ActiveDocument.Selection.EndOfLine()
Dim sComment
sComment = ActiveDocument.Selection.ToString()
If Left(sComment, 2) = "//" Then
ActiveDocument.Selection.Delete()
sComment = LTrim(Mid(sComment, 3))
Else
sComment = ""
End If
Dim sLineBreak
Dim sFileName
Dim sBlock
sLineBreak = "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////"
sFileName = ActiveDocument.Name
ActiveDocument.Selection.StartOfDocument()
sBlock = sLineBreak & vbLf & _
"// File : " & sFileName & vbLf & _
"// Author : Larry Frieson" & vbLf & _
"// Desc : " & sComment & vbLf & _
"// Date : " & CStr(Now.Date()) & vbLf & _
"//" & vbLf & _
"// Copyright © 20" + Right(CStr(Now.Year.ToString()), 2) + " MLinks Technologies. All rights reserved" + vbLf
If (HasRevHistory > 0) Then
sBlock = sBlock & _
"//" & vbLf & _
"// Revision History: " & vbLf & _
"// " & CStr(Now) & " created." & vbLf & _
"// " & vbLf
End If
sBlock = sBlock + sLineBreak + vbLf
Dim editPoint As EnvDTE.EditPoint
selection = DTE.ActiveDocument.Selection()
editPoint = selection.TopPoint.CreateEditPoint()
editPoint.Insert(sBlock)
End Sub
Hope this helps, or at least gives you some ideas. Again, I didn't test/debug the "source file looper", I figure you can handle that.
Larry

Resources