2015-06-14 16 views
0

Я написал эту простую функцию, чтобы автоматизировать составление одного ехе сборки со встроенным ресурсом:Скомпилировать приложение без командной строки с помощью CodeDomProvider?

Public Shared Function CompileAssembly(ByVal codeProvider As CodeDomProvider, 
            ByVal isExecutable As Boolean, 
            ByVal targetFile As String, 
            Optional ByVal resources As IEnumerable(Of String) = Nothing, 
            Optional ByVal code As String = "") As CompilerResults 

Dim cp As New CompilerParameters 
With cp 

    ' Generate an exe or a dll. 
    .GenerateExecutable = isExecutable 

    ' Set the assembly file name to generate. 
    .OutputAssembly = targetFile 

    ' Set compiler argument to optimize output. 
    .CompilerOptions = "/optimize" 

    ' Specify the class that contains the main method of the executable. 
    If codeProvider.Supports(GeneratorSupport.EntryPointMethod) Then 
     .MainClass = "MainClass" 
    End If 

    ' Set the embedded resource file of the assembly. 
    If codeProvider.Supports(GeneratorSupport.Resources) AndAlso resources IsNot Nothing Then 
     .EmbeddedResources.AddRange(resources.ToArray) 
    End If 

End With 

Return codeProvider.CompileAssemblyFromSource(cp, code) 

End Function 

Проблема заключается в том, что мне нужно собрать без командной строки приложения в одном классе, как это который я должен предоставить при запуске приложения:

но я не могу найти способ сделать это.

Я только может скомпилировать консольные приложения, так как codeprovider кажется, что нуждается в EntryPoint, так что я только быть в состоянии собрать это, что не то, что я хочу:

Dim Sourcecode As String = 
     <a> 
Module MainModule 

    Sub Main() 
    End Sub 

End Module 
     </a>.Value 

Как я мог бы сделать это для моих потребностей ?.

+0

без точки входа/Sub Main, это не является исполняемым и не побежит. Если вы хотите, чтобы 'MainClass.MainMenthod' выполнялся, должен быть код где-то экземпляр класса и вызвать метод. Может быть, вам нужна DLL? – Plutonix

+0

@Plutonix Нет, я притворяюсь компиляцией исполняемого файла, но просто не исполняемый файл командной строки. Я хочу скомпилировать exe, который не открывает консоль, как проект WinForms. Вы понимаете, что я притворяюсь ?, exe, у которого нет консоли, но есть основной метод, или, другими словами, я хочу, чтобы приложение GUI установило «невидимую форму», но я не знаю, как создайте этот исходный код во время выполнения, например, исходные коды примеров выше, потому что кодированныйпровайдер кажется, что он принимает только модули (приложения командной строки), а не формы, я не могу объяснить это лучше. Спасибо за комментарий – ElektroStudios

+0

Такое приложение все еще требуется Sub Main - точка входа. Все приложения (исполняемые файлы) имеют их, они скрыты в приложениях VB, которые используют форму основного запуска, но она есть ('Application.Run (New MainForm)'). – Plutonix

ответ

1

Я просто хочу поделиться своим рабочий CodeDomProvider компилятор рутина:

Imports System.CodeDom.Compiler 

