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
-
Install Visual Studio Code:
- Download and install VS Code from Visual Studio Code. Think of it as your coding spaceship—essential for intergalactic development.
-
Install .NET SDK:
- Download and install the latest .NET SDK (8 or 9) from .NET Downloads. This is your fuel for .NET development.
-
Install Python and Jupyter:
- Jupyter requires Python. Install it from python.org.
- Then install Jupyter Notebook using pip:pip install notebook
-
Install .NET Interactive:
- Install the .NET Interactive kernel for Jupyter:dotnet tool install --global Microsoft.dotnet-interactive dotnet interactive jupyter install
- Install the .NET Interactive kernel for Jupyter:
Step 2: Configure VS Code
-
Install the Jupyter Extension:
- Open VS Code, go to the Extensions Marketplace, and search for "Jupyter."
- Install the Jupyter extension.
-
Install the .NET Interactive Notebooks Extension:
- Search for ".NET Interactive Notebooks" in the Extensions Marketplace and install it.
-
Verify Kernel Availability:
- Create a new Jupyter Notebook:
- Open the command palette (
Ctrl+Shift+P
) and selectJupyter: Create New Blank Notebook
. - When prompted, select the
.NET (C#)
kernel.
- Open the command palette (
- Create a new Jupyter Notebook:
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
-
Create a New Console Application:
- Use the .NET CLI:dotnet new console -o MouseJiggler cd MouseJiggler
- Use the .NET CLI:
-
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
-
Build the application:
dotnet build -
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! 😊