├── .gitattributes ├── .gitignore ├── LICENSE.md ├── Microsoft.InteropFormTools.InteropFormProxyGenerator.sln ├── Microsoft.InteropFormTools.InteropFormProxyGenerator ├── GenerateInteropFormProxyClasses.vb ├── GenerateInteropFormProxyClassesPackage.vb ├── GenerateInteropFormProxyClassesPackage.vsct ├── Key.snk ├── Microsoft.InteropFormTools.InteropFormProxyGenerator.vbproj ├── My Project │ ├── AssemblyInfo.vb │ ├── Resources.Designer.vb │ └── Resources.resx ├── Resources │ ├── GenerateInteropFormProxyClasses.png │ └── GenerateInteropFormProxyClassesPackage.ico ├── VSPackage.resx ├── index.html ├── source.extension.vsixmanifest └── stylesheet.css ├── ReadMe.md └── VSIXProject1 ├── My Project └── AssemblyInfo.vb ├── VSIXProject1.vbproj ├── VSIXProject1Package.vb └── source.extension.vsixmanifest /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Windows Azure Build Output 155 | csx/ 156 | *.build.csdef 157 | 158 | # Windows Azure Emulator 159 | efc/ 160 | rfc/ 161 | 162 | # Windows Store app package directory 163 | AppPackages/ 164 | 165 | # Visual Studio cache files 166 | # files ending in .cache can be ignored 167 | *.[Cc]ache 168 | # but keep track of directories ending in .cache 169 | !*.[Cc]ache/ 170 | 171 | # Others 172 | ClientBin/ 173 | [Ss]tyle[Cc]op.* 174 | ~$* 175 | *~ 176 | *.dbmdl 177 | *.dbproj.schemaview 178 | *.pfx 179 | *.publishsettings 180 | node_modules/ 181 | orleans.codegen.cs 182 | 183 | # RIA/Silverlight projects 184 | Generated_Code/ 185 | 186 | # Backup & report files from converting an old project file 187 | # to a newer Visual Studio version. Backup files are not needed, 188 | # because we have git ;-) 189 | _UpgradeReport_Files/ 190 | Backup*/ 191 | UpgradeLog*.XML 192 | UpgradeLog*.htm 193 | 194 | # SQL Server files 195 | *.mdf 196 | *.ldf 197 | 198 | # Business Intelligence projects 199 | *.rdl.data 200 | *.bim.layout 201 | *.bim_*.settings 202 | 203 | # Microsoft Fakes 204 | FakesAssemblies/ 205 | 206 | # GhostDoc plugin setting file 207 | *.GhostDoc.xml 208 | 209 | # Node.js Tools for Visual Studio 210 | .ntvs_analysis.dat 211 | 212 | # Visual Studio 6 build log 213 | *.plg 214 | 215 | # Visual Studio 6 workspace options file 216 | *.opt 217 | 218 | # Visual Studio LightSwitch build output 219 | **/*.HTMLClient/GeneratedArtifacts 220 | **/*.DesktopClient/GeneratedArtifacts 221 | **/*.DesktopClient/ModelManifest.xml 222 | **/*.Server/GeneratedArtifacts 223 | **/*.Server/ModelManifest.xml 224 | _Pvt_Extensions 225 | 226 | # Paket dependency manager 227 | .paket/paket.exe 228 | 229 | # FAKE - F# Make 230 | .fake/ 231 | 232 | # ========================= 233 | # Operating System Files 234 | # ========================= 235 | 236 | # OSX 237 | # ========================= 238 | 239 | .DS_Store 240 | .AppleDouble 241 | .LSOverride 242 | 243 | # Thumbnails 244 | ._* 245 | 246 | # Files that might appear in the root of a volume 247 | .DocumentRevisions-V100 248 | .fseventsd 249 | .Spotlight-V100 250 | .TemporaryItems 251 | .Trashes 252 | .VolumeIcon.icns 253 | 254 | # Directories potentially created on remote AFP share 255 | .AppleDB 256 | .AppleDesktop 257 | Network Trash Folder 258 | Temporary Items 259 | .apdisk 260 | 261 | # Windows 262 | # ========================= 263 | 264 | # Windows image file caches 265 | Thumbs.db 266 | ehthumbs.db 267 | 268 | # Folder config file 269 | Desktop.ini 270 | 271 | # Recycle Bin used on file shares 272 | $RECYCLE.BIN/ 273 | 274 | # Windows Installer files 275 | *.cab 276 | *.msi 277 | *.msm 278 | *.msp 279 | 280 | # Windows shortcuts 281 | *.lnk 282 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Don Benson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35506.116 d17.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Microsoft.InteropFormTools.InteropFormProxyGenerator", "Microsoft.InteropFormTools.InteropFormProxyGenerator\Microsoft.InteropFormTools.InteropFormProxyGenerator.vbproj", "{5917F213-ECA0-43FE-81F0-444A48D4CC8F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5917F213-ECA0-43FE-81F0-444A48D4CC8F}.Debug|x64.ActiveCfg = Debug|x64 15 | {5917F213-ECA0-43FE-81F0-444A48D4CC8F}.Debug|x64.Build.0 = Debug|x64 16 | {5917F213-ECA0-43FE-81F0-444A48D4CC8F}.Release|x64.ActiveCfg = Release|x64 17 | {5917F213-ECA0-43FE-81F0-444A48D4CC8F}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/GenerateInteropFormProxyClasses.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.ComponentModel.Design 3 | Imports System.Windows.Forms 4 | Imports System.Collections.Generic 5 | Imports System.IO 6 | Imports System.CodeDom 7 | Imports System.CodeDom.Compiler 8 | Imports Microsoft.VisualBasic 9 | Imports Microsoft.VisualStudio.Shell 10 | Imports EnvDTE 11 | Imports EnvDTE80 12 | 13 | 14 | ''' 15 | ''' Command handler 16 | ''' 17 | Public NotInheritable Class GenerateInteropFormProxyClasses 18 | #Region " Template Generated Code - With mods " 19 | ''' 20 | ''' Command ID. 21 | ''' 22 | Public Const CommandId As Integer = 256 23 | 24 | ''' 25 | ''' Command menu group (command set GUID). 26 | ''' 27 | Public Shared ReadOnly CommandSet As New Guid("28d23e01-258c-44b9-9581-a4581c49aeaa") 28 | 29 | ''' 30 | ''' VS Package that provides this command, not null. 31 | ''' 32 | Private ReadOnly package As Package 33 | 34 | ''' 35 | ''' Initializes a new instance of the class. 36 | ''' Adds our command handlers for menu (the commands must exist in the command table file) 37 | ''' 38 | ''' Owner package, not null. 39 | Private Sub New(package As Package) 40 | If package Is Nothing Then 41 | Throw New ArgumentNullException("package") 42 | End If 43 | 44 | Me.package = package 45 | Dim commandService As OleMenuCommandService = Me.ServiceProvider.GetService(GetType(IMenuCommandService)) 46 | If commandService IsNot Nothing Then 47 | Dim menuCommandId = New CommandID(CommandSet, CommandId) 48 | ' Using a an OLE command so we can dynamically set the text to a localized value. 49 | Dim menuCommand = New MenuCommand(AddressOf Me.MenuItemCallback, menuCommandId) 50 | commandService.AddCommand(menuCommand) 51 | End If 52 | 53 | Try 54 | _applicationObject = Package.GetGlobalService(GetType(DTE)) 55 | LoadSupportedTypes() 56 | Catch 57 | DisplayError(My.Resources.LoadSupportedTypesErrMsg) 58 | End Try 59 | End Sub 60 | 61 | ''' 62 | ''' Gets the instance of the command. 63 | ''' 64 | Public Shared Property Instance As GenerateInteropFormProxyClasses 65 | 66 | ''' 67 | ''' Get service provider from the owner package. 68 | ''' 69 | Private ReadOnly Property ServiceProvider As IServiceProvider 70 | Get 71 | Return Me.package 72 | End Get 73 | End Property 74 | 75 | ''' 76 | ''' Initializes the singleton instance of the command. 77 | ''' 78 | ''' Owner package, Not null. 79 | Public Shared Sub Initialize(package As Package) 80 | Instance = New GenerateInteropFormProxyClasses(package) 81 | End Sub 82 | 83 | ''' 84 | ''' This function is the callback used to execute the command when the menu item is clicked. 85 | ''' See the constructor to see how the menu item is associated with this function using 86 | ''' OleMenuCommandService service and MenuCommand class. 87 | ''' 88 | ''' Event sender. 89 | ''' Event args. 90 | Private Sub MenuItemCallback(sender As Object, e As EventArgs) 91 | CreateInteropFormProxiesForSolution() 92 | If Not m_blnProxiesGenerated Then 93 | DisplayError(My.Resources.ADDIN_STATUS_NONE_GENERATED_OK) 94 | End If 95 | End Sub 96 | #End Region 97 | 98 | #Region " Private Constants " 99 | Private DISPLAY_CAPTION As String = My.Resources.DISPLAY_CAPTION 100 | Private DOCUMENT_TYPE As String = My.Resources.DOCUMENT_TYPE 101 | Private FOLDER_TYPE As String = My.Resources.FOLDER_TYPE 102 | Private INTEROP_FORM_PROXY_FOLDER_NAME As String = My.Resources.INTEROP_FORM_PROXY_FOLDER_NAME 103 | 104 | Private EVENT_ARGS_COMMENT As String = String.Format("{0}{1}{2}{3}{4}", My.Resources.EVENT_ARGS_COMMENT1, vbNewLine, My.Resources.EVENT_ARGS_COMMENT2, vbNewLine, My.Resources.EVENT_ARGS_COMMENT3) 105 | #End Region 106 | 107 | #Region " Private Variables " 108 | Dim _applicationObject As DTE2 109 | 110 | Dim _attrTypeForm As Type = GetType(InteropFormAttribute) 111 | Dim _attrTypeInitializer As Type = GetType(InteropFormInitializerAttribute) 112 | Dim _attrTypeMethod As Type = GetType(InteropFormMethodAttribute) 113 | Dim _attrTypeProperty As Type = GetType(InteropFormPropertyAttribute) 114 | Dim _attrTypeEvent As Type = GetType(InteropFormEventAttribute) 115 | 116 | Dim _supportedTypes As List(Of Type) = Nothing 117 | #End Region 118 | 119 | #Region " Private Methods " 120 | Private Sub LoadSupportedTypes() 121 | ' Load list of types that are allowed to be used in members. 122 | _supportedTypes = New List(Of Type) From { 123 | GetType(Integer), 124 | GetType(String), 125 | GetType(Boolean), 126 | GetType(Object) 127 | } 128 | End Sub 129 | 130 | Private m_blnProxiesGenerated As Boolean 131 | Private Sub CreateInteropFormProxiesForSolution() 132 | _applicationObject.StatusBar.Text = My.Resources.ADDIN_STATUS_GENERATING 133 | m_blnProxiesGenerated = False 134 | 135 | For Each assemblyProj As Project In _applicationObject.Solution.Projects 136 | If assemblyProj.ProjectItems IsNot Nothing AndAlso (assemblyProj.ProjectItems.Count > 0) Then 137 | CreateInteropFormProxiesForProject(assemblyProj, assemblyProj.ProjectItems) 138 | End If 139 | Next 140 | 141 | If m_blnProxiesGenerated Then 142 | _applicationObject.StatusBar.Text = My.Resources.ADDIN_STATUS_GENERATED_OK 143 | Else 144 | _applicationObject.StatusBar.Text = My.Resources.ADDIN_STATUS_NONE_GENERATED_OK 145 | End If 146 | End Sub 147 | 148 | Private Sub CreateInteropFormProxiesForProject(ByVal currentAssembly As Project, ByVal projItemCollection As ProjectItems) 149 | For Each projItem As ProjectItem In projItemCollection 150 | Try 151 | If projItem.Kind = DOCUMENT_TYPE AndAlso projItem.FileCodeModel IsNot Nothing Then 152 | ' this is a code document so search for InteropForm classes 153 | Dim interopFormClasses As List(Of CodeClass) = GetInteropFormClasses(currentAssembly, projItem) 154 | ' create file of wrapper classes for the InteropForm classes found in this document 155 | CreateInteropFormProxiesForDocument(interopFormClasses, currentAssembly, projItem) 156 | ElseIf projItem.ProjectItems IsNot Nothing AndAlso (projItem.ProjectItems.Count > 0) Then 157 | ' Not a document. It has sub items, though so search 158 | CreateInteropFormProxiesForProject(currentAssembly, projItem.ProjectItems) 159 | End If 160 | Catch ex As Exception 161 | ' Catch here so that other projects will work and you'll know which project failed 162 | Dim errMsg As String = My.Resources.ADDIN_STATUS_GENERATED_ERROR1 163 | If currentAssembly IsNot Nothing AndAlso currentAssembly.Name IsNot Nothing Then 164 | errMsg &= String.Format(My.Resources.ADDIN_STATUS_GENERATED_ERROR2, currentAssembly.Name) 165 | End If 166 | DisplayError(String.Format(My.Resources.ADDIN_STATUS_GENERATED_ERROR_FULL, currentAssembly.Name)) 167 | End Try 168 | Next 169 | End Sub 170 | 171 | Private Sub CreateInteropFormProxiesForDocument(ByVal interopFormClasses As List(Of CodeClass), ByVal currentAssembly As Project, ByVal interopFormDoc As ProjectItem) 172 | If interopFormClasses.Count <= 0 Then 173 | Return 174 | End If 175 | 176 | Dim interopFormFileInfo As New FileInfo(interopFormDoc.FileNames(0)) 177 | Dim proxyFolderInfo As New DirectoryInfo(interopFormFileInfo.DirectoryName & "\" & INTEROP_FORM_PROXY_FOLDER_NAME) 178 | 179 | ' check if folder is already part of the project 180 | Dim proxyfolderItem As ProjectItem = Nothing 181 | For Each level1Item As ProjectItem In currentAssembly.ProjectItems 182 | If level1Item.Kind = FOLDER_TYPE AndAlso level1Item.Name = INTEROP_FORM_PROXY_FOLDER_NAME Then 183 | proxyfolderItem = level1Item 184 | Exit For 185 | End If 186 | Next 187 | 188 | ' create folder if it doesn't already exist 189 | If proxyfolderItem Is Nothing Then 190 | If Not proxyFolderInfo.Exists Then 191 | 'proxyFolderInfo.Create() 192 | proxyfolderItem = currentAssembly.ProjectItems.AddFolder(proxyFolderInfo.Name) 193 | Else 194 | ' todo: better way to add the existing folder instead of deleting first 195 | ' todo: fix this because it doesn't always work - item is out of synch? 196 | proxyFolderInfo.Delete(True) 197 | 'proxyFolderInfo.Refresh() 198 | 'proxyFolderInfo.Create() 199 | 'proxyFolderInfo.Refresh() 200 | proxyfolderItem = currentAssembly.ProjectItems.AddFolder(proxyFolderInfo.Name) 201 | End If 202 | End If 203 | 204 | ' create proxy file info 205 | Dim proxyFilePath As String = proxyFolderInfo.FullName & "\" & interopFormFileInfo.Name.Replace(interopFormFileInfo.Extension, ".wrapper" & interopFormFileInfo.Extension) 206 | Dim proxyFileInfo As New FileInfo(proxyFilePath) 207 | Dim proxyFileItem As ProjectItem 208 | For Each doc As ProjectItem In proxyfolderItem.ProjectItems 209 | If doc.Kind = DOCUMENT_TYPE AndAlso doc.Name = proxyFileInfo.Name Then 210 | proxyFileItem = doc 211 | If currentAssembly.DTE.SourceControl.IsItemUnderSCC(proxyFilePath) Then 212 | If Not doc.Collection.ContainingProject.DTE.SourceControl.IsItemCheckedOut(proxyFilePath) Then 213 | doc.Collection.ContainingProject.DTE.SourceControl.CheckOutItem(proxyFilePath) 214 | End If 215 | End If 216 | Exit For 217 | End If 218 | Next 219 | 220 | ' wipe out the old file if it exists 221 | If proxyFileInfo.Exists Then 222 | proxyFileInfo.Delete() 223 | End If 224 | 225 | Dim code As New CodeCompileUnit() 226 | ' Import the InteropTools namespace 227 | Dim nsImport As New CodeDom.CodeNamespaceImport(_attrTypeForm.Namespace) 228 | 229 | ' Build within that a new sub namespace called Interop 230 | ' So if the Form class is MyCompany.HelloWorld 231 | ' the proxy class is MyCompany.HelloWorld.Interop. 232 | ' Since the former is not exposed to COM, VB6 233 | ' code doesn't need to qualify the namespace so 234 | ' the name will look the same. 235 | Dim ns As New CodeDom.CodeNamespace 236 | ns.Name = "Interop" 237 | code.Namespaces.Add(ns) 238 | ns.Imports.Add(nsImport) 239 | 240 | For Each interopFormClass As CodeClass In interopFormClasses 241 | 242 | Dim interopFormClassName As String = interopFormClass.FullName 243 | Dim proxyClassName As String = interopFormClass.Name 244 | 245 | ' create the proxy class and add it to the namespace 246 | Dim proxyClass As New CodeTypeDeclaration(proxyClassName) 247 | ns.Types.Add(proxyClass) 248 | proxyClass.IsClass = True 249 | proxyClass.IsPartial = True 250 | Dim trueEx As New CodePrimitiveExpression(True) 251 | Dim aDual As New CodeSnippetExpression("Runtime.InteropServices.ClassInterfaceType.AutoDual") 252 | proxyClass.CustomAttributes.Add(New CodeAttributeDeclaration("System.Runtime.InteropServices.ClassInterface", New CodeDom.CodeAttributeArgument() {New CodeDom.CodeAttributeArgument(aDual)})) 253 | ' todo: is autodual right way? Or should an explicit interface be generated? 254 | proxyClass.CustomAttributes.Add(New CodeAttributeDeclaration("System.Runtime.InteropServices.ComVisible", New CodeDom.CodeAttributeArgument() {New CodeDom.CodeAttributeArgument(trueEx)})) 255 | proxyClass.BaseTypes.Add(New CodeTypeReference(GetType(InteropFormProxyBase).Name)) 256 | 257 | ' create the event sink interface. wait to add it to the namespace only if events exist 258 | Dim proxyClassEventSinkInterface As New CodeTypeDeclaration("I" & proxyClass.Name & "EventSink") 259 | proxyClassEventSinkInterface.CustomAttributes.Add(New CodeAttributeDeclaration("System.Runtime.InteropServices.InterfaceTypeAttribute", New CodeDom.CodeAttributeArgument() {New CodeDom.CodeAttributeArgument(New CodeSnippetExpression("System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch"))})) 260 | proxyClassEventSinkInterface.CustomAttributes.Add(New CodeAttributeDeclaration("System.Runtime.InteropServices.ComVisible", New CodeDom.CodeAttributeArgument() {New CodeDom.CodeAttributeArgument(trueEx)})) 261 | proxyClassEventSinkInterface.IsInterface = True 262 | 263 | Dim defaultCtor As New CodeDom.CodeConstructor() 264 | Dim ctorLine1 As New CodeSnippetStatement(" FormInstance = New " & interopFormClassName & "()") 265 | Dim ctorLine2 As New CodeSnippetStatement(" RegisterFormInstance()") 266 | 267 | defaultCtor.Statements.Add(ctorLine1) 268 | defaultCtor.Statements.Add(ctorLine2) 269 | defaultCtor.Attributes = MemberAttributes.Public 270 | proxyClass.Members.Add(defaultCtor) 271 | 272 | ' check the members of the interop form class for attributes 273 | ' and generate members in the proxy accordingly 274 | If interopFormClass.Members.Count > 0 Then 275 | For Each member As CodeElement In interopFormClass.Members 276 | ' check for constructors to make Initialize methods for 277 | If member.Kind = vsCMElement.vsCMElementFunction Then 278 | ' cast as function object 279 | Dim method As CodeFunction2 = CType(member, CodeFunction2) 280 | If method.Access = vsCMAccess.vsCMAccessPublic Then 281 | For Each custAtt As CodeElement In method.Attributes 282 | If AttributesMatch(custAtt, _attrTypeInitializer) Then 283 | ' this method is a constructor and 284 | ' has been decorated to indicate it should 285 | ' be exposed via the proxy class 286 | AddInitializeMethodForConstructor(proxyClass, interopFormClass, method) 287 | Exit For 288 | ElseIf AttributesMatch(custAtt, _attrTypeMethod) Then 289 | ' this method is a non-constructor method and 290 | ' has been decorated to indicate it should 291 | ' be exposed via the proxy class 292 | AddMethod(proxyClass, interopFormClass, method) 293 | Exit For 294 | End If 295 | Next 296 | End If 297 | ElseIf member.Kind = vsCMElement.vsCMElementProperty Then 298 | ' cast as property object 299 | Dim prop As CodeProperty2 = CType(member, CodeProperty2) 300 | If prop.Access = vsCMAccess.vsCMAccessPublic Then 301 | 302 | For Each custAtt As CodeElement In prop.Attributes 303 | If AttributesMatch(custAtt, _attrTypeProperty) Then 304 | ' this method is a property and 305 | ' has been decorated to indicate it should 306 | ' be exposed via the proxy class 307 | AddProperty(proxyClass, interopFormClass, prop) 308 | Exit For 309 | End If 310 | Next 311 | End If 312 | ElseIf member.Kind = vsCMElement.vsCMElementEvent Then 313 | Dim evt As CodeEvent = CType(member, CodeEvent) 314 | If evt.Access = vsCMAccess.vsCMAccessPublic Then 315 | For Each custAtt As CodeElement In evt.Attributes 316 | If AttributesMatch(custAtt, _attrTypeEvent) Then 317 | ' this method is a property and 318 | ' has been decorated to indicate it should 319 | ' be exposed via the proxy class 320 | AddEvent(currentAssembly, proxyClass, interopFormClass, evt, proxyClassEventSinkInterface) 321 | Exit For 322 | End If 323 | Next 324 | End If 325 | End If 326 | Next 327 | End If 328 | 329 | ' only add the event sink if the interface was built out (i.e. the class has events) 330 | If proxyClassEventSinkInterface.Members.Count > 0 Then 331 | ns.Types.Add(proxyClassEventSinkInterface) 332 | proxyClass.CustomAttributes.Add(New CodeAttributeDeclaration("System.Runtime.InteropServices.ComSourceInterfaces", New CodeDom.CodeAttributeArgument() {New CodeDom.CodeAttributeArgument(New CodeDom.CodeTypeOfExpression(proxyClassEventSinkInterface.Name))})) 333 | End If 334 | 335 | Next 336 | 337 | Dim fsw As New System.IO.StreamWriter(proxyFileInfo.Create()) 338 | fsw.AutoFlush = True 339 | 340 | Dim vb As New VBCodeProvider() 341 | 342 | Dim options As New CodeGeneratorOptions() 343 | 'options("AllowLateBound") = "True" 344 | 'options("RequireVariableDeclaration") = "True" 345 | 'code.UserData.Add("AllowLateBound", True) 346 | 'code.UserData.Add("RequireVariableDeclaration", True) 347 | 348 | vb.GenerateCodeFromCompileUnit(code, fsw, options) 349 | 350 | ' Close the stream 351 | fsw.Close() 352 | fsw.Dispose() 353 | 354 | proxyfolderItem.ProjectItems.AddFromFile(proxyFileInfo.FullName) 355 | 356 | 'Yes, we've generated a proxy 357 | m_blnProxiesGenerated = True 358 | End Sub 359 | 360 | Private Function GetInteropFormClasses(ByVal assemblyProj As Project, ByVal projItem As ProjectItem) As List(Of CodeClass) 361 | ' Create list to hold the interopForm classes we find 362 | Dim interopFormClasses As New List(Of CodeClass) 363 | 364 | If projItem.FileCodeModel IsNot Nothing Then 365 | FindInteropFormClasses(assemblyProj, projItem.FileCodeModel.CodeElements, interopFormClasses) 366 | End If 367 | 368 | Return interopFormClasses 369 | End Function 370 | 371 | Private Sub FindInteropFormClasses(ByVal currentAssembly As Project, ByVal codeElements As CodeElements, ByVal interopFormClasses As List(Of CodeClass)) 372 | ' safety check 373 | If codeElements Is Nothing Then 374 | Exit Sub 375 | End If 376 | 377 | ' todo: faster/cleaner way to find? 378 | For Each ce As CodeElement In codeElements 379 | If ce.Kind = vsCMElement.vsCMElementAttribute AndAlso AttributesMatch(ce, _attrTypeForm) Then 380 | ' found an InteropForm attribute so add it to the list 381 | Dim interopFormClass As CodeClass = CType(codeElements.Parent, CodeClass) 382 | interopFormClasses.Add(interopFormClass) 383 | End If 384 | If ce.Children.Count > 0 Then 385 | FindInteropFormClasses(currentAssembly, ce.Children, interopFormClasses) 386 | End If 387 | Next 388 | End Sub 389 | 390 | Private Sub AddInitializeMethodForConstructor(ByVal proxyClass As CodeTypeDeclaration, ByVal interopFormClass As CodeClass, ByVal method As CodeFunction) 391 | Dim initMethod As New CodeMemberMethod() 392 | initMethod.Name = "Initialize" 393 | initMethod.Attributes = MemberAttributes.Public 394 | initMethod.CustomAttributes.Add(New CodeAttributeDeclaration("System.Diagnostics.DebuggerStepThrough")) 395 | Dim stmt As String = " FormInstance = New " & interopFormClass.FullName & "(" 396 | Dim addComma As Boolean = False 397 | For Each pOld As CodeParameter2 In method.Parameters 398 | ' check against list of supported types 399 | If Not IsSupported(pOld.Type) Then 400 | DisplayWarning(String.Format(My.Resources.InitMethodErrMsg, pOld.Type.AsFullName, pOld.Name, pOld.Type.AsFullName)) 401 | Exit Sub 402 | End If 403 | Dim pNew As New CodeParameterDeclarationExpression(pOld.Type.AsFullName, pOld.Name) 404 | pNew.Direction = GetParamDirection(pOld) 405 | initMethod.Parameters.Add(pNew) 406 | If addComma Then 407 | stmt &= ", " 408 | End If 409 | stmt &= pOld.Name 410 | addComma = True 411 | Next 412 | stmt &= ")" 413 | initMethod.Statements.Add(New CodeSnippetStatement(" UnregisterFormInstance()")) 414 | initMethod.Statements.Add(New CodeSnippetStatement(stmt)) 415 | initMethod.Statements.Add(New CodeSnippetStatement(" RegisterFormInstance()")) 416 | proxyClass.Members.Add(initMethod) 417 | End Sub 418 | 419 | Private Sub DisplayError(ByVal errorMessage As String) 420 | MessageBox.Show(errorMessage, DISPLAY_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 421 | End Sub 422 | 423 | Private Sub DisplayWarning(ByVal errorMessage As String) 424 | MessageBox.Show(errorMessage, DISPLAY_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning) 425 | End Sub 426 | 427 | Private Function AttributesMatch(ByVal ce As CodeElement, ByVal attrType As Type) As Boolean 428 | Dim isMatch As Boolean = False 429 | Dim ceName As String = "" 430 | Dim staticName As String = "" 431 | 432 | 'try matching name in CodeElement to actual type name 433 | 'matching is case insensitive 434 | If ce IsNot Nothing Then 435 | 'try matching using partial name of the class, e.g. InteropFormAttribute Or InteropForm 436 | If (ce.Name IsNot Nothing) AndAlso (ce.Name <> "") Then 437 | ceName = ce.Name 438 | isMatch = (ceName.ToLower = attrType.Name.ToLower) OrElse (ceName.ToLower = attrType.Name.Replace("Attribute", "").ToLower) 439 | End If 440 | 441 | 'next, try matching using full name of the class, e.g. Microsoft.InteropFormsToolkit.InteropFormAttribute Or *.InteropForm 442 | If (isMatch = False) AndAlso (ce.FullName IsNot Nothing) AndAlso (ce.FullName <> "") Then 443 | ceName = ce.FullName 444 | isMatch = (ceName.ToLower = attrType.FullName.ToLower) OrElse (ceName.ToLower = attrType.FullName.Replace("Attribute", "").ToLower) 445 | End If 446 | End If 447 | 448 | Return isMatch 449 | End Function 450 | 451 | Private Sub AddMethod(ByVal proxyClass As CodeTypeDeclaration, ByVal interopFormClass As CodeClass, ByVal method As CodeFunction) 452 | Dim proxyMethod As New CodeMemberMethod() 453 | proxyMethod.Name = method.Name 454 | proxyMethod.Attributes = MemberAttributes.Public 455 | Dim trueEx As New CodePrimitiveExpression(True) 456 | proxyMethod.CustomAttributes.Add(New CodeAttributeDeclaration("System.Diagnostics.DebuggerStepThrough")) 457 | proxyMethod.Statements.Add(GetCastFormInstanceStatement(interopFormClass)) 458 | Dim stmt As String 459 | If method.FunctionKind = vsCMFunction.vsCMFunctionFunction Then 460 | If Not IsSupported(method.Type) Then 461 | DisplayWarning(String.Format(My.Resources.MethodErrMsg1, method.Type.AsFullName, method.Name)) 462 | Exit Sub 463 | End If 464 | 465 | proxyMethod.ReturnType = New CodeTypeReference(method.Type.AsFullName) 466 | stmt = " Return " 467 | Else 468 | stmt = " " 469 | End If 470 | stmt &= "castFormInstance." & method.Name & "(" 471 | Dim addComma As Boolean = False 472 | For Each pOld As CodeParameter2 In method.Parameters 473 | ' check against list of supported types 474 | If Not IsSupported(pOld.Type) Then 475 | DisplayWarning(String.Format(My.Resources.MethodErrMsg2, pOld.Type.AsFullName, method.Name)) 476 | Exit Sub 477 | End If 478 | Dim pNew As New CodeParameterDeclarationExpression(pOld.Type.AsFullName, pOld.Name) 479 | pNew.Direction = GetParamDirection(pOld) 480 | proxyMethod.Parameters.Add(pNew) 481 | If addComma Then 482 | stmt &= ", " 483 | End If 484 | stmt &= pOld.Name 485 | addComma = True 486 | Next 487 | stmt &= ")" 488 | proxyMethod.Statements.Add(New CodeSnippetStatement(stmt)) 489 | proxyClass.Members.Add(proxyMethod) 490 | End Sub 491 | 492 | Private Sub AddProperty(ByVal proxyClass As CodeTypeDeclaration, ByVal interopFormClass As CodeClass, ByVal prop As CodeProperty2) 493 | Dim proxyProp As New CodeMemberProperty 494 | proxyProp.Name = prop.Name 495 | proxyProp.Attributes = MemberAttributes.Public 496 | proxyProp.Type = New CodeTypeReference(prop.Type.AsFullName) 497 | 498 | ' check against list of supported types 499 | If Not IsSupported(prop.Type) Then 500 | DisplayWarning(String.Format(My.Resources.PropertyErrMsg, prop.Type.AsFullName, proxyProp.Name)) 501 | Exit Sub 502 | End If 503 | 504 | ' check for any parameters 505 | If prop.Parameters.Count > 0 Then 506 | DisplayWarning(String.Format(My.Resources.ParamPropertyErrMsg, proxyProp.Name)) 507 | Exit Sub 508 | End If 509 | 510 | ' if there is a getter, create the getter for the proxy 511 | If prop.Getter IsNot Nothing Then 512 | proxyProp.HasGet = True 513 | proxyProp.GetStatements.Add(GetCastFormInstanceStatement(interopFormClass)) 514 | proxyProp.GetStatements.Add(New CodeMethodReturnStatement(New CodePropertyReferenceExpression(New CodeVariableReferenceExpression("castFormInstance"), prop.Name))) 515 | End If 516 | 517 | ' if there is a setter, create the setter for the proxy 518 | If prop.Setter IsNot Nothing Then 519 | proxyProp.HasSet = True 520 | proxyProp.SetStatements.Add(GetCastFormInstanceStatement(interopFormClass)) 521 | proxyProp.SetStatements.Add(New CodeAssignStatement(New CodePropertyReferenceExpression(New CodeVariableReferenceExpression("castFormInstance"), prop.Name), New CodePropertySetValueReferenceExpression())) 522 | End If 523 | 524 | proxyClass.Members.Add(proxyProp) 525 | End Sub 526 | 527 | Private Function GetCastFormInstanceStatement(ByVal interopFormClass As CodeClass) As CodeSnippetStatement 528 | Return New CodeSnippetStatement(" Dim castFormInstance As " & interopFormClass.FullName & " = FormInstance") 529 | End Function 530 | 531 | Private Sub AddEvent(ByVal currentAssembly As Project, ByVal proxyClass As CodeTypeDeclaration, ByVal interopFormClass As CodeClass, ByVal evt As CodeEvent, ByVal proxyClassEventSinkInterface As CodeTypeDeclaration) 532 | Dim evtDelegate As CodeDelegate2 = Nothing 533 | Try 534 | evtDelegate = CType(currentAssembly.CodeModel.CodeTypeFromFullName(evt.Type.AsFullName), CodeDelegate2) 535 | Catch typeFindEx As Exception 536 | For Each ce As CodeElement In evt.ProjectItem.FileCodeModel.CodeElements 537 | If ce.IsCodeType Then 538 | Dim ct As CodeType = CType(ce, CodeType) 539 | For Each ce2 As CodeElement In ct.Children 540 | If ce2.Kind = vsCMElement.vsCMElementDelegate And ce2.FullName = evt.Type.AsFullName Then 541 | evtDelegate = CType(ce2, CodeDelegate2) 542 | End If 543 | Next 544 | End If 545 | Next 546 | End Try 547 | 548 | If evtDelegate Is Nothing Then 549 | DisplayWarning(String.Format(My.Resources.EventErrMsg, evt.Name, evt.Type.AsFullName)) 550 | Exit Sub 551 | End If 552 | 553 | ' find or create the method that hooks the event from the Form 554 | Dim hookCustomEventsMethod As CodeDom.CodeMemberMethod = Nothing 555 | For Each member As CodeTypeMember In proxyClass.Members 556 | If member.Name = "HookCustomEvents" Then 557 | hookCustomEventsMethod = CType(member, CodeMemberMethod) 558 | End If 559 | Next 560 | 561 | If hookCustomEventsMethod Is Nothing Then 562 | hookCustomEventsMethod = New CodeMemberMethod() 563 | hookCustomEventsMethod.Name = "HookCustomEvents" 564 | hookCustomEventsMethod.Attributes = MemberAttributes.Override Or MemberAttributes.Family 565 | hookCustomEventsMethod.Statements.Add(GetCastFormInstanceStatement(interopFormClass)) 566 | proxyClass.Members.Add(hookCustomEventsMethod) 567 | End If 568 | 569 | ' declare the event to be added to the class 570 | Dim proxyEvent As New CodeDom.CodeMemberEvent() 571 | proxyEvent.Attributes = MemberAttributes.Public 572 | ' Set event type to same type as original event 573 | ' However, if we find System.EventArgs in the signature this will change below 574 | proxyEvent.Type = New CodeTypeReference(evt.Type.AsFullName) 575 | proxyEvent.Name = evt.Name 576 | 577 | ' declare the handler method to be added to the sink interface 578 | Dim sinkInterfaceMethod As New CodeDom.CodeMemberMethod() 579 | sinkInterfaceMethod.Name = evt.Name 580 | 581 | ' declare a new delegate for the event for the case in which 582 | ' the event signature includes EventArgs or a derived class 583 | ' and a new down-case delegate will be used instead 584 | ' i.e. 585 | ' original delegate: xxxHandler(sender as object, e as myderivedEventArgs) 586 | ' new delegate: xxxHandler(sender as object, e as System.EventArgs) 587 | Dim proxyDownCastDelegate As New CodeTypeDelegate(evt.Name & "Handler") 588 | Dim isProxyDownCastDelegateAdded As Boolean = False 589 | 590 | ' create the method that handles the interopform's event 591 | Dim proxyClassEventHandler As New CodeDom.CodeMemberMethod() 592 | proxyClassEventHandler.Name = "castFormInstance_" & evt.Name 593 | Dim reraiseEventExpression As New CodeDelegateInvokeExpression(New CodeEventReferenceExpression(New CodeThisReferenceExpression(), proxyEvent.Name)) 594 | 595 | ' Map old parameters to new ones 596 | For Each pOld As CodeParameter2 In evtDelegate.Parameters 597 | Dim sinkInterfaceMethodParmNew As CodeParameterDeclarationExpression 598 | Dim proxyEventHandlerParmNew As CodeParameterDeclarationExpression 599 | Dim reraiseEventExpressionParmNew As CodeArgumentReferenceExpression 600 | 601 | ' See if paramter type is System.EventArgs or derived type. 602 | ' If so, expose as System.EventArgs and add comment showing caller needs 603 | ' to reference .NET tlb in VB6. 604 | If pOld.Type.CodeType IsNot Nothing AndAlso IsEventArgs(pOld.Type.CodeType) Then 605 | ' since we're down-casting we must create the new delegate 606 | If Not isProxyDownCastDelegateAdded Then 607 | proxyClass.Members.Add(proxyDownCastDelegate) 608 | proxyEvent.Type = New CodeTypeReference(proxyDownCastDelegate.Name) 609 | End If 610 | sinkInterfaceMethodParmNew = New CodeParameterDeclarationExpression("System.EventArgs", pOld.Name) 611 | sinkInterfaceMethodParmNew.Direction = GetParamDirection(pOld) 612 | proxyEventHandlerParmNew = New CodeParameterDeclarationExpression(pOld.Type.AsFullName, pOld.Name) 613 | proxyEventHandlerParmNew.Direction = GetParamDirection(pOld) 614 | reraiseEventExpressionParmNew = New CodeArgumentReferenceExpression(sinkInterfaceMethodParmNew.Name) 615 | 616 | ' add comment about the down-casting 617 | proxyEvent.Comments.Add(New CodeCommentStatement(EVENT_ARGS_COMMENT)) 618 | sinkInterfaceMethod.Comments.Add(New CodeCommentStatement(EVENT_ARGS_COMMENT)) 619 | ElseIf Not IsSupported(pOld.Type) Then 620 | ' else check against list of supported types 621 | DisplayWarning(String.Format(My.Resources.EventErrMsg2, pOld.Type.AsFullName, evt.Name)) 622 | Exit Sub 623 | Else 624 | sinkInterfaceMethodParmNew = New CodeParameterDeclarationExpression(pOld.Type.AsFullName, pOld.Name) 625 | sinkInterfaceMethodParmNew.Direction = GetParamDirection(pOld) 626 | proxyEventHandlerParmNew = New CodeParameterDeclarationExpression(pOld.Type.AsFullName, pOld.Name) 627 | proxyEventHandlerParmNew.Direction = GetParamDirection(pOld) 628 | reraiseEventExpressionParmNew = New CodeArgumentReferenceExpression(sinkInterfaceMethodParmNew.Name) 629 | End If 630 | 631 | sinkInterfaceMethod.Parameters.Add(sinkInterfaceMethodParmNew) 632 | ' add same parameters to proxyDownCastDeleage as adding to 633 | ' method in the sinkInterface since they have to match 634 | proxyDownCastDelegate.Parameters.Add(sinkInterfaceMethodParmNew) 635 | proxyClassEventHandler.Parameters.Add(proxyEventHandlerParmNew) 636 | reraiseEventExpression.Parameters.Add(reraiseEventExpressionParmNew) 637 | Next 638 | 639 | proxyClassEventHandler.Statements.Add(reraiseEventExpression) 640 | 641 | hookCustomEventsMethod.Statements.Add(New CodeAttachEventStatement( 642 | New CodeEventReferenceExpression(New CodeVariableReferenceExpression("castFormInstance"), proxyEvent.Name), 643 | New CodeDelegateCreateExpression(proxyEvent.Type, New CodeThisReferenceExpression(), proxyClassEventHandler.Name))) 644 | 645 | ' add the handler to the sink interface 646 | proxyClassEventSinkInterface.Members.Add(sinkInterfaceMethod) 647 | ' add the event to the proxy class 648 | proxyClass.Members.Add(proxyClassEventHandler) 649 | proxyClass.Members.Add(proxyEvent) 650 | End Sub 651 | 652 | 'To make sure we have marked the declarations appropriately with byref or byval 653 | Private Function GetParamDirection(ByVal pOld As CodeParameter2) As FieldDirection 654 | Select Case pOld.ParameterKind 655 | Case vsCMParameterKind.vsCMParameterKindRef 656 | Return FieldDirection.Ref 657 | Case vsCMParameterKind.vsCMParameterKindOut 658 | Return FieldDirection.Out 659 | Case Else 660 | Return FieldDirection.In 661 | End Select 662 | End Function 663 | 664 | Private Function IsEventArgs(ByVal parmType As CodeType) As Boolean 665 | If parmType.FullName.ToLower() = "system.eventargs" Then 666 | Return True 667 | End If 668 | For Each baseElement As CodeElement In parmType.Bases 669 | If baseElement.FullName.ToLower() = "system.eventargs" Then 670 | Return True 671 | End If 672 | If baseElement.IsCodeType Then 673 | If IsEventArgs(CType(baseElement, CodeType)) Then 674 | Return True 675 | End If 676 | End If 677 | Next 678 | Return False 679 | End Function 680 | 681 | Private Function IsSupported(ByVal typeToCheck As CodeTypeRef) As Boolean 682 | For Each supportedType As Type In _supportedTypes 683 | If typeToCheck.AsFullName = supportedType.FullName Then 684 | Return True 685 | End If 686 | Next 687 | ' wasn't in the list of supported types 688 | Return False 689 | End Function 690 | #End Region 691 | End Class 692 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/GenerateInteropFormProxyClassesPackage.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualStudio.Shell 2 | Imports System.Runtime.InteropServices 3 | 4 | ''' 5 | ''' This is the class that implements the package exposed by this assembly. 6 | ''' 7 | ''' 8 | ''' 9 | ''' The minimum requirement for a class to be considered a valid package for Visual Studio 10 | ''' Is to implement the IVsPackage interface And register itself with the shell. 11 | ''' This package uses the helper classes defined inside the Managed Package Framework (MPF) 12 | ''' to do it: it derives from the Package Class that provides the implementation Of the 13 | ''' IVsPackage interface And uses the registration attributes defined in the framework to 14 | ''' register itself And its components with the shell. These attributes tell the pkgdef creation 15 | ''' utility what data to put into .pkgdef file. 16 | ''' 17 | ''' 18 | ''' To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. 19 | ''' 20 | ''' 21 | 22 | 23 | 24 | 25 | Public NotInheritable Class GenerateInteropFormProxyClassesPackage 26 | Inherits Package 27 | 28 | ''' 29 | ''' Package guid 30 | ''' 31 | Public Const PackageGuidString As String = "ff00ffd7-e541-426e-a2af-66850113d3cc" 32 | 33 | ''' 34 | ''' Default constructor of the package. 35 | ''' Inside this method you can place any initialization code that does not require 36 | ''' any Visual Studio service because at this point the package object is created but 37 | ''' not sited yet inside Visual Studio environment. The place to do all the other 38 | ''' initialization is the Initialize method. 39 | ''' 40 | Public Sub New() 41 | End Sub 42 | 43 | #Region "Package Members" 44 | ''' 45 | ''' Initialization of the package; this method is called right after the package is sited, so this is the place 46 | ''' where you can put all the initialization code that rely on services provided by VisualStudio. 47 | ''' 48 | Protected Overrides Sub Initialize() 49 | GenerateInteropFormProxyClasses.Initialize(Me) 50 | MyBase.Initialize() 51 | End Sub 52 | #End Region 53 | End Class 54 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/GenerateInteropFormProxyClassesPackage.vsct: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 48 | 55 | 62 | 63 | 64 | 65 | 66 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hurcane/Microsoft.InteropFormTools.InteropFormProxyGenerator/c93068ce298af1efc78984e1024e0ce211effcbc/Microsoft.InteropFormTools.InteropFormProxyGenerator/Key.snk -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/Microsoft.InteropFormTools.InteropFormProxyGenerator.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 15.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | true 9 | v3 10 | 11 | 12 | 13 | 14 | 14.0 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | 33 | On 34 | 35 | 36 | Binary 37 | 38 | 39 | true 40 | 41 | 42 | Key.snk 43 | 44 | 45 | true 46 | true 47 | true 48 | bin\x64\Debug\ 49 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42353,42354,42355 50 | full 51 | x64 52 | 53 | 54 | true 55 | bin\x64\Release\ 56 | true 57 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42353,42354,42355 58 | pdbonly 59 | x64 60 | 61 | 62 | 63 | Debug 64 | AnyCPU 65 | 2.0 66 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} 67 | {5917F213-ECA0-43FE-81F0-444A48D4CC8F} 68 | Library 69 | Microsoft.InteropFormTools.InteropFormProxyGenerator 70 | Microsoft.InteropFormTools.InteropFormProxyGenerator 71 | v4.7.2 72 | true 73 | true 74 | true 75 | true 76 | true 77 | false 78 | Off 79 | On 80 | 81 | 82 | true 83 | full 84 | false 85 | bin\Debug\ 86 | true 87 | true 88 | prompt 89 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42353,42354,42355 90 | True 91 | 92 | 93 | pdbonly 94 | true 95 | bin\Release\ 96 | false 97 | true 98 | prompt 99 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036,42353,42354,42355 100 | 101 | 102 | 103 | 104 | Designer 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | True 113 | True 114 | Resources.resx 115 | 116 | 117 | 118 | 119 | Menus.ctmenu 120 | Designer 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | False 132 | ..\..\..\Program Files (x86)\Microsoft Visual Basic Power Packs\Interop Forms Toolkit 2.1\SDK\Libraries\Microsoft.InteropFormTools.dll 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | My.Resources 141 | VbMyResourcesResXFileCodeGenerator 142 | Resources.Designer.vb 143 | Designer 144 | 145 | 146 | true 147 | VSPackage 148 | 149 | 150 | 151 | 152 | False 153 | .NET Framework 3.5 SP1 154 | false 155 | 156 | 157 | 158 | 159 | 17.12.40392 160 | 161 | 162 | 17.12.2069 163 | runtime; build; native; contentfiles; analyzers; buildtransitive 164 | all 165 | 166 | 167 | 168 | 169 | 176 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.VisualBasic 2 | Imports System.Reflection 3 | Imports System.Runtime.CompilerServices 4 | Imports System.Runtime.InteropServices 5 | 6 | ' General Information about an assembly is controlled through the following 7 | ' set of attributes. Change these attribute values to modify the information 8 | ' associated with an assembly. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ' Setting ComVisible to false makes the types in this assembly not visible 19 | ' to COM components. If you need to access a type in this assembly from 20 | ' COM, set the ComVisible attribute to true on that type. 21 | 22 | 23 | ' Version information for an assembly consists of the following four values: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' You can specify all the values or you can default the Build and Revision Numbers 31 | ' by using the '*' as shown below: 32 | ' [assembly: AssemblyVersion("1.0.*")] 33 | 34 | 35 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | Imports System 15 | 16 | Namespace My.Resources 17 | 18 | 'This class was auto-generated by the StronglyTypedResourceBuilder 19 | 'class via a tool like ResGen or Visual Studio. 20 | 'To add or remove a member, edit your .ResX file then rerun ResGen 21 | 'with the /str option, or rebuild your VS project. 22 | ''' 23 | ''' A strongly-typed resource class, for looking up localized strings, etc. 24 | ''' 25 | _ 29 | Friend Module Resources 30 | 31 | Private resourceMan As Global.System.Resources.ResourceManager 32 | 33 | Private resourceCulture As Global.System.Globalization.CultureInfo 34 | 35 | ''' 36 | ''' Returns the cached ResourceManager instance used by this class. 37 | ''' 38 | _ 39 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 40 | Get 41 | If Object.ReferenceEquals(resourceMan, Nothing) Then 42 | Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Microsoft.InteropFormTools.InteropFormProxyGenerator.Resources", GetType(Resources).Assembly) 43 | resourceMan = temp 44 | End If 45 | Return resourceMan 46 | End Get 47 | End Property 48 | 49 | ''' 50 | ''' Overrides the current thread's CurrentUICulture property for all 51 | ''' resource lookups using this strongly typed resource class. 52 | ''' 53 | _ 54 | Friend Property Culture() As Global.System.Globalization.CultureInfo 55 | Get 56 | Return resourceCulture 57 | End Get 58 | Set 59 | resourceCulture = value 60 | End Set 61 | End Property 62 | 63 | ''' 64 | ''' Looks up a localized string similar to Error Creating InteropForm Wrapper Classes for Project {0}. 65 | ''' 66 | Friend ReadOnly Property ADDIN_STATUS_GENERATED_ERROR_FULL() As String 67 | Get 68 | Return ResourceManager.GetString("ADDIN_STATUS_GENERATED_ERROR_FULL", resourceCulture) 69 | End Get 70 | End Property 71 | 72 | ''' 73 | ''' Looks up a localized string similar to Error Creating InteropForm Wrapper Classes. 74 | ''' 75 | Friend ReadOnly Property ADDIN_STATUS_GENERATED_ERROR1() As String 76 | Get 77 | Return ResourceManager.GetString("ADDIN_STATUS_GENERATED_ERROR1", resourceCulture) 78 | End Get 79 | End Property 80 | 81 | ''' 82 | ''' Looks up a localized string similar to for Project {0}. 83 | ''' 84 | Friend ReadOnly Property ADDIN_STATUS_GENERATED_ERROR2() As String 85 | Get 86 | Return ResourceManager.GetString("ADDIN_STATUS_GENERATED_ERROR2", resourceCulture) 87 | End Get 88 | End Property 89 | 90 | ''' 91 | ''' Looks up a localized string similar to InteropForm Wrapper Classes Generated. 92 | ''' 93 | Friend ReadOnly Property ADDIN_STATUS_GENERATED_OK() As String 94 | Get 95 | Return ResourceManager.GetString("ADDIN_STATUS_GENERATED_OK", resourceCulture) 96 | End Get 97 | End Property 98 | 99 | ''' 100 | ''' Looks up a localized string similar to Generating InteropForm Wrapper Classes.... 101 | ''' 102 | Friend ReadOnly Property ADDIN_STATUS_GENERATING() As String 103 | Get 104 | Return ResourceManager.GetString("ADDIN_STATUS_GENERATING", resourceCulture) 105 | End Get 106 | End Property 107 | 108 | ''' 109 | ''' Looks up a localized string similar to Unable to generate wrapper classes since no InteropForms were found. Please note that if you are building an Interop UserControl you don't need to use this Addin, just build the project.. 110 | ''' 111 | Friend ReadOnly Property ADDIN_STATUS_NONE_GENERATED_OK() As String 112 | Get 113 | Return ResourceManager.GetString("ADDIN_STATUS_NONE_GENERATED_OK", resourceCulture) 114 | End Get 115 | End Property 116 | 117 | ''' 118 | ''' Looks up a localized string similar to InteropForm Wrapper Class Generator. 119 | ''' 120 | Friend ReadOnly Property DISPLAY_CAPTION() As String 121 | Get 122 | Return ResourceManager.GetString("DISPLAY_CAPTION", resourceCulture) 123 | End Get 124 | End Property 125 | 126 | ''' 127 | ''' Looks up a localized string similar to {6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}. 128 | ''' 129 | Friend ReadOnly Property DOCUMENT_TYPE() As String 130 | Get 131 | Return ResourceManager.GetString("DOCUMENT_TYPE", resourceCulture) 132 | End Get 133 | End Property 134 | 135 | ''' 136 | ''' Looks up a localized string similar to This event exposes System.EventArgs as part of its signature.. 137 | ''' 138 | Friend ReadOnly Property EVENT_ARGS_COMMENT1() As String 139 | Get 140 | Return ResourceManager.GetString("EVENT_ARGS_COMMENT1", resourceCulture) 141 | End Get 142 | End Property 143 | 144 | ''' 145 | ''' Looks up a localized string similar to Any dervied types have been cast down.. 146 | ''' 147 | Friend ReadOnly Property EVENT_ARGS_COMMENT2() As String 148 | Get 149 | Return ResourceManager.GetString("EVENT_ARGS_COMMENT2", resourceCulture) 150 | End Get 151 | End Property 152 | 153 | ''' 154 | ''' Looks up a localized string similar to Be sure COM client references the Common Language Runtime Library (mscorlib.tlb) or library containing appropriate derived type.. 155 | ''' 156 | Friend ReadOnly Property EVENT_ARGS_COMMENT3() As String 157 | Get 158 | Return ResourceManager.GetString("EVENT_ARGS_COMMENT3", resourceCulture) 159 | End Get 160 | End Property 161 | 162 | ''' 163 | ''' Looks up a localized string similar to Event {0} will not be generated. Could not find delegate {1}. Delegate must be explicitly. 164 | ''' 165 | Friend ReadOnly Property EventErrMsg() As String 166 | Get 167 | Return ResourceManager.GetString("EventErrMsg", resourceCulture) 168 | End Get 169 | End Property 170 | 171 | ''' 172 | ''' Looks up a localized string similar to Type {0} is not supported. Event {1} will not be generated.. 173 | ''' 174 | Friend ReadOnly Property EventErrMsg2() As String 175 | Get 176 | Return ResourceManager.GetString("EventErrMsg2", resourceCulture) 177 | End Get 178 | End Property 179 | 180 | ''' 181 | ''' Looks up a localized string similar to {6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}. 182 | ''' 183 | Friend ReadOnly Property FOLDER_TYPE() As String 184 | Get 185 | Return ResourceManager.GetString("FOLDER_TYPE", resourceCulture) 186 | End Get 187 | End Property 188 | 189 | ''' 190 | ''' Looks up a localized string similar to Type {0} is not supported. Initialize method for constructor with parameter {1}({2}) will not be generated.. 191 | ''' 192 | Friend ReadOnly Property InitMethodErrMsg() As String 193 | Get 194 | Return ResourceManager.GetString("InitMethodErrMsg", resourceCulture) 195 | End Get 196 | End Property 197 | 198 | ''' 199 | ''' Looks up a localized string similar to InteropForm Wrapper Classes. 200 | ''' 201 | Friend ReadOnly Property INTEROP_FORM_PROXY_FOLDER_NAME() As String 202 | Get 203 | Return ResourceManager.GetString("INTEROP_FORM_PROXY_FOLDER_NAME", resourceCulture) 204 | End Get 205 | End Property 206 | 207 | ''' 208 | ''' Looks up a localized string similar to Global::ctrl+shift+g. 209 | ''' 210 | Friend ReadOnly Property KeyBinding() As String 211 | Get 212 | Return ResourceManager.GetString("KeyBinding", resourceCulture) 213 | End Get 214 | End Property 215 | 216 | ''' 217 | ''' Looks up a localized string similar to Error creating Add-In: could not load supported types for generated code. . 218 | ''' 219 | Friend ReadOnly Property LoadSupportedTypesErrMsg() As String 220 | Get 221 | Return ResourceManager.GetString("LoadSupportedTypesErrMsg", resourceCulture) 222 | End Get 223 | End Property 224 | 225 | ''' 226 | ''' Looks up a localized string similar to Type {0} is not supported. Method {1} will not be generated.. 227 | ''' 228 | Friend ReadOnly Property MethodErrMsg1() As String 229 | Get 230 | Return ResourceManager.GetString("MethodErrMsg1", resourceCulture) 231 | End Get 232 | End Property 233 | 234 | ''' 235 | ''' Looks up a localized string similar to Type {0} is not supported. Method {1} will not be generated.. 236 | ''' 237 | Friend ReadOnly Property MethodErrMsg2() As String 238 | Get 239 | Return ResourceManager.GetString("MethodErrMsg2", resourceCulture) 240 | End Get 241 | End Property 242 | 243 | ''' 244 | ''' Looks up a localized string similar to Parameterized properties are not supported. Property {0} will not be generated.. 245 | ''' 246 | Friend ReadOnly Property ParamPropertyErrMsg() As String 247 | Get 248 | Return ResourceManager.GetString("ParamPropertyErrMsg", resourceCulture) 249 | End Get 250 | End Property 251 | 252 | ''' 253 | ''' Looks up a localized string similar to Type {0} is not supported. Property {1} will not be generated.. 254 | ''' 255 | Friend ReadOnly Property PropertyErrMsg() As String 256 | Get 257 | Return ResourceManager.GetString("PropertyErrMsg", resourceCulture) 258 | End Get 259 | End Property 260 | End Module 261 | End Namespace 262 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Error Creating InteropForm Wrapper Classes for Project {0} 122 | 123 | 124 | Error Creating InteropForm Wrapper Classes 125 | 126 | 127 | for Project {0} 128 | 129 | 130 | InteropForm Wrapper Classes Generated 131 | 132 | 133 | Generating InteropForm Wrapper Classes... 134 | 135 | 136 | InteropForm Wrapper Class Generator 137 | 138 | 139 | {6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C} 140 | 141 | 142 | This event exposes System.EventArgs as part of its signature. 143 | 144 | 145 | Any dervied types have been cast down. 146 | 147 | 148 | Be sure COM client references the Common Language Runtime Library (mscorlib.tlb) or library containing appropriate derived type. 149 | 150 | 151 | Event {0} will not be generated. Could not find delegate {1}. Delegate must be explicitly 152 | 153 | 154 | Type {0} is not supported. Event {1} will not be generated. 155 | 156 | 157 | {6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C} 158 | 159 | 160 | Type {0} is not supported. Initialize method for constructor with parameter {1}({2}) will not be generated. 161 | 162 | 163 | InteropForm Wrapper Classes 164 | 165 | 166 | Global::ctrl+shift+g 167 | 168 | 169 | Type {0} is not supported. Method {1} will not be generated. 170 | 171 | 172 | Type {0} is not supported. Method {1} will not be generated. 173 | 174 | 175 | Parameterized properties are not supported. Property {0} will not be generated. 176 | 177 | 178 | Type {0} is not supported. Property {1} will not be generated. 179 | 180 | 181 | Error creating Add-In: could not load supported types for generated code. 182 | 183 | 184 | Unable to generate wrapper classes since no InteropForms were found. Please note that if you are building an Interop UserControl you don't need to use this Addin, just build the project. 185 | 186 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/Resources/GenerateInteropFormProxyClasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hurcane/Microsoft.InteropFormTools.InteropFormProxyGenerator/c93068ce298af1efc78984e1024e0ce211effcbc/Microsoft.InteropFormTools.InteropFormProxyGenerator/Resources/GenerateInteropFormProxyClasses.png -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/Resources/GenerateInteropFormProxyClassesPackage.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hurcane/Microsoft.InteropFormTools.InteropFormProxyGenerator/c93068ce298af1efc78984e1024e0ce211effcbc/Microsoft.InteropFormTools.InteropFormProxyGenerator/Resources/GenerateInteropFormProxyClassesPackage.ico -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/VSPackage.resx: -------------------------------------------------------------------------------- 1 |  2 | 12 | 13 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | text/microsoft-resx 120 | 121 | 122 | 2.0 123 | 124 | 125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | 132 | GenerateInteropFormProxyClasses Extension 133 | 134 | 135 | GenerateInteropFormProxyClasses Visual Studio Extension Detailed Info 136 | 137 | 138 | Resources\GenerateInteropFormProxyClassesPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 139 | 140 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | Getting Started 9 | 10 | 11 | 12 |
13 | 17 | 18 |
19 |
20 |