Namespace Tools 

    Public NotInheritable Class CodeDomUtil 

     ''' <summary> 
     ''' Specifies a <see cref="CompilerParameters"></see> target assembly. 
     ''' </summary> 
     Public Enum TargetAssembly As Integer 

      ''' <summary> 
      ''' A Command line interface executable. 
      ''' </summary> 
      Cli = 0 

      ''' <summary> 
      ''' A Graphical user interface executable. 
      ''' </summary> 
      Gui = 1 

      ''' <summary> 
      ''' A Dynamic-link library. 
      ''' </summary> 
      Dll = 2 

     End Enum 

     ''' <remarks> 
     ''' ***************************************************************** 
     ''' Title : Compile Assembly (from reaource). 
     ''' Author: Elektro 
     ''' Date : 14-June-2015 
     ''' Usage : 
     ''' 
     ''' Using vbCodeProvider As New Microsoft.VisualBasic.VBCodeProvider 
     ''' 
     '''  Dim resultVB As CompilerResults = 
     '''   CodeDomUtil.CompileAssembly(codeProvider:=vbCodeProvider, 
     '''          targetAssembly:=CodeDomUtil.TargetAssembly.Dll, 
     '''          targetFile:="C:\VB Assembly.dll", 
     '''          resources:={"C:\MyResources.resx"}, 
     '''          referencedAssemblies:={"System.dll"}, 
     '''          mainClassName:="MainNamespace.MainClass", 
     '''          sourceCode:=<a> 
     '''             Imports System 
     ''' 
     '''             Namespace MainNamespace 
     ''' 
     '''              Public NotInheritable MainClass 
     ''' 
     '''              End Class 
     ''' 
     '''             End Namespace 
     '''             </a>.Value) 
     ''' 
     '''  Dim warnings As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultVB.Errors.Cast(Of CompilerError)() 
     '''   Where ce.IsWarning 
     ''' 
     '''  Dim errors As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultVB.Errors.Cast(Of CompilerError)() 
     '''   Where Not ce.IsWarning 
     ''' 
     '''  For Each war As CompilerError In warnings 
     '''   Debug.WriteLine(String.Format("{0}| Warning: {1}", war.ErrorNumber, war.ErrorText)) 
     '''  Next war 
     ''' 
     '''  For Each err As CompilerError In errors 
     '''   Debug.WriteLine(String.Format("{0}| Error: {1}", err.ErrorNumber, err.ErrorText)) 
     '''  Next err 
     ''' 
     ''' End Using 
     ''' ----------------------------------------------------------------- 
     ''' Using csCodeProvider As New Microsoft.CSharp.CSharpCodeProvider 
     ''' 
     '''  Dim resultCS As CompilerResults = 
     '''   CodeDomUtil.CompileAssembly(codeProvider:=csCodeProvider, 
     '''          targetAssembly:=CodeDomUtil.TargetAssembly.Dll, 
     '''          targetFile:="C:\C# Assembly.dll", 
     '''          resources:={"C:\MyResources.resx"}, 
     '''          referencedAssemblies:={"System.dll"}, 
     '''          mainClassName:="MainNamespace.MainClass", 
     '''          sourceCode:=<a> 
     '''             using System; 
     ''' 
     '''             namespace MainNamespace 
     '''             { 
     '''              class MainClass 
     '''              { 
     ''' 
     '''              } 
     '''             } 
     '''             </a>.Value) 
     ''' 
     '''  Dim warnings As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultCS.Errors.Cast(Of CompilerError)() 
     '''   Where ce.IsWarning 
     ''' 
     '''  Dim errors As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultCS.Errors.Cast(Of CompilerError)() 
     '''   Where Not ce.IsWarning 
     ''' 
     '''  For Each war As CompilerError In warnings 
     '''   Debug.WriteLine(String.Format("{0}| Warning: {1}", war.ErrorNumber, war.ErrorText)) 
     '''  Next war 
     ''' 
     '''  For Each err As CompilerError In errors 
     '''   Debug.WriteLine(String.Format("{0}| Error: {1}", err.ErrorNumber, err.ErrorText)) 
     '''  Next err 
     ''' 
     ''' End Using 
     ''' ***************************************************************** 
     ''' </remarks> 
     ''' <summary> 
     ''' Compiles a .Net assembly as executable or link library. 
     ''' </summary> 
     ''' <param name="codeProvider">The code provider.</param> 
     ''' <param name="targetAssembly">The kind of assembly to generate.</param> 
     ''' <param name="targetFile">The target file to create.</param> 
     ''' <param name="resources">The embedded resources (if any).</param> 
     ''' <param name="referencedAssemblies">The referenced assemblies (if any).</param> 
     ''' <param name="mainClassName">The code to compile (if any).</param> 
     ''' <param name="sourceCode">The sourcecode to compile (if any).</param> 
     ''' <exception cref="Exception">The current CodeDomProvider does not support resource embedding.</exception> 
     ''' <exception cref="NotImplementedException">Default sourcecode is not implemented for the specified CodeDomProvider. Please, set a sourcecode yourself.</exception> 
     ''' <returns>The results of the compiler operation.</returns> 
     Public Shared Function CompileAssembly(ByVal codeProvider As CodeDomProvider, 
               ByVal targetAssembly As TargetAssembly, 
               ByVal targetFile As String, 
               Optional ByVal resources As IEnumerable(Of String) = Nothing, 
               Optional ByVal referencedAssemblies As IEnumerable(Of String) = Nothing, 
               Optional ByVal mainClassName As String = "MainNamespace.MainClass", 
               Optional ByVal sourceCode As String = Nothing) As CompilerResults 

      ' Set a default assembly reference. 
      If referencedAssemblies Is Nothing Then 
       referencedAssemblies = {"System.dll"} 
      End If 

      Dim cp As New CompilerParameters 
      With cp 

       ' Set compiler arguments. 
       Select Case targetAssembly 

        Case CodeDomUtil.TargetAssembly.Gui 
         .CompilerOptions = "/optimize /target:winexe" 

        Case Else 
         .CompilerOptions = "/optimize" 

       End Select 

       ' Generate an exe or a dll. 
       .GenerateExecutable = (targetAssembly <> CodeDomUtil.TargetAssembly.Dll) 

       ' Save the assembly as a physical file. 
       .GenerateInMemory = False 

       ' Generate debug information (pdb). 
       .IncludeDebugInformation = False 

       ' Set the assembly file name to generate. 
       .OutputAssembly = targetFile 

       ' Add an assembly reference. 
       .ReferencedAssemblies.AddRange(referencedAssemblies.ToArray) 

       ' Set a temporary files collection. 
       ' The TempFileCollection stores the temporary files generated during a build in the current directory. 
       .TempFiles = New TempFileCollection(tempdir:=IO.Path.GetTempPath(), keepFiles:=True) 

       ' Set whether to treat all warnings as errors. 
       .TreatWarningsAsErrors = False 

       ' Set the level at which the compiler should start displaying warnings. 
       ' 0 - Turns off emission of all warning messages. 
       ' 1 - Displays severe warning messages. 
       ' 2 - Displays level 1 warnings plus certain, less-severe warnings, such as warnings about hiding class members. 
       ' 3 - Displays level 2 warnings plus certain, less-severe warnings, such as warnings about expressions that always evaluate to true or false. 
       ' 4 - Displays all level 3 warnings plus informational warnings. This is the default warning level at the command line. 
       .WarningLevel = 3 

       ' Set the embedded resource file of the assembly. 
       If codeProvider.Supports(GeneratorSupport.Resources) AndAlso (resources IsNot Nothing) Then 
        .EmbeddedResources.AddRange(resources.ToArray) 

       ElseIf (Not codeProvider.Supports(GeneratorSupport.Resources)) AndAlso (resources IsNot Nothing) Then 
        Throw New Exception(message:="The current CodeDomProvider does not support resource embedding.") 

       End If 

       ' Specify the class that contains the main method of the executable. 
       If codeProvider.Supports(GeneratorSupport.EntryPointMethod) Then 

        .MainClass = mainClassName 

        If (TypeOf codeProvider Is Microsoft.VisualBasic.VBCodeProvider) AndAlso 
         (String.IsNullOrEmpty(sourceCode)) AndAlso 
         .GenerateExecutable Then 

         sourceCode = 
          <a> 
          Imports System 

          Namespace MainNamespace 

           Module MainClass 

            Sub Main() 
            End Sub 

           End Module 

          End Namespace 
          </a>.Value 

        ElseIf (TypeOf codeProvider Is Microsoft.VisualBasic.VBCodeProvider) AndAlso 
          (String.IsNullOrEmpty(sourceCode)) AndAlso 
          Not .GenerateExecutable Then 

         sourceCode = 
          <a> 
          Imports System 

          Namespace MainNamespace 

           Public NotInheritable MainClass 

           End Class 

          End Namespace 
          </a>.Value 

        ElseIf (TypeOf codeProvider Is Microsoft.CSharp.CSharpCodeProvider) AndAlso 
          (String.IsNullOrEmpty(sourceCode)) AndAlso 
          .GenerateExecutable Then 

         sourceCode = 
          <a> 
          using System; 

          namespace MainNamespace 
          { 
           class MainClass 
           { 
            static void Main(string[] args) 
            { 

            } 
           } 
          } 
          </a>.Value 

        ElseIf (TypeOf codeProvider Is Microsoft.CSharp.CSharpCodeProvider) AndAlso 
          (String.IsNullOrEmpty(sourceCode)) AndAlso 
          Not .GenerateExecutable Then 

         sourceCode = 
          <a> 
          using System; 

          namespace MainNamespace 
          { 
           class MainClass 
           { 

           } 
          } 
          </a>.Value 

        ElseIf String.IsNullOrEmpty(sourceCode) Then 
         Throw New NotImplementedException(message:="Default sourcecode is not implemented for the specified CodeDomProvider. Please, specify a sourcecode.") 

        End If 

       End If 

      End With 

      Return codeProvider.CompileAssemblyFromSource(cp, sourceCode) 

     End Function 

     ''' <remarks> 
     ''' ***************************************************************** 
     ''' Title : Compile Assembly (from file). 
     ''' Author: Elektro 
     ''' Date : 14-June-2015 
     ''' Usage : 
     ''' 
     ''' Using vbCodeProvider As New Microsoft.VisualBasic.VBCodeProvider 
     ''' 
     '''  Dim resultVB As CompilerResults = 
     '''   CodeDomUtil.CompileAssembly(codeProvider:=vbCodeProvider, 
     '''          targetAssembly:=CodeDomUtil.TargetAssembly.Dll, 
     '''          sourceFile:="C:\SourceCode.vb", 
     '''          targetFile:="C:\VB Assembly.dll", 
     '''          resources:={"C:\MyResources.resx"}, 
     '''          referencedAssemblies:={"System.dll"}, 
     '''          mainClassName:="MainNamespace.MainClass") 
     ''' 
     '''  Dim warnings As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultVB.Errors.Cast(Of CompilerError)() 
     '''   Where ce.IsWarning 
     ''' 
     '''  Dim errors As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultVB.Errors.Cast(Of CompilerError)() 
     '''   Where Not ce.IsWarning 
     ''' 
     '''  For Each war As CompilerError In warnings 
     '''   Debug.WriteLine(String.Format("{0}| Warning: {1}", war.ErrorNumber, war.ErrorText)) 
     '''  Next war 
     ''' 
     '''  For Each err As CompilerError In errors 
     '''   Debug.WriteLine(String.Format("{0}| Error: {1}", err.ErrorNumber, err.ErrorText)) 
     '''  Next err 
     ''' 
     ''' End Using 
     ''' ----------------------------------------------------------------- 
     ''' Using csCodeProvider As New Microsoft.CSharp.CSharpCodeProvider 
     ''' 
     '''  Dim resultCS As CompilerResults = 
     '''   CodeDomUtil.CompileAssembly(codeProvider:=csCodeProvider, 
     '''          targetAssembly:=CodeDomUtil.TargetAssembly.Dll, 
     '''          sourceFile:="C:\SourceCode.cs", 
     '''          targetFile:="C:\CS Assembly.dll", 
     '''          resources:={"C:\MyResources.resx"}, 
     '''          referencedAssemblies:={"System.dll"}, 
     '''          mainClassName:="MainNamespace.MainClass") 
     ''' 
     '''  Dim warnings As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultCS.Errors.Cast(Of CompilerError)() 
     '''   Where ce.IsWarning 
     ''' 
     '''  Dim errors As IEnumerable(Of CompilerError) = 
     '''   From ce As CompilerError In resultCS.Errors.Cast(Of CompilerError)() 
     '''   Where Not ce.IsWarning 
     ''' 
     '''  For Each war As CompilerError In warnings 
     '''   Debug.WriteLine(String.Format("{0}| Warning: {1}", war.ErrorNumber, war.ErrorText)) 
     '''  Next war 
     ''' 
     '''  For Each err As CompilerError In errors 
     '''   Debug.WriteLine(String.Format("{0}| Error: {1}", err.ErrorNumber, err.ErrorText)) 
     '''  Next err 
     ''' 
     ''' End Using 
     ''' ***************************************************************** 
     ''' </remarks> 
     ''' <summary> 
     ''' Compiles a .Net assembly as executable or link library. 
     ''' </summary> 
     ''' <param name="codeProvider">The code provider.</param> 
     ''' <param name="targetAssembly">The kind of assembly to generate.</param> 
     ''' <param name="sourceFile">The source file to compile.</param> 
     ''' <param name="targetFile">The target file to create.</param> 
     ''' <param name="resources">The embedded resources (if any).</param> 
     ''' <param name="referencedAssemblies">The referenced assemblies (if any).</param> 
     ''' <param name="mainClassName">The code to compile (if any).</param> 
     ''' <exception cref="Exception">The current CodeDomProvider does not support resource embedding.</exception> 
     ''' <returns>The results of the compiler operation.</returns> 
     Public Shared Function CompileAssembly(ByVal codeProvider As CodeDomProvider, 
               ByVal targetAssembly As TargetAssembly, 
               ByVal sourceFile As String, 
               ByVal targetFile As String, 
               Optional ByVal resources As IEnumerable(Of String) = Nothing, 
               Optional ByVal referencedAssemblies As IEnumerable(Of String) = Nothing, 
               Optional ByVal mainClassName As String = "MainNamespace.MainClass") As CompilerResults 

      ' Set a default assembly reference. 
      If referencedAssemblies Is Nothing Then 
       referencedAssemblies = {"System.dll"} 
      End If 

      Dim cp As New CompilerParameters 
      With cp 

       ' Set compiler arguments. 
       Select Case targetAssembly 

        Case CodeDomUtil.TargetAssembly.Gui 
         .CompilerOptions = "/optimize /target:winexe" 

        Case Else 
         .CompilerOptions = "/optimize" 

       End Select 

       ' Generate an exe or a dll. 
       .GenerateExecutable = (targetAssembly <> CodeDomUtil.TargetAssembly.Dll) 

       ' Save the assembly as a physical file. 
       .GenerateInMemory = False 

       ' Generate debug information (pdb). 
       .IncludeDebugInformation = False 

       ' Set the assembly file name to generate. 
       .OutputAssembly = targetFile 

       ' Add an assembly reference. 
       .ReferencedAssemblies.AddRange(referencedAssemblies.ToArray) 

       ' Set a temporary files collection. 
       ' The TempFileCollection stores the temporary files generated during a build in the current directory. 
       .TempFiles = New TempFileCollection(tempdir:=IO.Path.GetTempPath(), keepFiles:=True) 

       ' Set whether to treat all warnings as errors. 
       .TreatWarningsAsErrors = False 

       ' Set the level at which the compiler should start displaying warnings. 
       ' 0 - Turns off emission of all warning messages. 
       ' 1 - Displays severe warning messages. 
       ' 2 - Displays level 1 warnings plus certain, less-severe warnings, such as warnings about hiding class members. 
       ' 3 - Displays level 2 warnings plus certain, less-severe warnings, such as warnings about expressions that always evaluate to true or false. 
       ' 4 - Displays all level 3 warnings plus informational warnings. This is the default warning level at the command line. 
       .WarningLevel = 3 

       ' Set the embedded resource file of the assembly. 
       If codeProvider.Supports(GeneratorSupport.Resources) AndAlso (resources IsNot Nothing) Then 
        .EmbeddedResources.AddRange(resources.ToArray) 

       ElseIf (Not codeProvider.Supports(GeneratorSupport.Resources)) AndAlso (resources IsNot Nothing) Then 
        Throw New Exception(message:="The current CodeDomProvider does not support resource embedding.") 

       End If 

       ' Specify the class that contains the main method of the executable. 
       If codeProvider.Supports(GeneratorSupport.EntryPointMethod) Then 
        .MainClass = mainClassName 
       End If 

      End With 

      Return codeProvider.CompileAssemblyFromFile(cp, {sourceFile}) 

     End Function 

    End Class 

End Namespace