Search This Blog

23 November, 2024

Using Jupyter Notebooks in VS Code for C# Development and Production Scripting

Using Jupyter Notebooks in VS Code for C# Development and Production Scripting

Introduction

Jupyter Notebooks are a game-changer for interactive code development, documentation, and experimentation. While they're most commonly associated with Python, you can also use them for C# development with the .NET Interactive kernel. This opens up an exciting world where you can run C# code interactively, experiment with logic, and even document your workflow all in one place.

In this article, we’ll walk you through setting up Jupyter Notebooks in Visual Studio Code for C# development. We’ll build a dynamic mouse jiggler application to demonstrate the process and then export it as a production-ready C# console application. And yes, you can pretend it's for "testing purposes" at the office!

We’ll be using .NET 8 or 9 and file-scoped namespaces to keep our code modern and concise.

Why Use Jupyter Notebooks in VS Code for C#?

Jupyter Notebooks offer several key advantages for C# development:

  • Interactive Development: Test small code snippets and see results instantly. It’s like a sandbox, but without the messy sand.
  • Documentation Integration: Write markdown and executable code side-by-side. Your code becomes self-documenting—how neat is that?
  • Experimentation: Tweak, refine, and fine-tune your code in an interactive environment before committing to production.
  • Production Readiness: Once you’ve refined your code, you can easily export it into a standalone application.

Setting Up Jupyter Notebooks for C# in VS Code

Step 1: Install Prerequisites

  1. Install Visual Studio Code:

    • Download and install VS Code from Visual Studio Code. Think of it as your coding spaceship—essential for intergalactic development.
  2. Install .NET SDK:

    • Download and install the latest .NET SDK (8 or 9) from .NET Downloads. This is your fuel for .NET development.
  3. Install Python and Jupyter:

    • Jupyter requires Python. Install it from python.org.
    • Then install Jupyter Notebook using pip:
      pip install notebook
  4. Install .NET Interactive:

    • Install the .NET Interactive kernel for Jupyter:
      dotnet tool install --global Microsoft.dotnet-interactive dotnet interactive jupyter install

Step 2: Configure VS Code

  1. Install the Jupyter Extension:

    • Open VS Code, go to the Extensions Marketplace, and search for "Jupyter."
    • Install the Jupyter extension.
  2. Install the .NET Interactive Notebooks Extension:

    • Search for ".NET Interactive Notebooks" in the Extensions Marketplace and install it.
  3. Verify Kernel Availability:

    • Create a new Jupyter Notebook:
      • Open the command palette (Ctrl+Shift+P) and select Jupyter: Create New Blank Notebook.
      • When prompted, select the .NET (C#) kernel.

Building a Dynamic Mouse Jiggler in Jupyter Notebook

Let’s create a dynamic mouse jiggler—because who doesn’t want to keep their computer active while they enjoy a coffee break?

Step 1: Import Libraries and Declare Windows API Methods

To interact with the mouse, we’ll use user32.dll. Start by importing the required libraries and defining the necessary PInvoke methods. Select the code section and add the following:

using System; using System.Runtime.InteropServices; using System.Threading; [DllImport("user32.dll")] static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] static extern void GetCursorPos(out POINT lpPoint); [DllImport("user32.dll")] static extern short GetAsyncKeyState(int vKey); public struct POINT { public int X; public int Y; }

Once the code is added, click the "run" button on the left to verify everything works. There’s no output yet—it's just setting up.

Step 2: Implement Smooth Mouse Movement

Next, let's add logic to smoothly move the mouse back and forth, giving it a "glide" feel.

Create a new section and add this code:

static void MoveMouseSmoothly(int startX, int startY, int endX, int endY, int durationMs) { int steps = 100; // Number of steps for smooth motion double stepTime = (double)durationMs / steps; for (int i = 1; i <= steps; i++) { double t = (double)i / steps; // Linear interpolation factor int currentX = (int)(startX + t * (endX - startX)); int currentY = (int)(startY + t * (endY - startY)); SetCursorPos(currentX, currentY); Thread.Sleep((int)stepTime); } }

Step 3: Add Keyboard Listener for Termination

Let’s make sure the program stops when we press the Escape key. This code listens for the Escape key in a separate thread.

Add this to your next code section:

const int VK_ESCAPE = 0x1B; static bool keepRunning = true; static void KeyListener() { while (keepRunning) { if ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) { Console.WriteLine("Escape key detected. Stopping..."); keepRunning = false; } Thread.Sleep(100); // Reduce CPU usage } }

Step 4: Combine Logic in a Main Method

Now, let’s put everything together. This will create the main functionality to jiggle the mouse based on the current position.

Add the following code to your next section and hit the run button:

Console.WriteLine("Mouse Dynamic Jiggle Simulation"); Console.WriteLine("Press 'Escape' to stop the application."); // Start a thread to listen for the Escape key Thread keyListenerThread = new Thread(KeyListener); keyListenerThread.Start(); // Jiggle parameters int offsetX = 50; // Move 50 pixels left/right int offsetY = 0; // No vertical movement int intervalMinutes = 1; // Move every 1 minute while (keepRunning) { // Get the current mouse position GetCursorPos(out POINT currentPosition); Console.WriteLine($"Current Mouse Position: X={currentPosition.X}, Y={currentPosition.Y}"); // Jiggle the mouse relative to the current position MoveMouseSmoothly(currentPosition.X, currentPosition.Y, currentPosition.X + offsetX, currentPosition.Y + offsetY, 1000); // Brief pause before moving back Thread.Sleep(1000); // Move back to the original position MoveMouseSmoothly(currentPosition.X + offsetX, currentPosition.Y + offsetY, currentPosition.X, currentPosition.Y, 1000); // Wait for the interval before repeating, unless Escape is pressed if (keepRunning) { Console.WriteLine($"Waiting for {intervalMinutes} minutes..."); for (int i = 0; i < intervalMinutes * 60; i++) { Thread.Sleep(1000); if (!keepRunning) break; } } } Console.WriteLine("Application stopped.");

Exporting the Code to a Production-Ready C# Application

Once you’ve got the jiggling mouse working, you’ll want to make it a proper application.

Step 1: Copy Code into a New C# Project

  1. Create a New Console Application:

    • Use the .NET CLI:
      dotnet new console -o MouseJiggler cd MouseJiggler
  2. Add the Code to Program.cs: Use a file-scoped namespace to keep things tidy and modern:

    using System; using System.Runtime.InteropServices; using System.Threading; class Program { // Import necessary methods from user32.dll [DllImport("user32.dll")] static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] static extern void GetCursorPos(out POINT lpPoint); [DllImport("user32.dll")] static extern short GetAsyncKeyState(int vKey); // Struct for cursor position public struct POINT { public int X; public int Y; } // Escape key virtual-key code const int VK_ESCAPE = 0x1B; static bool keepRunning = true; static void Main(string[] args) { Console.WriteLine("Mouse Dynamic Jiggle Simulation"); Console.WriteLine("Press 'Escape' to stop the application."); // Start a thread to listen for the Escape key Thread keyListenerThread = new Thread(KeyListener); keyListenerThread.Start(); // Jiggle parameters int offsetX = 50; // Move 50 pixels left/right int offsetY = 0; // No vertical movement int intervalMinutes = 1; // Move every 1 minutes while (keepRunning) { // Get the current mouse position GetCursorPos(out POINT currentPosition); Console.WriteLine($"Current Mouse Position: X={currentPosition.X}, Y={currentPosition.Y}"); // Jiggle the mouse relative to the current position MoveMouseSmoothly(currentPosition.X, currentPosition.Y, currentPosition.X + offsetX, currentPosition.Y + offsetY, 1000); // Brief pause before moving back Thread.Sleep(1000); // Move back to the original position MoveMouseSmoothly(currentPosition.X + offsetX, currentPosition.Y + offsetY, currentPosition.X, currentPosition.Y, 1000); // Wait for the interval before repeating, unless Escape is pressed if (keepRunning) { Console.WriteLine($"Waiting for {intervalMinutes} minutes..."); for (int i = 0; i < intervalMinutes * 60; i++) { Thread.Sleep(1000); if (!keepRunning) break; } } } Console.WriteLine("Application stopped."); } static void MoveMouseSmoothly(int startX, int startY, int endX, int endY, int durationMs) { int steps = 100; // Number of steps for smoothness double stepTime = (double)durationMs / steps; // Time per step in ms for (int i = 1; i <= steps; i++) { if (!keepRunning) break; // Calculate the next position using linear interpolation double t = (double)i / steps; int currentX = (int)(startX + t * (endX - startX)); int currentY = (int)(startY + t * (endY - startY)); // Set cursor position SetCursorPos(currentX, currentY); // Simulate delay for smooth movement Thread.Sleep((int)stepTime); } } static void KeyListener() { while (keepRunning) { // Check if the Escape key is pressed if ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) { Console.WriteLine("Escape key detected. Stopping..."); keepRunning = false; break; } Thread.Sleep(100); // Small delay to reduce CPU usage } } }

Step 2: Build and Run the Application

  1. Build the application:

    dotnet build
  2. Run the application:

    dotnet run

Conclusion

Jupyter Notebooks allow for an interactive, real-time development experience, and integrating them with Visual Studio Code makes it even better for C# development. It’s perfect for experimenting, documenting, and quickly testing small code snippets—without all the hassle of compiling each time. And when you’re ready, you can export your work as a production-ready application.

Happy coding, and may your mouse jiggle forever! 😊