Need Visual Studio macro to add banner to all C# files - visual-studio

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

Related

Sync outlook messages with vbscript

I have a vbscript that copy's Outlook 2003 messages into a folder in msg format.
The problems are:
I am getting "path too long" errors for some *.msg . I wish to avoid these erros and I don't know how. ' On Error Resume Next is already on the script.
I am getting only inbox messages, but I want all subfolders too;
How can I extract this in *.txt and not in *.msg, in order to become lighter?
Here is my atual script. Thanks for the help!
On Error Resume Next
Dim myNameSpace
Dim ofChosenFolder
Dim myOlApp
Dim myItem
Dim objItem
Dim myFolder
Dim strSubject
Dim strName
Dim strFile
Dim strReceived
Dim strSavePath
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set myOlApp = CreateObject("Outlook.Application")
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Const olFolderInbox = 6
Set ofChosenFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
strSavePath = "c:\test\" 'OBS! use a \ at the end of the path
i = 1
For each Item in ofChosenFolder.Items
Set myItem = ofChosenFolder.Items(i)
strReceived = ArrangedDate(myitem.ReceivedTime)
' strSubject = myItem.Subject
strSubject = myitem.SenderName & "_" & myitem.Subject
strName = StripIllegalChar(strSubject)
strFile = strSavePath & strReceived & "_" & strName & ".msg"
If Not Len(strfile) > 256 then
myItem.SaveAs strfile, 3
Else
wscript.echo strfile & vbcrlf & "Path and filename too long."
End If
i = i + 1
next
Function StripIllegalChar(strInput)
'***************************************************
'Simple function that removes illegal file system
'characters.
'***************************************************
Set RegX = New RegExp
RegX.pattern = "[\" & chr(34) & "\!\#\#\$\%\^\&\*\(\)\=\+\|\[\]\{\}\`\'\;\:\<\>\?\/\,]"
RegX.IgnoreCase = True
RegX.Global = True
StripIllegalChar = RegX.Replace(strInput, "")
Set RegX = nothing
End Function
Function ArrangedDate(strDateInput)
'***************************************************
'This function re-arranges the date data in order
'for it to display in chronilogical order in a
'sorted list in the file system. It also removes
'illegal file system characters and replaces them
'with dashes.
'Example:
'Input: 2/26/2004 7:07:33 AM
'Output: 2004-02-26_AM-07-07-33
'***************************************************
Dim strFullDate
Dim strFullTime
Dim strAMPM
Dim strTime
Dim strYear
Dim strMonthDay
Dim strMonth
Dim strDay
Dim strDate
Dim strDateTime
Dim RegX
If not Left(strDateInput, 2) = "10" Then
If not Left(strDateInput, 2) = "11" Then
If not Left(strDateInput, 2) = "12" Then
strDateInput = "0" & strDateInput
End If
End If
End If
strFullDate = Left(strDateInput, 10)
If Right(strFullDate, 1) = " " Then
strFullDate = Left(strDateInput, 9)
End If
strFullTime = Replace(strDateInput,strFullDate & " ","")
If Len(strFullTime) = 10 Then
strFullTime = "0" & strFullTime
End If
strAMPM = Right(strFullTime, 2)
strTime = strAMPM & "-" & Left(strFullTime, 8)
strYear = Right(strFullDate,4)
strMonthDay = Replace(strFullDate,"/" & strYear,"")
strMonth = Left(strMonthDay, 2)
strDay = Right(strMonthDay,len(strMonthDay)-3)
If len(strDay) = 1 Then
strDay = "0" & strDay
End If
strDate = strYear & "-" & strMonth & "-" & strDay
'strDateTime = strDate & "_" & strTime
strDateTime = strDate
Set RegX = New RegExp
RegX.pattern = "[\:\/\ ]"
RegX.IgnoreCase = True
RegX.Global = True
ArrangedDate = RegX.Replace(strDateTime, "-")
Set RegX = nothing
End Function
You need to truncate the file name appropriately (strName)
Move your code that processes a folder into a sub that take fodler that takes folder as parameter and call it for ofChosenFolder as well as all of its child fodlers in the ofChosenFolder.Folders collection.
You are calling SaveAs..., 3 - 3 here is olMsg. Specify olTxt (= 0).
Off the top of my head:
Const olFolderInbox = 6
Set ofChosenFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
trSavePath = "c:\test\"
ProcessFolder ofChosenFolder, trSavePath
sub ProcessFolder(folder, path)
For each Item in folder.Items
strReceived = ArrangedDate(Item.ReceivedTime)
strSubject = Item.SenderName & "_" &Item .Subject
strName = StripIllegalChar(strSubject)
strFile = strSavePath & strReceived & "_" & strName & ".msg"
If Not Len(strfile) > 256 then
Item.SaveAs strfile, 3
Else
wscript.echo strfile & vbcrlf & "Path and filename too long."
End If
next
for each subfolder in folder.Folders
ProcessFolder(subfolder, trSavePath & subfolder.Name & "\"
next
end sub

WiX v3.7 - vbScript Custom Action BrowseForFolder() not returning individual file names

I found a VB Script example for opening a file browser, which I used in a custom action in WiX. However, the VB Script function I use is called BrowseForFolder() (not browseforfile) and only seems to return a value when a directory is selected, but not when an individual file is selected. Here is the custom action:
<CustomAction Id="File" Script="vbscript" Execute="immediate" Return="ignore">
<![CDATA[
Dim shell
Set shell = CreateObject("Shell.Application")
Dim file
Set file = shell.BrowseForFolder(0, "Choose a file:", &H4000)
Session.Property("FileName") = file.self.Path
]]>
</CustomAction>
Using this method, I can actually see individual files in the dialog, which is a step up from Wix's built-in directory browser.
Now I just need to be able to retrieve individual file names, not just names of folders.
I've found this code.
https://gist.github.com/wangye/1932941
and made some changes on it to a better understanding
WScript.Echo GetOpenFileName("C:\", "")
'
' Description: VBScript/VBS open file dialog
' Compatible with most Windows platforms
' Author: wangye <pcn88 at hotmail dot com>
' Website: http://wangye.org
'
' dir is the initial directory; if no directory is
' specified "Desktop" is used.
' filter is the file type filter; format "File type description|*.ext"
'
'
Public Function GetOpenFileName(dir, filter)
Const msoFileDialogFilePicker = 3
If VarType(dir) <> vbString Or dir="" Then
dir = CreateObject( "WScript.Shell" ).SpecialFolders( "Desktop" )
End If
If VarType(filter) <> vbString Or filter="" Then
filter = "All files|*.*"
End If
' try to choose the way to open the dialog box. Array: TryObjectNames
Dim i,j, objDialog, TryObjectNames
TryObjectNames = Array( _
"UserAccounts.CommonDialog", _
"MSComDlg.CommonDialog", _
"MSComDlg.CommonDialog.1", _
"Word.Application", _
"SAFRCFileDlg.FileOpen", _
"InternetExplorer.Application" _
)
On Error Resume Next
Err.Clear
For i=0 To UBound(TryObjectNames)
Set objDialog = WSH.CreateObject(TryObjectNames(i))
If Err.Number <> 0 Then
Err.Clear
Else
Exit For
End If
Next
' Select the way to dealing the object dialog
Select Case i
Case 0,1,2
' 0. UserAccounts.CommonDialog XP Only.
' 1.2. MSComDlg.CommonDialog MSCOMDLG32.OCX must registered.
If i=0 Then
objDialog.InitialDir = dir
Else
objDialog.InitDir = dir
End If
objDialog.Filter = filter
If objDialog.ShowOpen Then
GetOpenFileName = objDialog.FileName
End If
Case 3
' 3. Word.Application Microsoft Office must installed.
objDialog.Visible = False
Dim objOpenDialog, filtersInArray
filtersInArray = Split(filter, "|")
Set objOpenDialog = _
objDialog.Application.FileDialog( _
msoFileDialogFilePicker)
With objOpenDialog
.Title = "Open File(s):"
.AllowMultiSelect = False
.InitialFileName = dir
.Filters.Clear
For j=0 To UBound(filtersInArray) Step 2
.Filters.Add filtersInArray(j), _
filtersInArray(j+1), 1
Next
If .Show And .SelectedItems.Count>0 Then
GetOpenFileName = .SelectedItems(1)
End If
End With
objDialog.Visible = True
objDialog.Quit
Set objOpenDialog = Nothing
Case 4
' 4. SAFRCFileDlg.FileOpen xp 2003 only
' See http://www.robvanderwoude.com/vbstech_ui_fileopen.php
If objDialog.OpenFileOpenDlg Then
GetOpenFileName = objDialog.FileName
End If
Case 5
Dim IEVersion,IEMajorVersion, hasCompleted
hasCompleted = False
Dim shell
Set shell = CreateObject("WScript.Shell")
' ????IE??
IEVersion = shell.RegRead( _
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version")
If InStr(IEVersion,".") > 0 Then
' ??????
IEMajorVersion = CInt(Left(IEVersion, InStr(IEVersion,".")-1))
If IEMajorVersion > 7 Then
' ???????7,?????IE7,???MSHTA??
' Bypasses c:\fakepath\file.txt problem
' http://pastebin.com/txVgnLBV
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim tempFolder : Set tempFolder = fso.GetSpecialFolder(2)
Dim tempName : tempName = fso.GetTempName()
Dim tempFile : Set tempFile = tempFolder.CreateTextFile(tempName & ".hta")
Dim tempBaseName
tempBaseName = tempFolder & "\" & tempName
tempFile.Write _
"<html>" & _
" <head>" & _
" <title>Browse</title>" & _
" </head>" & _
" <body>" & _
" <input type='file' id='f'>" & _
" <script type='text/javascript'>" & _
" var f = document.getElementById('f');" & _
" f.click();" & _
" var fso = new ActiveXObject('Scripting.FileSystemObject');" & _
" var file = fso.OpenTextFile('" & _
Replace(tempBaseName,"\", "\\") & ".txt" & "', 2, true);" & _
" file.Write(f.value);" & _
" file.Close();" & _
" window.close();" & _
" </script>" & _
" </body>" & _
"</html>"
tempFile.Close
Set tempFile = Nothing
Set tempFolder = Nothing
shell.Run tempBaseName & ".hta", 1, True
Set tempFile = fso.OpenTextFile(tempBaseName & ".txt", 1)
GetOpenFileName = tempFile.ReadLine
tempFile.Close
fso.DeleteFile tempBaseName & ".hta"
fso.DeleteFile tempBaseName & ".txt"
Set tempFile = Nothing
Set fso = Nothing
hasCompleted = True ' ??????
End If
End If
If Not hasCompleted Then
' 5. InternetExplorer.Application IE must installed
objDialog.Navigate "about:blank"
Dim objBody, objFileDialog
Set objBody = _
objDialog.document.getElementsByTagName("body")(0)
objBody.innerHTML = "<input type='file' id='fileDialog'>"
while objDialog.Busy Or objDialog.ReadyState <> 4
WScript.sleep 10
Wend
Set objFileDialog = objDialog.document.all.fileDialog
objFileDialog.click
GetOpenFileName = objFileDialog.value
End If
objDialog.Quit
Set objFileDialog = Nothing
Set objBody = Nothing
Set shell = Nothing
Case Else
MsgBox("No file dialog component found", MsgBoxStyle.Exclamation, "Error")
End Select
Set objDialog = Nothing
End Function

Find all photographs taken on a certain date

If have the following VBScript for recursively finding all the files in a set of folders. I simply found this on the web somewhere and can't take credit for it.
fileExtension = ".jpg"
folderPath = "C:\Pictures"
computerName = "."
arrFIL = Array()
If Right(folderPath,1) = "\" Then folderPath = Left(folderPath,Len(folderPath)-1)
Set wmiObject = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & computerName & "\root\cimv2")
Set folderObject = wmiObject.Get("Win32_Directory='" & folderPath & "'")
EnumFolders folderObject, wmiObject, arrFIL
strFIL = UBound(arrFIL) + 1 & " files found with extension '" & fileExtension & "':" & vbCrLf & vbCrLf
For intFIL = 0 To UBound(arrFIL)
Set objFile = objFSO.GetFile(arrFIL(intFIL))
strFIL = strFIL & arrFIL(intFIL) & vbCrLf
Next
WScript.Echo strFIL
Sub EnumFolders(folderObject, wmiObject, arrFIL)
On Error Resume Next
Dim objSD1
Dim objSD2
Dim objFI1
Dim objFI2
Set objSD1 = wmiObject.ExecQuery("Associators of {Win32_Directory.Name='" & fold erObject.Name & "'} Where AssocClass=Win32_SubDirectory ResultRole=PartComponent")
For Each objSD2 in objSD1
EnumFolders objSD2, wmiObject, arrFIL
Next
On Error Goto 0
Set objFI1 = wmiObject.ExecQuery("Associators of {Win32_Directory.Name='" & folderObject.Name & "'} Where ResultClass=CIM_DataFile")
For Each objFI2 in objFI1
If Right(objFI2.Name,Len(fileExtension)) = fileExtension Then
intFIL = UBound(arrFIL) + 1
ReDim Preserve arrFIL(intFIL)
arrFIL(intFIL) = objFI2.Name
End If
Next
End Sub
What I need to do is run this against a bunch of folders, within C:\Pictures, and have it return all files where the Date Taken property of the photo is the 23rd of the month. Is this possible? How would I achieve this?
Thanks
I'd use the Shell.Application object instead of WMI:
Const Name = 0
Const DateTaken = 12
folderPath = "C:\Pictures"
Set re = New RegExp
re.Pattern = "[^0-9:./ ]"
re.Global = True
Traverse CreateObject("Shell.Application").Namespace(folderPath)
Sub Traverse(fldr)
For Each obj In fldr.Items
If obj.IsFolder Then
Traverse obj.GetFolder
ElseIf LCase(obj.Type) = "jpeg image" Then
If Day(re.Replace(fldr.GetDetailsOf(obj, DateTaken), "")) = 23 Then
WScript.Echo fldr.GetDetailsOf(obj, Name)
End If
End If
Next
End Sub

VBScript. Move a file and rename it with increment if exists

I'm trying to create a vbscript that moves files from one directory to another, that increments the filename if the file allready exists. I.e. if file.ext exists, new filename is file_01.ext. If file_01.ext exists, new filename is file_02.ext, and so on. I can't get it to work. Any help would be very much appreciated.
Const cVBS = "Vaskedama.vbs" '= script name
Const cLOG = "Vaskedama.log" '= log filename
Const cFOL = "C:\fra\" '= source folder
Const cMOV = "C:\til\" '= dest. folder
Const cDAZ = -1 '= # days
Dim strMSG
strMSG = " files moved from " & cFOL & " to " & cMOV
MsgBox Move_Files(cFOL) & strMSG,vbInformation,cVBS
Function Move_Files(folder)
Move_Files = 0
Dim strDAT
Dim intDAZ
Dim arrFIL()
ReDim arrFIL(0)
Dim intFIL
intFIL = 0
Dim strFIL
Dim intLEN
intLEN = 0
Dim strLOG
strLOG = "echo " & cVBS & " -- " & Now & vbCrLf
Dim dtmNOW
dtmNOW = Now
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objGFO
Dim objGFI
If Not objFSO.FolderExists(cFOL) _
Or Not objFSO.FolderExists(cMOV) Then
MsgBox "A folder does not exist!",vbExclamation,cVBS
Exit Function
End If
Set objGFO = objFSO.GetFolder(folder)
Set objGFI = objGFO.Files
For Each strFIL In objGFI
strDAT = strFIL.DateCreated
intDAZ = DateDiff("d",strDAT,dtmNOW)
If intDAZ > cDAZ Then
intFIL = intFIL + 1
ReDim Preserve arrFIL(intFIL)
arrFIL(intFIL) = strFIL.Name
If intLEN < Len(strFIL.Name) Then
intLEN = Len(strFIL.Name)
End If
End If
Next
For intFIL = 1 To UBound(arrFIL)
strFIL = arrFIL(intFIL)
Do While (objFSO.FileExists(cMOV & strFIL))
strFil = CreateNewName(strFIL, intFIL)
Loop
objFSO.MoveFile folder & strFIL, cMOV & strFIL
strLOG = strLOG & "move " & folder & strFIL _
& Space(intLEN-Len(strFIL)+1) _
& cMOV & strFIL & vbCrLf
Next
Set objGFI = Nothing
Set objGFO = Nothing
strLOG = strLOG & "echo " & UBound(arrFIL) & " files moved"
objFSO.CreateTextFile(cLOG,True).Write(strLOG)
Set objFSO = Nothing
Move_Files = UBound(arrFIL)
End Function
Function CreateNewName(strValue, intValue)
CreateNewName = strValue & intValue
End Function
As I can't understand your script at all, I'll concentrate on the the task "build a new file name by incrementing a counter". Obviously you have to check for each file whether there is a file with the same name or this name + suffix in the destination folder. The answer to this question for file a is completely independent of all files in the source folder - so I doubt your array makes any sense.
In code:
Const cnMax = 3
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim oSrcDir : Set oSrcDir = goFS.GetFolder("..\testdata\FancyRename\from")
Dim sDstDir : sDstDir = "..\testdata\FancyRename\to"
Dim oFile, nInc, sNFSpec
For Each oFile In oSrcDir.Files
WScript.Echo "looking at", oFile.Name
nInc = 0
sNFSpec = getNewFSpec(oFile.Name, sDstDir, nInc)
Do While goFS.FileExists(sNFSpec) And nInc <= cnMax
sNFSpec = getNewFSpec(oFile.Name, sDstDir, nInc)
Loop
If nInc > cnMax Then
WScript.Echo "won't copy to", sNFSpec
Else
WScript.Echo "will copy to ", sNFSpec
oFile.Copy sNFSpec
End If
Next
Function getNewFSpec(ByVal sFName, sDstDir, ByRef nInc)
If 0 < nInc Then
Dim sSfx
sSfx = goFS.GetExtensionName(sFName)
If "" <> sSfx Then sSfx = "." & sSfx
sSfx = "_" & Right("00" & nInc, 2) & sSfx
sFName = goFS.GetBaseName(sFName) & sSfx
End If
nInc = nInc + 1
getNewFSpec = goFS.BuildPath(sDstDir, sFName)
End Function
some sample output:
looking at B.txt
will copy to ..\testdata\FancyRename\to\B.txt
looking at C.txt
will copy to ..\testdata\FancyRename\to\C.txt
looking at A.txt
will copy to ..\testdata\FancyRename\to\A.txt
looking at B.txt
will copy to ..\testdata\FancyRename\to\B_01.txt
looking at B.txt
won't copy to ..\testdata\FancyRename\to\B_03.txt

Deduplication and filtering of Add/Remove Programs list (VBScript)

This script works and tells and me what is installed in Program files.
Two problems
Duplicate lines
i.e
AVG 2011 Ver: 10.0.1204
AVG 2011 Ver: 10.0.1204 Installed: 27/01/2011
and
I don't want to include lines that have key words "Update","Hotfix","Java" can any VB gurus out there help with what extra is needed in this script?
Option Explicit
Dim sTitle
sTitle = "Installed Programs on your PC -"
Dim StrComputer
strComputer = Trim(strComputer)
If strComputer = "" Then strComputer = "."
'Wscript.Echo GetAddRemove(strComputer)
Dim sCompName : sCompName = GetProbedID(StrComputer)
Dim sFileName
sFileName = sCompName & "_" & GetDTFileName() & "_Software.txt"
Dim s : s = GetAddRemove(strComputer)
If WriteFile(s, sFileName) Then
'optional prompt for display
If MsgBox("Finished processing. Results saved to " & sFileName & _
vbcrlf & vbcrlf & "Do you want to view the results now?", _
4 + 32, sTitle) = 6 Then
WScript.CreateObject("WScript.Shell").Run sFileName, 9
End If
End If
Function GetAddRemove(sComp)
'Function credit to Torgeir Bakken
Dim cnt, oReg, sBaseKey, iRC, aSubKeys
Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
sComp & "/root/default:StdRegProv")
sBaseKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
iRC = oReg.EnumKey(HKLM, sBaseKey, aSubKeys)
Dim sKey, sValue, sTmp, sVersion, sDateValue, sYr, sMth, sDay
For Each sKey In aSubKeys
iRC = oReg.GetStringValue(HKLM, sBaseKey & sKey, "DisplayName", sValue)
If iRC <> 0 Then
oReg.GetStringValue HKLM, sBaseKey & sKey, "QuietDisplayName", sValue
End If
If sValue <> "" Then
iRC = oReg.GetStringValue(HKLM, sBaseKey & sKey, _
"DisplayVersion", sVersion)
If sVersion <> "" Then
sValue = sValue & vbTab & "Ver: " & sVersion
Else
sValue = sValue & vbTab
End If
iRC = oReg.GetStringValue(HKLM, sBaseKey & sKey, _
"InstallDate", sDateValue)
If sDateValue <> "" Then
sYr = Left(sDateValue, 4)
sMth = Mid(sDateValue, 5, 2)
sDay = Right(sDateValue, 2)
'some Registry entries have improper date format
On Error Resume Next
sDateValue = DateSerial(sYr, sMth, sDay)
On Error GoTo 0
If sdateValue <> "" Then
sValue = sValue & vbTab & "Installed: " & sDateValue
End If
End If
sTmp = sTmp & sValue & vbcrlf
cnt = cnt + 1
End If
Next
sTmp = BubbleSort(sTmp)
GetAddRemove = "INSTALLED SOFTWARE (" & cnt & ") - " & sCompName & _
" - " & Now() & vbcrlf & vbcrlf & sTmp
End Function
Function BubbleSort(sTmp)
'cheapo bubble sort
Dim aTmp, i, j, temp
aTmp = Split(sTmp, vbcrlf)
For i = UBound(aTmp) - 1 To 0 Step -1
For j = 0 to i - 1
If LCase(aTmp(j)) > LCase(aTmp(j+1)) Then
temp = aTmp(j + 1)
aTmp(j + 1) = aTmp(j)
aTmp(j) = temp
End if
Next
Next
BubbleSort = Join(aTmp, vbcrlf)
End Function
Function GetProbedID(sComp)
Dim objWMIService, colItems, objItem
Set objWMIService = GetObject("winmgmts:\\" & sComp & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select SystemName from " & _
"Win32_NetworkAdapter",,48)
For Each objItem in colItems
GetProbedID = objItem.SystemName
Next
End Function
Function GetDTFileName()
dim sNow, sMth, sDay, sYr, sHr, sMin, sSec
sNow = Now
sMth = Right("0" & Month(sNow), 2)
sDay = Right("0" & Day(sNow), 2)
sYr = Right("00" & Year(sNow), 4)
sHr = Right("0" & Hour(sNow), 2)
sMin = Right("0" & Minute(sNow), 2)
sSec = Right("0" & Second(sNow), 2)
GetDTFileName = sMth & sDay & sYr & "_" & sHr & sMin & sSec
End Function
Function WriteFile(sData, sFileName)
Dim fso, OutFile, bWrite
bWrite = True
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set OutFile = fso.OpenTextFile(sFileName, 2, True)
'Possibly need a prompt to close the file and one recursion attempt.
If Err = 70 Then
Wscript.Echo "Could not write to file " & sFileName & ", results " & _
"not saved." & vbcrlf & vbcrlf & "This is probably " & _
"because the file is already open."
bWrite = False
ElseIf Err Then
WScript.Echo err & vbcrlf & err.description
bWrite = False
End If
On Error GoTo 0
If bWrite Then
OutFile.WriteLine(sData)
OutFile.Close
End If
Set fso = Nothing
Set OutFile = Nothing
WriteFile = bWrite
End Function
#icecurtain: The second part of your question can be solved using InStr as suggested by #Oliver, rewritten to suit your script it would look like --
If sValue <> "" _
AND (InStr(1, sValue, "Hotfix", 1)) = 0 _
AND (InStr(1, sValue, "Update", 1)) = 0 _
AND (InStr(1, sValue, "Java", 1)) = 0) Then
The first part wouldn't be that tricky either except for the fact that you include a version and installation date if found (which some of the duplicates will only include in part or not at all). If the extra bits of data wasn't included, you could loop through all the lines and add them into a Scripting.Dictory object with a .Exists check to prevent a duplicate from being added.
Ok, even if i'm not a jedi master (or have no self-respect ;-)), this could help you:
If InStr(1, sValue, "hotfix", vbTextCompare) = 0 Then
Print "This is NOT a hotfix"
End If
For further informations just take a look at the MSDN page for InStr().
I don't think hardcoded string checks are the way to go, a uninstall entry is a update if any of these are true:
It has a dword value named SystemComponent that is <> 0
A string value named ParentKeyName
The registry sub key starts with "KB" or "Q" + 6 numbers (KB######,Q######)

Resources