Macro: How to replace text in files without crashing Visual Studio 2010?
-
Thursday, September 13, 2012 11:04 AM
I have written a simple macro that invokes the "Replace in Files" dialog in order to update version numbers in multiple *.rc and AssemblyInfo.cs files.
For simple Visual Studio solutions, this macro works fine.
For Visual Studio solutions with a large number of projects, Visual Studio 2010 crashes while executing the macro.
Does anyone know an alternative way to write the below macro? Maybe then I can avoid the Visual Studio crash.
This is the macro:
Sub ReplaceInFiles(ByVal findstr As String, ByVal replacestr As String, ByVal filepattern As String) DTE.ExecuteCommand("Edit.FindinFiles") DTE.ExecuteCommand("Edit.SwitchtoReplaceInFiles") DTE.Find.Action = vsFindAction.vsFindActionReplaceAll DTE.Find.FindWhat = findstr DTE.Find.ReplaceWith = replacestr DTE.Find.Target = vsFindTarget.vsFindTargetFiles DTE.Find.MatchCase = True DTE.Find.MatchWholeWord = False DTE.Find.MatchInHiddenText = True DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr DTE.Find.SearchPath = "Entire Solution" DTE.Find.SearchSubfolders = True DTE.Find.KeepModifiedDocumentsOpen = False DTE.Find.FilesOfType = filepattern DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResults1 If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then Throw New System.Exception("vsFindResultNotFound") End If DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Close() End Sub Sub UpdateVersionNumbers() ReplaceInFiles("FILEVERSION:b+[0-9,]+", "FILEVERSION 10,0,200,0", "*.rc") ReplaceInFiles("PRODUCTVERSION:b+[0-9,]+", "PRODUCTVERSION 10,0,200,0", "*.rc") ReplaceInFiles("VALUE ""FileVersion"",:b+""[0-9.]+""", "VALUE ""FileVersion"", ""10.0.200""", "*.rc") ReplaceInFiles("VALUE ""ProductVersion"",:b+""[0-9.]+""", "VALUE ""ProductVersion"", ""10.0.200""", "*.rc") ReplaceInFiles("^\[assembly\: AssemblyVersion\(""[0-9.]+""\)\]", "[assembly: AssemblyVersion(""10.0.100.0"")]", "assemblyinfo.cs") ReplaceInFiles("^\[assembly\: AssemblyFileVersion\(""[0-9.]+""\)\]", "[assembly: AssemblyFileVersion(""10.0.100.0"")]", "assemblyinfo.cs") End SubThe crash occurs here:
> msenv.dll!ReplaceInFiles() + 0x697 bytes
msenv.dll!CVsFindManager::FindReplace() + 0x1448 bytes
msenv.dll!CVsFindManager::DefaultFindReplace() + 0x37 bytes
msenv.dll!CVsFindManager::Execute() + 0x71 bytes
rpcrt4.dll!_Invoke @ 12() + 0x2a bytes
rpcrt4.dll!_NdrStubCall2 @ 16() + 0x256 bytes
ole32.dll!_CStdStubBuffer_Invoke @ 12() - 0x28b5 bytes
oleaut32.dll!CUnivStubWrapper::Invoke() + 0x36 bytesReason for the crash: Unhandled exception at 0x5e12a492 (msenv.dll) in devenv.exe: 0xC0000005: Access violation reading location 0x00000000.
- Edited by fmunkert Thursday, September 13, 2012 11:25 AM
All Replies
-
Thursday, September 13, 2012 8:37 PMModerator
A crash dump would be helpful, obviously a null ref is always a VS bug. I can set up an upload share for the crash dump if you can get one. All I would need to know is a geographic area (to minimize latency). Choices are:
1: North America2: EMEA (Europe and the Middle East)
3: AsiaRyan
-
Friday, September 14, 2012 6:34 AM
Hi Ryan,
it is "2. EMEA".
Regards
- Frank -
Monday, September 17, 2012 8:57 AMModerator
Hi Frank,
I will involve some experts into this issue to see whether they can help you out. There might be some time delay, appreciate for your patience.
Thank you for your understanding and support.
Best regards,Ego [MSFT]
MSDN Community Support | Feedback to us
-
Tuesday, September 18, 2012 5:06 PMModerator
Sorry for the delay, if you can shoot me an e-mail (rmolden AT <obvious company name here> . com) I can give you the upload link / password for the share.
Ryan
-
Wednesday, September 19, 2012 8:28 AM
Hi Ryan,
I have uploaded devenv_dmp.zip to the workspace.
Regards
- Frank -
Thursday, September 20, 2012 5:28 PMModerator
Thanks, the crash is interesting, it is hitting a null on a local variable (a pointer to a heap-allocated object), but immediately after allocating it ensures it is non-null (which can only happen if an OOM situation). There are many lines after its creation where it is used and you aren't null-refing there, so it implies it is non-null for some period of time.
I suspect the stack is being corrupted as there are no code paths that re-assign that local nor pass it by reference to any other function.
It does appear it is inside a block that deals with IVsQueryEditQuerySave::QueryEditFiles returning something other than QER_EditOK. When this happens it is attempting to hide the cancel dialog window, this is what is crashing.
IVsQueryEditQuerySave is an interaction point with source control, basically the IDE asking if it can makes edits to a file that is under source control. This appears to be being denied. Do you have source control active? If so is it a built in one (say TFS) or a third party one? Is it set up to allow automatic check-out or to prompt?
-
Friday, September 21, 2012 6:02 AM
Do you have source control active? If so is it a built in one (say TFS) or a third party one? Is it set up to allow automatic check-out or to prompt?
Yes, source control is active. We are using TFS.
Under "Tools | Options | Source Control | Environment", the drop-down lists "Saving" and "Editing" are set to "Check out automatically".
-
Friday, September 21, 2012 3:01 PMModerator
I looked in the internal bug database and this bug was previously filed. It appears there is a race condition between the foreground thread running the replace and the background threads that are doing the work per-file. In error cases it seems that the code that destroys the object that is null-reffing here does not wait for the background thread, which it has shared the object with, to terminate, so if it terminates without using the object again all is fine, if not, crash :( It has been fixed in 2012 but there is no known work around for 2010 that I can find / see.
- Marked As Answer by Ed DoreMicrosoft Employee, Moderator Wednesday, October 17, 2012 10:11 PM
-
Tuesday, September 25, 2012 9:09 PMModerator
Well, macros are gone in 2012 which sort or renders upgrading a non-option. However, if Frank is using Team Build, perhaps it would be better to update/modify those attributes during the build process.
It's a sincere pain in the backside to implement, as you can change up the build workflow. If memory servers, you'd need to monkey with the build name (so that it would auto-incremement), then parse out the version info from the build name, and have the workflow edit the file(s) before initiating the build.
To change up the values within the IDE, a package or addin would probably be best. I'm wondering if there might be an alternative to using DTE here, and whether that would avoid the bug. For example would using IVsFindHelper.FindInText avoid the issue?
Ed....
Ed Dore
- Proposed As Answer by Ed DoreMicrosoft Employee, Moderator Tuesday, September 25, 2012 9:09 PM

