Get functions in VS using macros - visual-studio

How to get all the functions you have in a code file in Visual Studio using VS macros?
I`m using Visual Studio 2008.
Also I need to get whether function is private protected or public. For now I know I can just parse the code and check it on my own, but I want to make it in a proper way and think vs macros environment should allow know all info about functions.

See HOWTO: Navigate the code elements of a file from a Visual Studio .NET macro or add-in
An maybe HOWTO: Navigate the files of a solution from a Visual Studio .NET macro or add-in would be interesting for you.
Getting function accessibility is easy. Following the first article, you have CodeElement object. If it is of type CodeFunction, you can cast it to CodeFunction (or also to CodeFunction2) type. The CodeFunction contains many properties including Access which is what you need. I have modified ShowCodeElement from this article so it only shows functions and also displays their accessibility:
Private Sub ShowCodeElement(ByVal objCodeElement As CodeElement)
Dim objCodeNamespace As EnvDTE.CodeNamespace
Dim objCodeType As EnvDTE.CodeType
Dim objCodeFunction As EnvDTE.CodeFunction
If TypeOf objCodeElement Is EnvDTE.CodeNamespace Then
objCodeNamespace = CType(objCodeElement, EnvDTE.CodeNamespace)
ShowCodeElements(objCodeNamespace.Members)
ElseIf TypeOf objCodeElement Is EnvDTE.CodeType Then
objCodeType = CType(objCodeElement, EnvDTE.CodeType)
ShowCodeElements(objCodeType.Members)
ElseIf TypeOf objCodeElement Is EnvDTE.CodeFunction Then
Try
Dim msg As String = objCodeElement.FullName & vbCrLf
Dim cd As EnvDTE.CodeFunction = DirectCast(objCodeElement, CodeFunction)
Select Case cd.Access
Case vsCMAccess.vsCMAccessDefault
msg &= "Not explicitly specified. It is Public in VB and private in C#."
Case Else
msg &= cd.Access.ToString
End Select
MsgBox(msg)
Catch ex As System.Exception
' Ignore
End Try
End If
End Sub
Change it and execute ShowFileCodeModel macro then.

Related

Launch debugger from VSIX and trigger method on project in current solution

I am trying to build a VSIX extension which Starts debugger in currently selected project and runs a method within that project.
I am able, using reflection to instantiate and call the method. However I would like my extension to start the debugger so that I can use breakpoints etc.
I have been able to build the projects by accessing the dte object, but cant see how I launch the debugger and run code.
foreach (Project project in dte.Solution.Projects)
{
dte.Solution.SolutionBuild.BuildProject("Debug", project.UniqueName);
}
I did something similar in the past. The code is in VB but it's very simple and you can easily convert it to C#.
Your code to build the project is OK. But if you have more Platforms available, such as "x86" and "Any CPU", the SolutionBuild.BuildProject takes a random platform. So it's better to explicitly specify it, like:
dte.Solution.SolutionBuild.BuildProject("Debug|Any CPU", project.UniqueName);
You can get the current configuration name and platform from:
Dim solutionConfiguration As SolutionConfiguration2 = CType(dte.Solution.SolutionBuild.ActiveConfiguration, SolutionConfiguration2)
Then you cannot start debugging particular method. DTE can only start to debug the startup object, e.g. Main. Exactly as if you press F5. If you want to start any particular method, it is more difficult.
You wrote, you can instantiate and call the method with reflection. This is OK. But remember, you cannot debug the process itself. This is how Windows works. It means, Visual Studio process can only debug ANOTHER process. So you cannot instantiate your compiled assembly in VSIX process (which is in fact a VS process).
You must create a new process and load your assembly in it. I don't have a code how to do it. Just for your information, the path of the compiled assembly can be retrieved like this:
Private Shared Function GetAssemblyPath(proj As EnvDTE.Project) As String
Dim fullPath As String = proj.Properties.Item("FullPath").Value.ToString()
Dim outputPath As String = proj.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString()
Dim outputDir As String = Path.Combine(fullPath, outputPath)
Dim outputFileName As String = proj.Properties.Item("OutputFileName").Value.ToString()
Dim assemblyPath As String = Path.Combine(outputDir, outputFileName)
Return assemblyPath
End Function
When you have the process and its ID, you must attach Visual Studio to this process:
Friend Sub AttachDebuggerToProcess(processId As Integer)
Dim dte As DTE2 = TryCast(Package.GetGlobalService(GetType(SDTE)), DTE2)
If dte Is Nothing Then
Return
End If
Dim proc As Process2 = Nothing
For Each process As Process In dte.Debugger.LocalProcesses
If process.ProcessID = processId Then
proc = process
Exit For
End If
Next
If proc Is Nothing Then
' report error
Return
End If
Try
If Not proc.IsBeingDebugged Then
proc.Attach()
End If
Catch exx As Exception
End Try
End Sub
And only now you can call your method with reflection. If there's a breakpoint set, it will be hit.

How can I detect an unmanaged C++ project in a visual studio extension

In my Visual Studio Extension, I need to detect whether a C++ project is managed or unmanaged code.
Previously, I had a satisfactory method, described in this posting in an MSDN forum.
In that example, it was necessary to get the ManagedExtensions property of the active configuration.
Sub Macro1()
Dim objProject As EnvDTE.Project
Dim objConfiguration As EnvDTE.Configuration
Dim objProperty As EnvDTE.Property
For Each objProject In DTE.Solution.Projects
objConfiguration = objProject.ConfigurationManager.ActiveConfiguration()
objProperty = objConfiguration.Properties.Item("ManagedExtensions")
System.Windows.Forms.MessageBox.Show(objProject.Name & " (" & objConfiguration.ConfigurationName & ") ManagedExtensions: " & objProperty.Value.ToString)
Next
End Sub
Unfortunately, this method is no longer working for me.
For unmanaged projects, I get an exception trying to fetch the ActiveConfiguration.
For managed projects, I can get the ActiveConfiguration, but the ManagedExtensions property is not available. In fact, I think that the properties collection is empty.
Is there a new way to recognize an unmanaged C++ project?
You can get the ManagedExtensions property via the VCConfiguration object, with code something like
Private Enum compileAsManagedOptions
managedNotSet = 0
managedAssembly = 1
managedAssemblyPure = 2
managedAssemblySafe = 3
managedAssemblyOldSyntax = 4
End Enum
Dim VCProj As Object 'VCProject
Dim VCConfig As Object 'VCConfiguration
Dim VCManagedOption As compileAsManagedOptions = compileAsManagedOptions.managedAssemblyPure
VCProj = prj.Object
If VCProj IsNot Nothing Then
VCConfig = VCProj.Configurations.Item(1)
If VCConfig IsNot Nothing Then
VCManagedOption = VCConfig.ManagedExtensions
End If
End If
where prj is the Envdte.Project object.
This code is only executed if I already know that it is a C++ project, based on the project kind.
I defined the variables as object, so that I don't have to add a reference to
Microsoft.VisualStudio.VCProject.dll
to my package, because this DLL will only be present if support for C++ projects has been installed.

Classic ASP Intellisense ADODB Visual Studio 2010

I am using Visual Studio to edit my classic asp web site and intellisense and colour coding works for most part, i.e. if I type "Response." then it pops up with a list of options.
However when I use a declared object type such as;
Set DB = Server.CreateObject("ADODB.Connection")
I no longer get intellisense options when I type "DB."
I used to get intellisense when using MicroSoft Interdev (blast from the past) to edit ASP files and it would be handy to get it back.
My question is therefore, does anyone know of a way with VS2010 (or later) in which I can re-enable intellisense for Server Created objects ?
Many thanks
Matt
I'm using VS2015 and it works for me, but the file must have an ASP extension. And it only works in direct scope of the Created object.
For example:
set command = CreateCommandWithParameters(Me.conn, parameterizedQuery, values)
Command.... 'no intellisense here because Server.CreateObject was called in a Function elsewhere
But I get intellisense below just fine.
Private Function CreateCommand(connection, query, commandType)
if (commandType <> adCmdText AND commandType <> adCmdTable AND commandType <> adCmdStoredProc AND commandType <> adCmdFile AND commandType <> adCmdTableDirect) then Err.Raise 16001, "Invalid Command Type", "Must be, adCmdText, adCmdTable, adCmdStoredProc, adCmdFile, adCmdTableDirect"
Set CreateCommand = Server.CreateObject("ADODB.Command")
Set CreateCommand.ActiveConnection = connection
CreateCommand.ActiveConnection = connection
CreateCommand.NamedParameters = true
CreateCommand.CommandText = query
CreateCommand.CommandType = commandType
CreateCommand.CommandTimeout = 120 '2 minutes....
CreateCommand.Prepared = true
End Function
It could also be because I have the TypeLib imported in the Global.asa
<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->
As a final note, while it does work on Server.CreateObject in some cases..... It does not work on user defined subs, classes, and functions...
I've basically just gotten use to not having intellisense. VBScript is not case sensitive so it hasn't bothered me to much.

VBA - User-defined type not defined

I am trying to update an VBA module to use the System.Windows.Forms.FolderBrowserDialog class. I declared my object as follows:
Dim MyFolderBrowser As New System.Windows.Forms.FolderBrowserDialog
Running this gave me the error User-defined type not defined. I figured the compiler didn't know about that class so I tried going to Tools > References and adding Systems_Windows_Forms, but I'm still getting the same error. Does anyone know what I'm missing here? Do I need a reference to the library in my code as well?
System.Windows.Forms.FolderBrowserDialog looks like something from .Net to me, not VBA.
You can use Application.FileDialog in Access VBA. This sample uses late binding and allows the user to select a folder from a browse dialog.
Const msoFileDialogFolderPicker As Long = 4
Dim objFileDialog As Object ' FileDialog
Set objFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
With objFileDialog
.AllowMultiSelect = False
If .Show Then
Debug.Print .SelectedItems(1)
End If
End With
If you prefer to use early binding, set a reference to the Microsoft Office [version] Object Library. You could then declare the object like this ...
Dim objFileDialog As FileDialog
And you wouldn't need to define the constant, so discard this line if using early binding ...
Const msoFileDialogFolderPicker As Long = 4

Add item to Error List in Macro

I want to notify the user of the macro if something went wrong during the execution of the macro. I was wondering if it would be possible to add an item to the Visual Studio error list?
It is possible to do so from within an AddIn (like here), but I would like to do the same thing from a macro.
Edit
To further clarify what i want to achive, here is the sample from the Samples macro library (Alt+F8 -> Samples -> Utilities -> SaveView())
Sub SaveView()
Dim name As String
name = InputBox("Enter the name you want to save as:", "Save window layout")
If (name = "") Then
MsgBox("Empty string, enter a valid name.")
Else
DTE.WindowConfigurations.Add(name)
End If
End Sub
Instead of the MsgBox("...") alert I want to put the error into the VS error list.
You can add an item in the Task List easily from your macro. Just use the AddTaskToList method from that article and change m_objDTE to DTE. I've tried it and it worked.
However, adding the item in Error List, is probably impossible. You need to call VS services, see how adding an error is done in an add-in. I created a macro from this code and it didn't work. In general, VS services don't work in macros. I was able to create ErrorListProvider successfully. I could access it's methods and properties. But calling ErrorListProvider.Task.Add caused COM exception. If you want to play with it, several notes:
As described in the article, you need to get 4 assemblies out of the GAC e.g. to c:\dlls\ directory. Since Macros IDE doesn't allow you to browse when you Add Reference, you need to copy these dlls into ...\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies directory (change the 10.0 to your VS version). Then, when you Add Reference in Macros IDE, you should see the assemblies.
The GetService function always returned Nothing. Add the following field to the class:
Private serviceProvider As IServiceProvider = New Microsoft.VisualStudio.Shell.ServiceProvider(CType(DTE, Microsoft.VisualStudio.OLE.Interop.IServiceProvider))
and in GetService function change line:
objService = Microsoft.VisualStudio.Shell.Package.GetGlobalService(serviceType)
to
objService = serviceProvider.GetService(serviceType)
As I wrote, everything seems OK then but ErrorListProvider.Task.Add fails.
I think that for your situation outputting something to your own output pane would be more suitable. The error list is generally used for errors within the project the user is working on, not for errors caused by running macros. Especially when someone says it can't be done. :)
Outputting to your own output pane is pretty easy:
DTE.Windows.Item(Constants.vsWindowKindOutput).Activate()
Dim panes As OutputWindowPanes = window.OutputWindowPanes
Dim my_pane As OutputWindowPane
Try
my_pane = panes.Item("SaveView")
Catch exception As System.ArgumentException
my_pane = panes.Add("SaveView")
End Try
my_pane.Activate()
my_pane.OutputString("Empty string, enter a valid name." + vbCrLf)
Hope this helps.
Cheers,
Sebastiaan
Is this not what you want?
HOWTO: Add an error with navigation to the Error List from a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008022.aspx

Resources