Creating a Visual Studio Extension

21 | 22 |

This project enables developers to create an extension for Visual Studio. The solution contains a VSIX project that packages the extension into a VSIX file. This file is used to install an extension for Visual Studio.

23 |

Add new features

24 | 25 |
    26 |
  1. Right-click the project node in Solution Explorer and select Add>New Item.
  2. 27 |
  3. In the Add New Item dialog box, expand the Extensibility node under Visual C# or Visual Basic.
  4. 28 |
  5. Choose from the available item templates: Visual Studio Package, Editor Items (Classifier, Margin, Text Adornment, Viewport Adornment), Command, Tool Window, Toolbox Control, and then click Add.
  6. 29 |
30 | 31 |

The files for the template that you selected are added to the project. You can start adding functionality to your item template, press F5 to run the project, or add additional item templates.

32 | 33 |

Run and debug

34 |

To run the project, press F5. Visual Studio will:

35 | 36 |
    37 |
  • Build the extension from the VSIX project.
  • 38 |
  • Create a VSIX package from the VSIX project.
  • 39 |
  • When debugging, start an experimental instance of Visual Studio with the VSIX package installed.
  • 40 |
41 | 42 |

In the experimental instance of Visual Studio you can test out the functionality of your extension without affecting your Visual Studio installation.

