161
I Use This!
Inactive

News

Analyzed 2 days ago. based on code collected 3 days ago.
Posted over 18 years ago by MattWard
SharpDevelop2 now supports Mono's GAC, so this post takes a low level look into how it uses MSBuild to do this.Our starting point is a previous Custom MSBuild Targets for Mono post, which introduced an MSBuild task (Mcs), which was used to compile ... [More] the code using Mono's Mcs compiler, and an MSBuild targets file (Mono.Mcs.targets).  We will be using the ICSharpCode.Build.Tasks assembly that ships with SharpDevelop2 which contains the custom MSBuild tasks.  We will not be using the SharpDevelop2's target files since these target more than just the Mono framework.Mono GAC ReferencesThe original custom MSBuild task and targets file did not support Mono GAC references.  In fact they were the bare minimum required to compile code using Mcs.  The only MSBuild target that was overridden was the CoreCompile target, which was changed to use the Mcs task instead of Microsoft's Csc task.  Without support for Mono's GAC any assembly references needed to have a HintPath<Reference Include="gtk-sharp">    <HintPath>..\..\Program Files\Mono\lib\mono\gtk-sharp\gtk-sharp.dll</HintPath> </Reference> In order to add support for Mono's GAC we will need to look at the following Microsoft targets and properties:AssemblySearchPathsGetFrameworkPathsResolveAssemblyReferencesFirst let us see if we can get a simple GAC reference to System.Xml to work.  With the old tasks and targets a reference of the form<Reference Include="System.Xml"/>   is resolved to "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll".To fix this we need to override the GetFrameworkPaths target and set the TargetFrameworkDirectory property  correctly.  This can be done by adding the following to the Mono.Mcs.targets file<Target Name="GetFrameworkPaths">     <!-- Get the path to the target Mono Framework directory. -->     <GetMonoFrameworkPath TargetFrameworkVersion="Mono v1.1">         <Output TaskParameter="Path" PropertyName="TargetFrameworkDirectory"/>         <Output TaskParameter="Path" ItemName="_TargetFrameworkDirectoryItem"/>     </GetMonoFrameworkPath>     <!-- Get the path to the target the Mono SDK directory. -->     <GetMonoFrameworkSDKPath>         <Output TaskParameter="Path" PropertyName="TargetFrameworkSDKDirectory"/>         <Output TaskParameter="Path" ItemName="_TargetFrameworkSDKDirectoryItem"/>     </GetMonoFrameworkSDKPath> </Target>    This override must come after the<Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" /> statement, so this should be moved to the beginning of the Mono.Mcs.targets file.  It also uses two custom  tasks that need to be made known to MSBuild<UsingTask TaskName="ICSharpCode.Build.Tasks.GetMonoFrameworkPath"            AssemblyFile="ICSharpCode.Build.Tasks.dll"/> <UsingTask TaskName="ICSharpCode.Build.Tasks.GetMonoFrameworkSdkPath"            AssemblyFile="ICSharpCode.Build.Tasks.dll"/>   The GetFrameworkPaths target sets a few more things than just the TargetFrameworkDirectory, this is done for completeness based on what the Microsoft.Common.targets file does, but only the TargetFrameworkDirectory property needs to be set.  The TargetFrameworkDirectory is set by calling the GetMonoFrameworkPath task and passing in the target framework version, which in this case is "Mono v1.1".  This task uses the registry to locate the Mono framework directory (e.g. "C:\Program Files\Mono\lib\mono\1.0").AssemblySearchPaths and ResolveAssemblyReferenceNow what about an assembly that only exists in Mono's GAC and cannot be found in Mono framework's directory?  A reference to glib-sharp is a good place to start.<Reference Include="glib-sharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"/> We need to modify the AssemblySearchPaths which is being passed to the ResolveAssemblyReference task.  In the Microsoft's target files this is defined as:<PropertyGroup>     <!--     The SearchPaths property is set to find assemblies in the following order:         (1) Files from current project - indicated by {CandidateAssemblyFiles}         (2) $(ReferencePath) - the reference path property, which comes from the .USER file.         (3) The hintpath from the referenced item itself, indicated by {HintPathFromItem}.         (4) The directory of MSBuild's "target" runtime from GetFrameworkPath.             The "target" runtime folder is the folder of the runtime that MSBuild is a part of.         (5) Registered assembly folders, indicated by {Registry:*,*,*}         (6) Legacy registered assembly folders, indicated by {AssemblyFolders}         (7) Look in the application's output folder (like bin\debug)         (8) Resolve to the GAC.         (9) Treat the reference's Include as if it were a real file name.     -->             <AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == '' ">         {CandidateAssemblyFiles};         $(ReferencePath);         {HintPathFromItem};         {TargetFrameworkDirectory};         {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};         {AssemblyFolders};         {GAC};         {RawFileName};         $(OutputPath)     </AssemblySearchPaths>                        </PropertyGroup> The {Registry} part is Microsoft specific and can be removed for Mono.  The {GAC} part is also Microsoft specific.  When the ResolveAssemblyReference task encounters this string it knows to look in Microsoft's GAC.  We will replace this with {MonoGAC} which Microsoft's ResolveAssemblyReference task knows nothing about.<PropertyGroup>     <AssemblySearchPaths>         {CandidateAssemblyFiles};         $(ReferencePath);         {HintPathFromItem};         {TargetFrameworkDirectory};         {AssemblyFolders};         {MonoGAC};         {RawFileName};         $(OutputPath)     </AssemblySearchPaths>  </PropertyGroup> Now we need to somehow replace the {MonoGAC} with a set of directories.  We could write our own ResolveAssemblyReference task, but this seems like a lot of work.  Instead let us update the AssemblySearchPaths just before the ResolveAssemblyReference task is called.  We do this by overriding the ResolveAssemblyReferenceDependsOn target and making it call our custom AddMonoAssemblySearchPaths target.<PropertyGroup>     <ResolveAssemblyReferencesDependsOn>         GetFrameworkPaths;         GetRedistLists;         PrepareForBuild;         AddMonoAssemblySearchPaths     </ResolveAssemblyReferencesDependsOn> </PropertyGroup> <Target Name="AddMonoAssemblySearchPaths">     <AddMonoAssemblySearchPaths          Assemblies="@(Reference)"         Paths="$(AssemblySearchPaths)">         <Output TaskParameter="Paths" PropertyName="AssemblySearchPaths"/>     </AddMonoAssemblySearchPaths> </Target> Again this custom task needs to be included via<UsingTask TaskName="ICSharpCode.Build.Tasks.AddMonoAssemblySearchPaths"            AssemblyFile="ICSharpCode.Build.Tasks.dll"/> The AddMonoAssemblySearchPath task looks for the {MonoGAC} item in the AssemblySearchPaths property and replaces it with any Mono GAC directories that need to be searched.  The GAC directories are determined by looking at the assembly references passed in via the Assemblies property.  If multiple GAC references are located then multiple directories are inserted into the AssemblySearchPaths property.Now we can use MSBuild to build a project with references to assemblies in Mono's GAC using SharpDevelop2's ICSharpCode.Build.Tasks assembly and the Mono.Mcs.targets file.Mono.Mcs.targets<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">     <Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" />     <UsingTask TaskName="ICSharpCode.Build.Tasks.Mcs"                AssemblyFile="ICSharpCode.Build.Tasks.dll"/>      <UsingTask TaskName="ICSharpCode.Build.Tasks.GetMonoFrameworkPath"                AssemblyFile="ICSharpCode.Build.Tasks.dll"/>      <UsingTask TaskName="ICSharpCode.Build.Tasks.GetMonoFrameworkSdkPath"                AssemblyFile="ICSharpCode.Build.Tasks.dll"/>      <UsingTask TaskName="ICSharpCode.Build.Tasks.AddMonoAssemblySearchPaths"                AssemblyFile="ICSharpCode.Build.Tasks.dll"/>    <PropertyGroup>         <MSBuildAllProjects>$(MSBuildAllProjects);Mono.Mcs.targets</MSBuildAllProjects>         <DefaultLanguageSourceExtension>.cs</DefaultLanguageSourceExtension>         <Language>C#</Language>     </PropertyGroup>          <Target Name="CreateManifestResourceNames"/>     <PropertyGroup>         <DebugSymbols Condition=" '$(DebugType)' == 'none' ">false</DebugSymbols>         <DebugType    Condition=" '$(DebugType)' == 'none' "></DebugType>         </PropertyGroup>     <ItemGroup>         <DocFileItem Include="$(DocumentationFile)" Condition="'$(DocumentationFile)'!=''">             <InProject>false</InProject>         </DocFileItem>     </ItemGroup>     <PropertyGroup>         <CoreCompileDependsOn>_ComputeNonExistentFileProperty</CoreCompileDependsOn>     </PropertyGroup>         <!-- Override AssemblySearchPaths property and remove Microsoft specific search paths -->    <PropertyGroup>         <AssemblySearchPaths>             {CandidateAssemblyFiles};             $(ReferencePath);             {HintPathFromItem};             {TargetFrameworkDirectory};             {AssemblyFolders};             {MonoGAC};             {RawFileName};             $(OutputPath)         </AssemblySearchPaths>      </PropertyGroup>          <!-- Modify what the ResolveAssemblyReferences tasks depends on so the          AssemblySearchPaths can be modified to use the Mono GAC -->     <PropertyGroup>         <ResolveAssemblyReferencesDependsOn>             GetFrameworkPaths;             GetRedistLists;             PrepareForBuild;             AddMonoAssemblySearchPaths         </ResolveAssemblyReferencesDependsOn>     </PropertyGroup>     <Target Name="AddMonoAssemblySearchPaths">         <AddMonoAssemblySearchPaths              Assemblies="@(Reference)"             Paths="$(AssemblySearchPaths)">                          <Output TaskParameter="Paths" PropertyName="AssemblySearchPaths"/>         </AddMonoAssemblySearchPaths>     </Target>          <Target    Name="GetFrameworkPaths">         <!-- Get the path to the target Mono Framework directory. -->         <GetMonoFrameworkPath TargetFrameworkVersion="Mono v1.1">             <Output TaskParameter="Path" PropertyName="TargetFrameworkDirectory"/>             <Output TaskParameter="Path" ItemName="_TargetFrameworkDirectoryItem"/>         </GetMonoFrameworkPath>              <!-- Get the path to the target the Mono SDK directory. -->         <GetMonoFrameworkSDKPath>             <Output TaskParameter="Path" PropertyName="TargetFrameworkSDKDirectory"/>             <Output TaskParameter="Path" ItemName="_TargetFrameworkSDKDirectoryItem"/>         </GetMonoFrameworkSDKPath>     </Target>          <Target         Name="CoreCompile"         Inputs="$(MSBuildAllProjects);                 @(Compile);                 @(ManifestResourceWithNoCulture);                 $(ApplicationIcon);                 $(AssemblyOriginatorKeyFile);                 @(ManifestNonResxWithNoCultureOnDisk);                 @(ReferencePath);                 @(CompiledLicenseFile)"         Outputs="@(DocFileItem);                  @(IntermediateAssembly);                  $(NonExistentFile)"         DependsOnTargets="$(CoreCompileDependsOn)"     >                 <Mcs               AdditionalLibPaths="$(AdditionalLibPaths)"               AddModules="@(AddModules)"               AllowUnsafeBlocks="$(AllowUnsafeBlocks)"               CheckForOverflowUnderflow="$(CheckForOverflowUnderflow)"               CodePage="$(CodePage)"               DebugType="$(DebugType)"               DefineConstants="$(DefineConstants)"               DelaySign="$(DelaySign)"               DisabledWarnings="$(NoWarn)"               DocumentationFile="@(DocFileItem)"               EmitDebugInformation="$(DebugSymbols)"               KeyContainer="$(KeyContainerName)"               KeyFile="$(KeyOriginatorFile)"               LangVersion="$(LangVersion)"               MainEntryPoint="$(StartupObject)"               NoConfig="true"               NoLogo="$(NoLogo)"               NoStandardLib="$(NoStdLib)"               Optimize="$(Optimize)"               OutputAssembly="@(IntermediateAssembly)"               References="@(ReferencePath)"               Resources="@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile)"               ResponseFiles="$(CompilerResponseFile)"               Sources="@(Compile)"               TargetType="$(OutputType)"               ToolPath="$(McsToolPath)"               TreatWarningsAsErrors="$(TreatWarningsAsErrors)"               WarningLevel="$(WarningLevel)"               Win32Icon="$(ApplicationIcon)"               Win32Resource="$(Win32Resource)" />     </Target> </Project> [Less]
Posted over 18 years ago by MattWard
In revision 983 SharpDevelop2 has support for Mono's GAC.  It also includes new Gtk# and Glade# project templates, and a Gtk# Window file template.  Mono can be downloaded from here Creating a new Glade# ProjectSelect the menu option File | New | ... [More] Solution to open the "New Project" dialog. Select the C# category.There are two new projects here, a Gtk# project and a Glade# project.  Select the Glade# project.Enter a name for the project and select the "Create" button to generate the project.The generated project will target Mono 1.1 by default, and will use Mono's Mcs compiler.Running the Glade# ApplicationIf you have the Mono bin directory (e.g. C:\Program Files\Mono\bin) added to your Path environment variable, the project can be started by selecting the menu option Debug | Run or Debug | Run without debugger. This will run the application under the Microsoft .NET framework and not Mono itself, to run under Mono see this post. Note that you cannot debug the application when it is built with either of the Mono compilers.Adding a Mono GAC ReferenceOpen the Project Browser via View | Project.Select the "References" node, right click and select "Add Mono Reference".  Select the GAC entry that will be added to the project, click the Select button and then click the OK button to add the reference to the project. Code CompletionThere is a small problem with code auto-completion.  In order for auto-completion to work the reference must be added via the "Add Mono Reference" dialog.  So the first time a Glade# or Gtk# project has been created you will have to remove the GAC references and then re-add them to get code auto-completion working.  This only needs to be done once, not every time a Gtk# or Glade# project is created. Debugging a Mono ApplicationYou cannot debug a Mono app built using Mcs or Gmcs.  The Mono compilers create their own open source debugging symbols binary (.mdb) which SharpDevelop and Microsoft's DbgCLR do not support.  There is also no Mono debugger available for Windows.  In order to debug a Mono app it needs to be built using the Microsoft Csc compiler.  The general guidelines to be able to debug your Mono app using the SharpDevelop debugger are:Make sure all Mono specific GAC references have "Local Copy" set to true.  Select the reference in the Project Browser and select Properties to set this.The Mono bin directory (e.g. C:\Program Files\Mono\bin) must be added to the Path environment variable.Change the "Target Framework" (Project | Project Options | Compiling) to one of the Microsoft .NET frameworks.Remove and re-add your Mono GAC references using the "Add Mono Reference" dialog.  You should only need to do this once and only if you are using a project created from the Glade# or Gtk# templates.  Doing this will add a HintPath to the references in your MSBuild project so the Microsoft compilers can locate the assemblies in the Mono GAC.  These HintPaths are not currently added to a newly created Glade/Gtk# project.Rebuild your application.Once the HintPaths have been added to your MSBuild project you should be able to switch between the Microsoft and Mono frameworks as required, and build your code using the Microsoft or Mono compilers.If you are going to debug a Gtk# or Glade# application you will need to add extra GAC references.  Mcs and Gmcs do not need all Gtk# references to be added, but Microsoft's Csc compiler does.  For a Gtk# app you will need at least:atk-sharpgdk-sharpglib-sharpgtk-sharppango-sharpAlso add glade-sharp if you are developing a Glade# app.LinksMono DownloadsTargeting Mono with SharpDevelop2SharpDevelop Daily Builds [Less]
Posted over 18 years ago by MattWard
Support for web references has now been added to SharpDevelop2 in revision 955.  FeaturesAdd web referenceBrowse/view web servicesAutomatic web proxy class generationRefresh web referenceUpdates generated web proxy classAdding a Web ReferenceWith a ... [More] project open in SharpDevelop, view the project browser by selecting View | Projects.In the project browser, right click either the project node or the References node and select "Add Web Reference" to open a dialog.Enter a url and browse for a web service.Once the web service has been located the reference name and namespace will be auto-generated.Change the reference name and the web proxy namespace if required. Click the "Add" button to add the web reference to the project.Refreshing the Web ReferenceIf the web service changes, the generated proxy class will need to be refreshed or updated.  Open the project browser.Select the web reference node, right click and select "Refresh Web Reference".The proxy class will then be regenerated.  Note that when the web service is refreshed the namespace of the proxy class will be set to the namespace of the project.  This may not correspond to what was entered into the "Add Web Reference" dialog.Discovering Web ServicesNow let us take a look at the code.  The web service discovery is handled completely by the DiscoveryClientProtocol class which is part of the .NET Framework.  The following simple example code discovers a web service and saves the discovered documents to disk.    DiscoveryClientProtocol protocol = new DiscoveryClientProtocol();     protocol.DiscoverAny("http://localhost/Maths.asmx");     protocol.ResolveOneLevel();     protocol.WriteAll(@"c:\temp\Web References", "Reference.map"); Generating a Web ProxyOnce the DiscoveryClientProtocol class has discovered the web service the web proxy can be generated.  To generate a proxy the CSharpCodeProvider and the ServiceDescriptionImporter; class can be used.  Here is a simple example that discovers a web service, saves the discovered documents, and then generates a web proxy.using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.IO; using System.Web.Services.Description; using System.Web.Services.Discovery; using System.Xml.Schema; using System.Xml.Serialization; namespace WebServiceTest {     class MainClass     {         public static void Main(string[] args)         {             // Discover and save web service information.             DiscoveryClientProtocol protocol = new DiscoveryClientProtocol();             protocol.DiscoverAny("http://localhost/Maths.asmx");             protocol.ResolveOneLevel();             protocol.WriteAll(@"c:\temp\Web References", "Reference.map");                          // Generate the web proxy.             ServiceDescriptionCollection services = GetServiceDescriptionCollection(protocol);             XmlSchemas schemas = GetXmlSchemas(protocol);             GenerateWebProxy("WebServiceTest", @"c:\temp\Web References\Reference.cs", services, schemas);         }                          static ServiceDescriptionCollection GetServiceDescriptionCollection(DiscoveryClientProtocol protocol)         {             ServiceDescriptionCollection services = new ServiceDescriptionCollection();             foreach (DictionaryEntry entry in protocol.References) {                 ContractReference contractRef = entry.Value as ContractReference;                 DiscoveryDocumentReference discoveryRef = entry.Value as DiscoveryDocumentReference;                 if (contractRef != null) {                     services.Add(contractRef.Contract);                 }             }             return services;         }                  static XmlSchemas GetXmlSchemas(DiscoveryClientProtocol protocol)         {             XmlSchemas schemas = new XmlSchemas();             foreach (DictionaryEntry entry in protocol.References) {                 SchemaReference schemaRef = entry.Value as SchemaReference;                 if (schemaRef != null) {                     schemas.Add(schemaRef.Schema);                 }             }             return schemas;         }                  static void GenerateWebProxy(string proxyNamespace, string fileName, ServiceDescriptionCollection serviceDescriptions, XmlSchemas schemas)         {             ServiceDescriptionImporter importer = new ServiceDescriptionImporter();                          foreach (ServiceDescription description in serviceDescriptions) {                 importer.AddServiceDescription(description, null, null);             }                          foreach (XmlSchema schema in schemas) {                 importer.Schemas.Add(schema);             }                          CodeNamespace codeNamespace = new CodeNamespace(proxyNamespace);             CodeCompileUnit codeUnit = new CodeCompileUnit();             codeUnit.Namespaces.Add(codeNamespace);             ServiceDescriptionImportWarnings warnings = importer.Import(codeNamespace, codeUnit);                          CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();                                     using (StreamWriter sw = new StreamWriter(fileName)) {                 CodeGeneratorOptions options = new CodeGeneratorOptions();                 options.BracingStyle = "C";                 provider.GenerateCodeFromCompileUnit(codeUnit, sw, options);             }         }     } } Compatiblity with Visual StudioWeb references generated by SharpDevelop are "Static".  Visual Studio generates "Dynamic" web references.Creating and refreshing "Dynamic" web references are not currently supported in SharpDevelop.Visual Studio generates dynamic web references, where the web service URL is stored in an app.config file rather than hard coded in the web proxy itself.  The proxy generated by Visual Studio accesses this URL through a Settings class, which is used to access all properties for an application. this.Url = global::BaseFormTest.Properties.Settings.Default.WebServiceTest_localhost_Maths;SharpDevelop is currently not able to generate corresponding code when refreshing the web service.Web References VideoThere is also a video, created by Chris, showing the web reference functionality in SharpDevelop 1.1. [Less]
Posted over 18 years ago by MattWard
Support for inserting PInvoke signatures has been added to SharpDevelop2 in revision 925.FeaturesSearch PInvoke signatures held at pinvoke.netInsert C# or VB.Net signatures into source code.How to usePosition the cursor where you want the pinvoke ... [More] method signature to be inserted.Right click, or open the Tools menu option, and select "Insert PInvoke Signatures..." to open a dialog.Type in the name of the function you want and click the Find button.The pinvoke signature is retrieved and displayed in the dialog.  Further information can be viewed by clicking the "More Info" hyperlink which will send your browser to the appropriate pinvoke.net web page.Click the insert button to insert the signature into your code.pinvoke.netThis SharpDevelop2 feature uses a web service from the excellent pinvoke.net web site created by Adam Nathan.  If you want more information than the insert pinvoke signatures dialog provides and examples then explore the pinvoke.net wiki. [Less]
Posted over 18 years ago by MattWard
Here is a list of features that were available in SharpDevelop 1.1, but are not available in SharpDevelop 2.0, and the reasons why. This list will be kept updated as features are ported over. Missing Features Feature ID Information ... [More] Assembly Analyzer SD2-528 Not yet ported. Assembly Scout SD2-527 Not yet ported. There also seems to be a large overlap with the new and improved class browser. The class browser now allows us to drill down into a project's references and pull up class/method information. Auto Find Files SD2-540 Not yet ported. C Projects Not yet ported. NProf SD2-535 Need an open source profiler for .NET 2.0. Pause Console Output SD2-475 Not yet ported. Projects and Solutions Options SD2-464 Not yet ported. Publishing SD2-430 Not yet ported. WiX Not yet ported. Features Dropped Feature ID Information Console Window SD2-529 No longer part of the official distribution. Markus Palme has ported it to SharpDevelop2 and it can be downloaded from his web site. InitializeComponents Read-Only SD2-539 Feature dropped to be replaced by partial form designer classes. Forms designer currently supports partial classes, but form templates need modifying. Message Box Wizard SD2-537 Feature dropped due to improved enum auto-completion in SharpDevelop 2.0. NAnt Create Build File SD2-531 Feature dropped. NAnt Contrib will be getting an MSBuild task at some point in the future so there will be no need to convert from MSBuild to NAnt. [Less]
Posted over 18 years ago by MattWard
The starting point is the Glade xml file. Glade xml file This was created using the Glade UI Builder that ships with the Mono installer. The xml file specifies the UI components and signals (events) for these components. In our case the main ... [More] components we have are a mainWindow and a messageLabel. There is also a delete_event signal defined for the main window named MainWindowDeleteEvent.<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--><!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"><glade-interface><widget class="GtkWindow" id="mainWindow">  <property name="visible">True</property>  <property name="title" translatable="yes">Hello, Gtk# World</property>  <property name="type">GTK_WINDOW_TOPLEVEL</property>  <property name="window_position">GTK_WIN_POS_NONE</property>  <property name="modal">False</property>  <property name="default_width">300</property>  <property name="default_height">300</property>  <property name="resizable">True</property>  <property name="destroy_with_parent">False</property>  <property name="decorated">True</property>  <property name="skip_taskbar_hint">False</property>  <property name="skip_pager_hint">False</property>  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>  <signal name="delete_event" handler="MainWindowDeleteEvent" last_modification_time="Thu, 20 Oct 2005 13:24:07 GMT"/>  <child>    <widget class="GtkLabel" id="messageLabel">      <property name="visible">True</property>      <property name="label" translatable="yes">Message here...</property>      <property name="use_underline">False</property>      <property name="use_markup">False</property>      <property name="justify">GTK_JUSTIFY_LEFT</property>      <property name="wrap">False</property>      <property name="selectable">False</property>      <property name="xalign">0.5</property>      <property name="yalign">0.5</property>      <property name="xpad">0</property>      <property name="ypad">0</property>    </widget>  </child></widget></glade-interface> Now we need to create a SharpDevelop project to add this Glade xml file to. Create a new empty project Select File | New | Solution to open the "New Project" dialog. Select the C# category and the "Empty Project" template. Enter in project name "HelloGtkWorld" and choose a location. Click the "Create" button to create your empty project. Remove all unwanted assembly references Select View | Projects to open up the project browser. Expand the tree so the assembly references are displayed. There should be two, System and System.Xml. Select one at a time, right click and select "Remove". Repeat until all references have been removed. Add a Glade xml file to the project Select the project tree node, right click and select Add | New Item... to open the "New File" dialog. Select the Misc category and the "Empty XML file" template. Type in the name "glade.xml" and click the "Create" button. Modify the glade.xml file so it contains the xml shown above. Embed this xml file as a resource. Select the file in the Project Browser. Select the menu View | Properties. Change the "Build action" to "EmbeddedResource". Create a new C# class that will be the main entry point for the application Open the project browser again. Select the project tree node, right click and select Add | New Item... to open the "New File" dialog. Select the C# category and the Class template. Type in the filename GladeApp.cs and click the "Create" button to add the new C# class file to the project. This file should be opened when created. Modify the code so the file contains:using Glade;using Gtk;using System;public class GladeApp{        [Widget]    Label messageLabel;           public static void Main (string[] args)    {        new GladeApp (args);    }    public GladeApp (string[] args)     {        Application.Init();        Glade.XML gxml = new Glade.XML(null, "HelloGtkWorld.glade.xml", "mainWindow", null);        gxml.Autoconnect(this);        messageLabel.Text = "Hello, Gtk# World.";        Application.Run();    }        void MainWindowDeleteEvent(object o, DeleteEventArgs args)    {        Application.Quit();        args.RetVal = true;    }} Let us have a look at this code before we attempt to make sure it compiles. The main part of interest is in the GladeApp class's constructor. First Gtk is initialised:        Application.Init(); This must be called before any Gtk libraries are used. Then a Glade.XML object is created that will use our "glade.xml" file which has been embedded as a resource. Note that the resource name is the name of the file with the project's namespace prefixed "HelloGtkWorld.gui.xml".        Glade.XML gxml = new Glade.XML(null, "HelloGtkWorld.glade.xml", "mainWindow", null); The Autoconnect call connects the signals defined in the Glade xml file to matching handlers in the GladeApp class. It will also initialise any fields that correspond to UI components defined in the Glade xml file.        gxml.Autoconnect(this); The next line sets the text of the label that will be displayed in the main window.        messageLabel.Text = "Hello, Gtk# World."; The messageLabel object    [Widget]    Label messageLabel; will auto-magically be initialised for us by the Glade.Xml object. Finally the application is run via:        Application.Run(); When the user closes the main window the MainWindowDeleteEvent method is called.    void MainWindowDeleteEvent(object o, DeleteEventArgs args)    {        Application.Quit();        args.RetVal = true;    } This method makes sure the application quits. If the Application.Quit method is not called then even though the main window has been closed the app will still be running in the background. Add references to the Glade and Gtk assemblies. Open the Project Browser. Select the "References" node, right click and select "Add References". In the "Add Reference" dialog select the ".NET Assembly Browser" tab and click the "Browse..." button. Browse to the Mono folder containing the assemblies for Glade and Gtk#. The folder should be something like "C:\Program Files\Mono\lib\mono\gtk-sharp". Select the glade-sharp and gtk-sharp dlls and click the "Open" button. In the "Add Reference" dialog click the "OK" button. Compiling the code Select the menu item Project | Project Options. In the "Application" tab, change the "Output type" to be "Windows Application". In the "Compiling" tab, change the "Target framework" to "Mono 1.1". In the "Debug" tab, change the "Start Action" to "Start external program". Set the external program field by browsing and selecting Mono.exe, which lives in "C:\Program Files\Mono\bin". In the "Start Options" group set the "Command line arguments to be "${TargetPath}" and the "Working directory" to "${TargetDir}". Select the menu Build | Rebuild Solution. The code should build successfully. There will be two warnings, one about MainWindowDeleteEvent method never being called and another about the messageLabel variable never being assigned to, both of which can be safely ignored. It is optional whether you use the Mono as the Target framework, the Gtk# and Glade libraries should work under the .NET framework. You will have to add references to the Glib and Atk libraries to be able to compile using Csc. Running the app Select the menu Debug | Run without debugger. As with the target framework, it is optional whether you run the application under Mono since the Gtk# and Glade libraries should work under the .NET framework. Other Useful Resources Introduction to Mono - Your first Mono app - Covers creating a Mono console app.A google search application using Gtk# - Uses Visual Studio to create a Gtk# Mono app that uses Google's web service. A Gtk# beginners guide. - Covers Gtk# and Glade. GUI development with Glade - A tutorial covering the Glade User Interface Builder. Mono Documentation - Covers all the Mono libraries including Gtk# and Glade.[Update: 10 Jan, 2006]SharpDevelop2 now ships with Gtk# and Glade# templates.  Support for Mono's GAC has also been added.  Read more here. [Less]
Posted over 18 years ago by MattWard
Whilst looking at the NAnt config file (Nant.exe.config), I noticed that NAnt does a much better job at detecting where the Mono compilers, Mcs and Gmcs, are located. NAnt reads the registry, whilst SharpDevelop assumes that they exist somewhere ... [More] in a folder, typically "C:\Program Files\Mono\bin", that has been added to the Path environment variable. If you add the "C:\Program Files\Mono\bin" folder to the Path then everything should work. In this bin folder there are several .bat files that can be used to run the various Mono compilers, and these are what SharpDevelop uses. The Mono executables live in "C:\Program Files\Mono\lib\mono\1.0" and "C:\Program Files\Mono\lib\mono\2.0", depending on the framework being targeted, and the .bat files run these executables under Mono. Mono's Registry Settings When you install Mono under Windows the installer adds a registry key under HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Mono, and the values entered here can be used to detect where Mono is. [HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Mono] DefaultCLR=1.1.9.2 [HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Mono\1.1.9.2] FrameworkAssemblyDirectory=C:\Program Files\Mono\lib MonoConfigDir=C:\Program Files\Mono\etc SdkInstallRoot=C:\Program Files\Mono SharpDevelop will now use the registry to locate the Mono bin folder, and if this fails then it falls back on its original method of assuming that the compiler lives in a folder added to the Path. This small improvement has been added to SharpDevelop 2.0 in revision 593. [Less]
Posted over 18 years ago by MattWard
Support for NAnt has been added to SharpDevelop 2.0. in revision 573.Changes from SharpDevelop 1.1There are a few things missing from the NAnt addin compared to the previous version that shipped with SharpDevelop 1.1.The "Create Build File" menu ... [More] option has been removed.  SharpDevelop now uses MSBuild project files instead of SharpDevelop projects (.prjx) and there is currently no conversion code written.  The original code took the project file and ran an XSL transform on it to produce the NAnt build file.  This feature will be added at a later date.NAnt no longer ships with SharpDevelop.  This means that NAnt needs to be installed separately.  By default SharpDevelop assumes that the NAnt executable is accessible by the Path environment variable.  If this not the case the NAnt executable to use can be set via Tools | Options | Tools | NAnt | Command.  If you install one of the NAnt nightly builds  you will be able to target .NET Framework 2.0 Beta 2.By default SharpDevelop supports NAnt 0.85 RC3, previously the 0.84 schema was the default.IssuesThe first time SharpDevelop is run the NAnt pad may not display any contents.  To fix this you will need to restart SharpDevelop.  There seems to be an issue with the default layout information.Creating a new NAnt build fileTo add a new build file to your project: Open the project browser, View | Projects. Right click the project and select Add | Add New Item... In the "New File" dialog, select the Misc category. Choose the "NAnt Build File" template, specify a file name and click the "Create" button. Xml auto-completion, based on the NAnt 0.85 RC3 schema, will occur whilst you are editing the NAnt build.Project Menu Run Default Target Runs the default target of the build file for the project.  The build file must be part of the project (i.e. it exists in the project view). Run Clean Target Runs the "clean" target of the build file for the project.There is currently no clever add-in logic here, in order for this menu option to work there needs to be a target called "clean". Stop NAnt Stops a currently running build.  A warning message is displayed.  This option kills the NAnt process.Project BrowserNAnt ".build" and ".include" files are displayed in the project browser with their own icon.NAnt PadTo open the NAnt pad, select View | Tools | NAnt. The NAnt Pad displays all the build files in the solution.  It gives a high level overview of the build file, showing all the build targets.Double clicking a target node will open up the build file and move the cursor to the corresponding <target> element.The NAnt pad's toolbar buttons, from left to right: Run If the build file node is selected, runs the default target.If a target node is selected, runs that target. Refresh Refreshes the tree.  Reads the build file again and updates the display. Stop Stops the currently running build.The NAnt pad has a text box at the bottom where the user can specify extra command line options.  In the screenshot below the user has entered "-targetframework:net-1.1", this will be added to the NAnt command line.NAnt Pad Context MenuRight clicking the build file node shows the context menu:The Open menu option will open the build file into the SharpDevelop text editor.The other menu options have been described in the "Project Menu" section.Right clicking on a target node shows the context menu: Run Target Runs the target selected.  This passes the target's name to NAnt on the command line. Open Opens the build file into the SharpDevelop's text editor. Goto Definition Opens up the build file and moves the mouse cursor to the corresponding <target> element.Output WindowAll NAnt output is shown in a NAnt output window.The first two lines are outputted by the NAnt add-in showing the NAnt command line used.  The rest is the output from NAnt.Errors WindowErrors and warnings from the NAnt build are displayed in the Errors window.  NAnt ConfigurationOpen the NAnt options panel via Tools | Options | Tools | NAnt  Panel Option Description Command The location of the NAnt executable to use. Arguments Standard arguments that will be passed to NAnt (e.g. -targetframework:net-1.1). Quiet Maps to NAnt's -quiet command line option. Show Logo Shows/hides the NAnt logo in the output window. Verbose Maps to NAnt's -verbose command line option. Debug Maps to NAnt's -debug command line option. [Less]
Posted over 18 years ago by MattWard
Daniel recently added support for .NET 1.1 and .NET 1.0 to SharpDevelop 2.0.  Let us take a low level look at how SharpDevelop 2.0 targets other frameworks.  Targeting another framework involves a custom .targets file and custom MSBuild tasks.  ... [More] SharpDevelop Custom MSBuild Tasks and Targets Component Description ICSharpCode.Build.Tasks.dll Assembly containing custom MSBuild tasks. SharpDevelop.Build.Common.targets Specifies targets common to all SharpDevelop targets. SharpDevelop.Build.CSharp.targets Specifies targets for C# projects that target a framework other than the default. SharpDevelop.Build.Mono.Mcs.targets Defines the Mcs task. SharpDevelop.Build.Mono.Gmcs.targets Defines the Gmcs task. SharpDevelop.Build.MSIL.targets Specifies targets for ILAsm projects. What happens when another framework is targeted? When the project has been configured to target a framework other than the default, the project is modified to use a customised .targets file and has a property added that specifies the framework being targeted.  Below is a project file for a console application that targets Mono 1.1. <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">   <PropertyGroup>     <OutputType>Exe</OutputType>     <RootNamespace>HelloMonoWorld</RootNamespace>     <AssemblyName>HelloMonoWorld</AssemblyName>     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>     <ProjectGuid>{0534CD74-E5FA-4349-866E-4E0C6428E840}</ProjectGuid>     <TargetFrameworkVersion>Mono v1.1</TargetFrameworkVersion>     <NoStdLib>False</NoStdLib>     <WarningLevel>4</WarningLevel>   </PropertyGroup>   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">     <OutputPath>bin\Debug\</OutputPath>     <Optimize>False</Optimize>     <DefineConstants>DEBUG;TRACE</DefineConstants>     <DebugSymbols>true</DebugSymbols>     <DebugType>Full</DebugType>   </PropertyGroup>   <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">     <OutputPath>bin\Release\</OutputPath>     <Optimize>True</Optimize>     <DefineConstants>TRACE</DefineConstants>     <DebugSymbols>False</DebugSymbols>     <DebugType>None</DebugType>   </PropertyGroup>   <ItemGroup>     <Compile Include="Main.cs" />     <Compile Include="AssemblyInfo.cs" />   </ItemGroup>   <Import Project="$(SharpDevelopBinPath)\SharpDevelop.Build.CSharp.targets" /> </Project> The .csproj file has a <TargetFrameworkVersion> element and includes a custom .targets file "SharpDevelop.Build.CSharp.targets" instead of the usual "Microsoft.CSharp.Targets". The "SharpDevelop.Build.CSharp.targets" file looks at the TargetFrameworkVersion information and targets the appropriate runtime.  If we are targeting Mono, the file imports one of the Mono specific target files. <Import Condition=" '$(TargetFrameworkVersion)' == 'Mono v1.1' "          Project="$(SharpDevelopBinPath)\SharpDevelop.Build.Mono.Mcs.targets"/> <Import Condition=" '$(TargetFrameworkVersion)' == 'Mono v2.0' "         Project="$(SharpDevelopBinPath)\SharpDevelop.Build.Mono.Gmcs.targets"/> These Mono specific files reference the custom MSBuild tasks in the ICSharpCode.Build.Tasks assembly. If one of the Microsoft .NET frameworks is targeted, various properties, such as CscToolPath, are changed so the correct compiler is used, but no custom tasks are involved. [Less]
Posted over 18 years ago by MattWard
SharpDevelop ships with two custom MSBuild tasks for Mono, one for Mcs and the other for Gmcs, both of which live in the ICSharpCode.Build.Tasks assembly.  With the recent Mono release, 1.1.9, the command line options and compiler error message ... [More] formats are the same for Mcs and Gmcs, earlier versions differed.  This means that the Mcs and Gmcs classes do not do much apart from determine the name of the compiler to use.  The MonoCompilerTask class does the hard work of compiling the code and reporting error messages back. Simple C# Console Project HelloMonoWorld.csproj: <Project DefaultTargets="Build"           xmlns="http://schemas.microsoft.com/developer/msbuild/2003">   <PropertyGroup>     <OutputType>Exe</OutputType>     <AssemblyName>HelloMonoWorld</AssemblyName>     <WarningLevel>4</WarningLevel>   </PropertyGroup>   <PropertyGroup>     <OutputPath>bin</OutputPath>   </PropertyGroup>   <ItemGroup>     <Compile Include="Main.cs" />     <Compile Include="AssemblyInfo.cs" />   </ItemGroup>   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project> Main.cs: using System; namespace HelloMonoWorld {     class MainClass     {         public static void Main(string[] args)         {             Console.WriteLine("Hello World!");         }     } } Running MSBuild, passing the .csproj as a command line argument, will build the console app using Microsoft's Csc and targets the .NET Framework 2.0. Using the Mcs Task Directly Let us modify the project file so it calls the Mcs task directly.  I am assuming that the ICSharpCode.Build.Tasks.dll exists in the same folder as the project file. <Project DefaultTargets="Build"           xmlns="http://schemas.microsoft.com/developer/msbuild/2003">   <PropertyGroup>     <OutputType>Exe</OutputType>     <AssemblyName>HelloMonoWorld</AssemblyName>     <WarningLevel>4</WarningLevel>   </PropertyGroup>   <PropertyGroup>     <OutputPath>bin</OutputPath>   </PropertyGroup>   <ItemGroup>     <Compile Include="Main.cs" />     <Compile Include="AssemblyInfo.cs" />   </ItemGroup>      <UsingTask TaskName="ICSharpCode.Build.Tasks.Mcs"              AssemblyFile="ICSharpCode.Build.Tasks.dll"/>   <Target Name="Build">     <Mcs       OutputAssembly="$(OutputPath)\$(AssemblyName).exe"       References="@(ReferencePath)"       Sources="@(Compile)"       TargetType="$(OutputType)"/>   </Target> </Project> The project file above is a bit limited, it does not have standard targets such as "Rebuild" and "Clean".  We could write everything ourselves, but instead why not use the standard .targets that Microsoft provides and just override the bare minimum? Mono.Mcs.targets So what is the bare minimum .targets file we need in order to get MSBuild to use our custom Mono tasks? First let us look at the modified project file: <Project DefaultTargets="Build"           xmlns="http://schemas.microsoft.com/developer/msbuild/2003">   <PropertyGroup>     <OutputType>Exe</OutputType>     <AssemblyName>HelloMonoWorld</AssemblyName>     <WarningLevel>4</WarningLevel>   </PropertyGroup>   <PropertyGroup>     <OutputPath>bin</OutputPath>   </PropertyGroup>   <ItemGroup>     <Compile Include="Main.cs" />     <Compile Include="AssemblyInfo.cs" />   </ItemGroup>   <Import Project="Mono.Mcs.targets" /> </Project> The Mono.Mcs.targets file, which is based on the Microsoft.CSharp.targets file, overrides the CoreCompile target: <Project DefaultTargets="Build"          xmlns="http://schemas.microsoft.com/developer/msbuild/2003">     <UsingTask TaskName="ICSharpCode.Build.Tasks.Mcs"                AssemblyFile="ICSharpCode.Build.Tasks.dll"/>         <PropertyGroup>         <MSBuildAllProjects>$(MSBuildAllProjects);Mono.Mcs.targets</MSBuildAllProjects>         <DefaultLanguageSourceExtension>.cs</DefaultLanguageSourceExtension>         <Language>C#</Language>     </PropertyGroup>          <Target Name="CreateManifestResourceNames"/>     <PropertyGroup>         <DebugSymbols Condition=" '$(DebugType)' == 'none' ">false</DebugSymbols>         <DebugType    Condition=" '$(DebugType)' == 'none' "></DebugType>         </PropertyGroup>     <ItemGroup>         <DocFileItem Include="$(DocumentationFile)" Condition="'$(DocumentationFile)'!=''">             <InProject>false</InProject>         </DocFileItem>     </ItemGroup>     <PropertyGroup>         <CoreCompileDependsOn>_ComputeNonExistentFileProperty</CoreCompileDependsOn>     </PropertyGroup>          <Target         Name="CoreCompile"         Inputs="$(MSBuildAllProjects);                 @(Compile);                 @(ManifestResourceWithNoCulture);                 $(ApplicationIcon);                 $(AssemblyOriginatorKeyFile);                 @(ManifestNonResxWithNoCultureOnDisk);                 @(ReferencePath);                 @(CompiledLicenseFile)"         Outputs="@(DocFileItem);                  @(IntermediateAssembly);                  $(NonExistentFile)"         DependsOnTargets="$(CoreCompileDependsOn)"     >                 <Mcs               AdditionalLibPaths="$(AdditionalLibPaths)"               AddModules="@(AddModules)"               AllowUnsafeBlocks="$(AllowUnsafeBlocks)"               CheckForOverflowUnderflow="$(CheckForOverflowUnderflow)"               CodePage="$(CodePage)"               DebugType="$(DebugType)"               DefineConstants="$(DefineConstants)"               DelaySign="$(DelaySign)"               DisabledWarnings="$(NoWarn)"               DocumentationFile="@(DocFileItem)"               EmitDebugInformation="$(DebugSymbols)"               KeyContainer="$(KeyContainerName)"               KeyFile="$(KeyOriginatorFile)"               LangVersion="$(LangVersion)"               MainEntryPoint="$(StartupObject)"               NoConfig="true"               NoLogo="$(NoLogo)"               NoStandardLib="$(NoStdLib)"               Optimize="$(Optimize)"               OutputAssembly="@(IntermediateAssembly)"               References="@(ReferencePath)"               Resources="@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile)"               ResponseFiles="$(CompilerResponseFile)"               Sources="@(Compile)"               TargetType="$(OutputType)"               ToolPath="$(McsToolPath)"               TreatWarningsAsErrors="$(TreatWarningsAsErrors)"               WarningLevel="$(WarningLevel)"               Win32Icon="$(ApplicationIcon)"               Win32Resource="$(Win32Resource)" />     </Target>          <Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" /> </Project> The differences between this is and the standard Microsoft.CSharp.targets file is that a few properties have been removed (NoWarn and UseHostCompilerIfAvailable) and the CreateManifestResourceNames target has essentially been removed, the target is defined, but it does nothing.  This targets file is good enough to compile our console application, as long as we do not add any embedded resources to it. SharpDevelop How does this compare with the .targets files that ship with SharpDevelop?  Since SharpDevelop can target more than just Mono, it supports the older .NET frameworks too, things are a little more complicated.  This will be covered in another post. [Less]