# Mono + GTK# + Glade — WSL Setup Guide

## Table of Contents
- [Mono](#mono)
  - [1. Prerequisites](#1-prerequisites)
  - [2. Install Mono](#2-install-mono)
  - [3. Install GTK# (GTK# 3.0, for Ubuntu 24.04)](#3-install-gtk-gtk-30-for-ubuntu-2404)
  - [4. Install Glade (visual UI designer)](#4-install-glade-visual-ui-designer)
  - [5. Optional: libgdiplus (only if using System.Drawing)](#5-optional-libgdiplus-only-if-using-systemdrawing)
  - [6. Compiling & Running](#6-compiling--running)
  - [7. Minimal Working Examples](#7-minimal-working-examples)
  - [8. Custom Output Names, Targets & Exporting DLLs](#8-custom-output-names-targets--exporting-dlls)
  - [9. Common Errors & Fixes](#9-common-errors--fixes)
  - [10. Notes on Alternatives](#10-notes-on-alternatives)
- [OS](#os)
  - [Workflow](#workflow)
  - [OS images checked](#os-images-checked)
  - [OS images to check](#os-images-to-check)


---

## Mono

### 1. Prerequisites
- Windows 11 (or updated Windows 10) with WSL2 and **WSLg** enabled for GUI support
- Ubuntu 24.04 (noble) or similar WSL distro

Check WSLg is active:
```bash
echo $DISPLAY
```
Should return something like `:0`. If empty, GUI apps won't display.

---

### 2. Install Mono

```bash
sudo apt update
sudo apt install mono-complete
```

Verify:
```bash
mono --version
mcs --version
```

---

### 3. Install GTK# (GTK# 3.0, for Ubuntu 24.04)

> Note: `gtk-sharp2` is **not available** on Ubuntu 24.04 (noble). Use `gtk-sharp3` instead.

```bash
sudo add-apt-repository universe
sudo apt update
sudo apt install gtk-sharp3
```

Verify the package is registered:
```bash
pkg-config --list-all | grep gtk-sharp
```
Expected output:
gtk-sharp-3.0 Gtk - Gtk
---

### 4. Install Glade (visual UI designer)

```bash
sudo apt install glade
```

Launch it:
```bash
glade
```
Design your UI visually, then save as `yourfile.glade` (XML format).

---

### 5. Optional: libgdiplus (only if using System.Drawing)

Only needed if your code uses `System.Drawing.Bitmap`, `Graphics`, etc. (not required for plain GTK#/Glade apps):

```bash
sudo apt install libgdiplus
```

---

### 6. Compiling & Running

#### Plain console C# program
```bash
mcs myprogram.cs
mono myprogram.exe
```

#### GTK# 3.0 program (no Glade)
```bash
mcs -pkg:gtk-sharp-3.0 myapp.cs
mono myapp.exe
```

#### GTK# 3.0 program using a Glade file
```bash
mcs -pkg:gtk-sharp-3.0 -pkg:glade-sharp-3.0 myapp.cs
mono myapp.exe
```
Make sure the `.glade` file referenced in code sits in the same folder (or update the path in `new Builder("...")`).

---

### 7. Minimal Working Examples

#### Hello World (console)
```csharp
using System;

class Hello {
    static void Main() {
        Console.WriteLine("Hello from Mono in WSL!");
    }
}
```
```bash
mcs hello.cs
mono hello.exe
```

#### Hello World (GTK# window, no Glade)
```csharp
using System;
using Gtk;

class GtkCheck {
    static void Main() {
        Application.Init();
        var win = new Window("Hello GTK#3");
        win.SetDefaultSize(300, 200);
        win.DeleteEvent += (o, args) => Application.Quit();

        var button = new Button("Click me");
        button.Clicked += (o, args) => Console.WriteLine("Clicked!");
        win.Add(button);

        win.ShowAll();
        Application.Run();
    }
}
```
```bash
mcs -pkg:gtk-sharp-3.0 gtkcheck.cs
mono gtkcheck.exe
```

#### Loading a UI built in Glade
```csharp
using System;
using Gtk;

class Program {
    static void Main() {
        Application.Init();
        var builder = new Builder("myui.glade");
        builder.Autoconnect(new Program());

        var win = (Window)builder.GetObject("window1");
        win.DeleteEvent += (o, args) => Application.Quit();
        win.ShowAll();

        Application.Run();
    }
}
```
```bash
mcs -pkg:gtk-sharp-3.0 -pkg:glade-sharp-3.0 program.cs
mono program.exe
```

---

### 8. Custom Output Names, Targets & Exporting DLLs

By default, `mcs file.cs` names the output after the source file (`file.exe`). You can control this with `-out:` and change what kind of binary is produced with `-target:`.

#### 8.1 Custom output name
```bash
mcs -pkg:gtk-sharp-3.0 Program.cs -out:MyCustomApp.exe
```
Run it the same way:
```bash
mono MyCustomApp.exe
```

#### 8.2 `-target` options
| Target | Produces | Notes |
|---|---|---|
| `exe` (default) | Console executable | Shows a console window when run on Windows |
| `winexe` | Windows GUI executable | No console window — correct choice for GTK#/Glade GUI apps distributed on Windows |
| `library` | `.dll` class library | No `Main` entry point required to run directly; used by other programs |
| `module` | `.netmodule` | Rarely used; for combining into a single assembly later |

Your example, building a windowed GUI executable with a custom name:
```bash
mcs -target:winexe -pkg:gtk-sharp-3.0 Program.cs -out:programwin.exe
```
This produces `programwin.exe`, which on Windows will run without popping up a console window alongside your GTK window.

#### 8.3 Exporting a DLL

If you want to package reusable code (helper classes, business logic, etc.) as a library instead of a standalone app:

```bash
mcs -target:library Program.cs -out:MyLibrary.dll
```

- No `Main()` method is required in a `library` target (though it's fine if one class in your project has one — it just won't be used as an entry point for the DLL itself).
- This creates `MyLibrary.dll`, a Mono/.NET assembly that other C# programs can reference.

#### 8.4 Using a DLL in another program

Suppose `MyLibrary.dll` contains:
```csharp
// MyLibrary.cs
namespace MyLib {
    public class Greeter {
        public string Greet(string name) => $"Hello, {name}!";
    }
}
```
Compiled with:
```bash
mcs -target:library MyLibrary.cs -out:MyLibrary.dll
```

Then in a separate consumer program:
```csharp
// ConsumerApp.cs
using System;
using MyLib;

class ConsumerApp {
    static void Main() {
        var greeter = new Greeter();
        Console.WriteLine(greeter.Greet("World"));
    }
}
```

Compile it while referencing the DLL with `-r:`:
```bash
mcs ConsumerApp.cs -r:MyLibrary.dll -out:ConsumerApp.exe
```

Run it (make sure `MyLibrary.dll` is in the same folder as `ConsumerApp.exe`, or on Mono's library search path):
```bash
mono ConsumerApp.exe
```

#### 8.5 Combining `-target:library` with GTK# packages
If your DLL itself uses GTK# types (e.g., a shared custom widget), include the package flag when building the library too:
```bash
mcs -target:library -pkg:gtk-sharp-3.0 MyGtkWidgets.cs -out:MyGtkWidgets.dll
```
And reference both the package and the DLL when compiling the consumer:
```bash
mcs -pkg:gtk-sharp-3.0 ConsumerApp.cs -r:MyGtkWidgets.dll -out:ConsumerApp.exe
```

#### 8.6 Quick reference
```bash
# Console exe, custom name
mcs Program.cs -out:myapp.exe

# Windowed (no console) exe, custom name
mcs -target:winexe -pkg:gtk-sharp-3.0 Program.cs -out:programwin.exe

# Class library (DLL)
mcs -target:library Library.cs -out:MyLibrary.dll

# Program referencing that DLL
mcs Consumer.cs -r:MyLibrary.dll -out:Consumer.exe
```

#### 8.7 Running the compiled .exe on Windows (outside WSL)

Compiling in WSL produces a `.exe` that targets the .NET/Mono runtime — it is **not** a native Windows binary, and it will not run on Windows by itself. Two things are needed:

**1. Install a runtime on the Windows machine**

Pick one:
- **Mono runtime for Windows** — install the [Mono for Windows](https://www.mono-project.com/download/stable/) package so `.exe` files built with `mcs` can run via the Mono runtime. After install, you can either double-click the `.exe` (Mono associates itself with `.exe` files) or run it explicitly:
```powershell
  mono programwin.exe
```
- **.NET Framework / .NET runtime** — for simple GTK#-free console apps, the .exe may also run under an installed .NET runtime, but GTK# apps specifically require Mono's GTK# libraries, so the Mono for Windows install is the reliable option.

**2. Copy the required DLLs alongside the .exe**

Your compiled `.exe` references managed DLLs at runtime (not just at compile time). Anything you referenced with `-r:` or `-pkg:` must physically travel with the `.exe`:

- Any custom library you built, e.g. `MyLibrary.dll` or `MyGtkWidgets.dll`
- GTK# binding assemblies your app depends on (typically already provided by installing Mono for Windows, since it bundles the GTK# runtime — but if you used a nonstandard package, copy its DLL too)
- Your `.glade` file, if the app loads one via `Builder("myui.glade")` — this isn't a DLL but is just as required; it must sit next to the `.exe` at the same relative path your code expects

Minimum folder layout to copy over to Windows:
programwin.exe
MyLibrary.dll (any custom DLLs you referenced with -r:)
myui.glade (if using Glade)

**Common pitfall:** a program that runs fine in WSL but fails on Windows with `FileNotFoundException` or `Could not load file or assembly` almost always means a referenced DLL (or the `.glade` file) wasn't copied over, or Mono for Windows isn't installed.

---

### 9. Common Errors & Fixes

| Error | Cause | Fix |
|---|---|---|
| `File does not contain a valid CIL image` | Ran `mono` on `.cs` source instead of compiled `.exe` | Compile first: `mcs file.cs`, then `mono file.exe` |
| `CS0246: type or namespace 'Gtk' could not be found` | Missing package reference during compile | Add `-pkg:gtk-sharp-3.0` to `mcs` command |
| `CS0103: name 'Console' does not exist` | Missing `using System;` | Add `using System;` at top of file |
| `Unable to locate package gtk-sharp2` | Package dropped in Ubuntu 24.04 | Use `gtk-sharp3` instead |
| `DllNotFoundException: libgdiplus` | Code uses `System.Drawing` without the lib installed | `sudo apt install libgdiplus` |
| `Could not load file or assembly 'MyLibrary.dll'` | DLL not in same folder / not found | Place DLL next to the `.exe`, or set `MONO_PATH` |
| `FileNotFoundException` / `Could not load file or assembly` (on Windows) | Runtime not installed, or referenced DLL/.glade not copied alongside the .exe | Install Mono for Windows; copy all `-r:` DLLs and `.glade` files into the same folder as the `.exe` |

---

### 10. Notes on Alternatives

GTK# is a legacy, lightly-maintained binding. For new projects, consider:
- **Avalonia UI** — modern, XAML-based, cross-platform, actively maintained
```bash
  sudo apt install dotnet-sdk-8.0
  dotnet new install Avalonia.Templates
  dotnet new avalonia.app -o MyApp
```

Use GTK#/Mono/Glade for legacy projects or learning; use Avalonia + `dotnet` for anything new and long-term.


Personal note:

Compile note:
    to compile the cs file
        mcs NAME_OF_THE_FILE.cs 
    for GTK appilcation
        mcs -pkg:gtk-sharp-3.0 NAME_OF_THE_FILE.cs
    custom output name / windowed exe
        mcs -target:winexe -pkg:gtk-sharp-3.0 NAME_OF_THE_FILE.cs -out:CUSTOM_NAME.exe
    export as DLL
        mcs -target:library NAME_OF_THE_FILE.cs -out:CUSTOM_NAME.dll
    use a DLL in another program
        mcs Consumer.cs -r:CUSTOM_NAME.dll -out:Consumer.exe



to run note:
    same for all cases
        mono NAME_OF_THE_FILE.exe

## OS

To test the application/setup across different Linux distributions, I used **Ventoy** to create a multiboot USB drive. Ventoy lets you copy multiple ISO files onto a single USB stick and choose which one to boot at startup, without needing to reformat or re-flash the drive for each OS.

### Workflow
1. Install Ventoy on the target USB drive.
2. Copy the desired `.iso` files directly onto the Ventoy partition (no extraction needed).
3. Boot from the USB, select the ISO from the Ventoy boot menu, and test the OS live or install it.

### OS images checked
- Fedora-Workstation-Live-44-1.7.x86_64
- lubuntu-26.04-desktop-amd64
- xubuntu-25.10-desktop-amd64

### OS images to check
- antiX-26_x64-full
- xubuntu-26.04-minimal-amd64