43 | 44 |
45 |
46 |
47 |

Visual Studio Extensibility Resources

48 | 49 |
    50 |
  1. MSDN documentation
    Detailed documentation and API reference material for building extensions.
  2. 51 |
  3. Extension samples on GitHub
    Use a sample project to kickstart your development.
  4. 52 |
  5. Extensibility chat room on Gitter
    Meet other extension developers and exchange tips and tricks for extension development.
  6. 53 |
  7. Channel 9 videos on extensibility
    Watch videos from the product team on Visual Studio extensibility.
  8. 54 |
  9. Extensibility Tools 2015
    Install an optional helper tool that adds extra IDE support for extension authors.
  10. 55 |
56 |

Give us feedback

57 | 60 |
61 |
62 |
63 |
64 | 65 | 66 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Microsoft Interop Form Tools Proxy Generator 6 | Proxy Generator command converted from add-in with Microsoft InteropForms Toolkit 2.1. 7 | 8 | 9 | 10 | amd64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Microsoft.InteropFormTools.InteropFormProxyGenerator/stylesheet.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | color: #1E1E1E; 6 | font-size: 13px; 7 | font-family: "Segoe UI", Helvetica, Arial, sans-serif; 8 | line-height: 1.45; 9 | word-wrap: break-word; 10 | } 11 | 12 | /* General & 'Reset' Stuff */ 13 | 14 | 15 | .container { 16 | width: 980px; 17 | margin: 0 auto; 18 | } 19 | 20 | section { 21 | display: block; 22 | margin: 0; 23 | } 24 | 25 | h1, h2, h3, h4, h5, h6 { 26 | margin: 0; 27 | } 28 | 29 | /* Header,
30 | header - container 31 | h1 - project name 32 | h2 - project description 33 | */ 34 | 35 | #header { 36 | color: #FFF; 37 | background: #68217a; 38 | position:relative; 39 | } 40 | #hangcloud { 41 | width: 190px; 42 | height: 160px; 43 | background: url("../images/bannerart03.png"); 44 | position: absolute; 45 | top: 0; 46 | right: -30px; 47 | } 48 | h1, h2 { 49 | font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif; 50 | line-height: 1; 51 | margin: 0 18px; 52 | padding: 0; 53 | } 54 | #header h1 { 55 | font-size: 3.4em; 56 | padding-top: 18px; 57 | font-weight: normal; 58 | margin-left: 15px; 59 | } 60 | 61 | #header h2 { 62 | font-size: 1.5em; 63 | margin-top: 10px; 64 | padding-bottom: 18px; 65 | font-weight: normal; 66 | } 67 | 68 | 69 | #main_content { 70 | width: 100%; 71 | display: flex; 72 | flex-direction: row; 73 | } 74 | 75 | 76 | h1, h2, h3, h4, h5, h6 { 77 | font-weight: bolder; 78 | } 79 | 80 | #main_content h1 { 81 | font-size: 1.8em; 82 | margin-top: 34px; 83 | } 84 | 85 | #main_content h1:first-child { 86 | margin-top: 30px; 87 | } 88 | 89 | #main_content h2 { 90 | font-size: 1.4em; 91 | font-weight: bold; 92 | } 93 | p, ul { 94 | margin: 11px 18px; 95 | } 96 | 97 | #main_content a { 98 | color: #06C; 99 | text-decoration: none; 100 | } 101 | ul { 102 | margin-top: 13px; 103 | margin-left: 18px; 104 | padding-left: 0; 105 | } 106 | ul li { 107 | margin-left: 18px; 108 | padding-left: 0; 109 | } 110 | #lpanel { 111 | width: 620px; 112 | float: left; 113 | } 114 | #rpanel ul { 115 | list-style-type: none; 116 | width: 300px; 117 | } 118 | #rpanel ul li { 119 | line-height: 1.8em; 120 | } 121 | #rpanel { 122 | background: #e7e7e7; 123 | width: 360px; 124 | float: right; 125 | } 126 | 127 | #rpanel div { 128 | width: 300px; 129 | } 130 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | ## Microsoft Interop Forms Toolkit Extension ## 2 | 3 | ## Description ## 4 | The official Microsoft Interop Forms Toolkit cannot be used in Visual Studio versions beyond 10.0 (VS 2010). This project converts the add-in source code to a Visual Studio Extensibility project. 5 | 6 | Requirements 7 | ================================= 8 | * [Microsoft Interop Forms Toolkit 2.1](https://web.archive.org/web/20200810070025if_/https://download.microsoft.com/download/3/7/D/37D90824-1BE8-4085-920E-54812C045A55/InteropFormToolsInstaller.msi) 9 | >[!NOTE] 10 | >Microsoft removed the official download page. This link downloads from archive.org. 11 | 12 | Supported Environments 13 | ================================= 14 | * Visual Studio 2022 15 | >[!NOTE] 16 | >Earlier releases support older versions of Visual Studio. 17 | 18 | Usage 19 | ================================= 20 | If you are already familiar with generating wrapper classes using the Microsoft Interop Forms Toolkit in Visual Studio 2010, the experience is identical. Otherwise, review the documentation that is included with the Toolkit. 21 | 22 | Support Forums 23 | ================================= 24 | There is no official support for this project. If you find an issue, you can add it in the [issue tracker](https://github.com/hurcane/Microsoft.InteropFormTools.InteropFormProxyGenerator/issues). 25 | -------------------------------------------------------------------------------- /VSIXProject1/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System.Reflection 2 | Imports System.Runtime.CompilerServices 3 | Imports System.Runtime.InteropServices 4 | Imports Microsoft.VisualBasic 5 | 6 | ' General Information about an assembly is controlled through the following 7 | ' set of attributes. Change these attribute values to modify the information 8 | ' associated with an assembly. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ' Setting ComVisible to false makes the types in this assembly not visible 19 | ' to COM components. If you need to access a type in this assembly from 20 | ' COM, set the ComVisible attribute to true on that type. 21 | 22 | 23 | ' Version information for an assembly consists of the following four values: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' You can specify all the values or you can default the Build and Revision Numbers 31 | ' by using the '*' as shown below: 32 | ' [assembly: AssemblyVersion("1.0.*")] 33 | 34 | 35 | -------------------------------------------------------------------------------- /VSIXProject1/VSIXProject1.vbproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | On 9 | 10 | 11 | Binary 12 | 13 | 14 | 15 | Debug 16 | AnyCPU 17 | 2.0 18 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} 19 | {1B86F030-DDF5-48D4-8098-47AFB2C556B9} 20 | Library 21 | VSIXProject1 22 | VSIXProject1 23 | v4.7.2 24 | true 25 | true 26 | true 27 | false 28 | false 29 | true 30 | true 31 | Off 32 | On 33 | Program 34 | $(DevEnvDir)devenv.exe 35 | /rootsuffix Exp 36 | 37 | 38 | true 39 | full 40 | false 41 | bin\Debug\ 42 | true 43 | true 44 | prompt 45 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 46 | 47 | 48 | pdbonly 49 | true 50 | bin\Release\ 51 | false 52 | true 53 | prompt 54 | 41999,42016,42017,42018,42019,42020,42021,42022,42032,42036 55 | 56 | 57 | 58 | Designer 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | compile; build; native; contentfiles; analyzers; buildtransitive 71 | 72 | 73 | 74 | 75 | 76 | 83 | -------------------------------------------------------------------------------- /VSIXProject1/VSIXProject1Package.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Runtime.InteropServices 3 | Imports System.Threading 4 | Imports Microsoft.VisualBasic 5 | Imports Microsoft.VisualStudio.Shell 6 | Imports Task = System.Threading.Tasks.Task 7 | 8 | 9 | ''' 10 | ''' This is the class that implements the package exposed by this assembly. 11 | ''' 12 | ''' 13 | ''' 14 | ''' The minimum requirement for a class to be considered a valid package for Visual Studio 15 | ''' Is to implement the IVsPackage interface And register itself with the shell. 16 | ''' This package uses the helper classes defined inside the Managed Package Framework (MPF) 17 | ''' to do it: it derives from the Package Class that provides the implementation Of the 18 | ''' IVsPackage interface And uses the registration attributes defined in the framework to 19 | ''' register itself And its components with the shell. These attributes tell the pkgdef creation 20 | ''' utility what data to put into .pkgdef file. 21 | ''' 22 | ''' 23 | ''' To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. 24 | ''' 25 | ''' 26 | 27 | 28 | Public NotInheritable Class VSIXProject1Package 29 | Inherits AsyncPackage 30 | 31 | ''' 32 | ''' Package guid 33 | ''' 34 | Public Const PackageGuidString As String = "8f368540-07f2-4a8d-bf8a-8a710d0ddd86" 35 | 36 | #Region "Package Members" 37 | 38 | ''' 39 | ''' Initialization of the package; this method is called right after the package is sited, so this is the place 40 | ''' where you can put all the initialization code that rely on services provided by VisualStudio. 41 | ''' 42 | ''' A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down. 43 | ''' A provider for progress updates. 44 | ''' A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method. 45 | Protected Overrides Async Function InitializeAsync(cancellationToken As CancellationToken, progress As IProgress(Of ServiceProgressData)) As Task 46 | ' When initialized asynchronously, the current thread may be a background thread at this point. 47 | ' Do any initialization that requires the UI thread after switching to the UI thread. 48 | Await Me.JoinableTaskFactory.SwitchToMainThreadAsync() 49 | End Function 50 | 51 | #End Region 52 | 53 | End Class 54 | -------------------------------------------------------------------------------- /VSIXProject1/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | VSIXProject1 6 | Empty VSIX Project. 7 | 8 | 9 | 10 | amd64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------