diff --git a/Cargo.toml b/Cargo.toml
index 3ffe8c1447f603cb07d6aa811f82ce931d79df8d..ec5f25f85512c03b1b1db74912c3aeafb769c6d8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,10 @@ version = "0.1.0"
 authors = ["Dorian Weber <weber@informatik.hu-berlin.de>"]
 edition = "2018"
 
+[features]
+default = ["mock"]
+mock = []
+
 [profile.release]
 lto = true
 opt-level = 3
diff --git a/build.rs b/build.rs
index c1460dd0a70582b3033ec323205cb569b4325805..2131f3e40013173d535b39f5940dd66512fbbb05 100644
--- a/build.rs
+++ b/build.rs
@@ -105,5 +105,7 @@ fn main() {
 		println!("cargo:warning=This library will still work, \
 	          the C++ benchmarks will not!");
 		println!("cargo:warning={}", msg);
+	} else {
+		println!("cargo:rustc-cfg=feature=\"odemx\"");
 	}
 }
diff --git a/examples/barbershop.rs b/examples/barbershop.rs
index 20e1d0399f07a153e541e30533797303253ca9d5..2b18c1ca92d370c3b3f2a18c088f55fc0deedab6 100644
--- a/examples/barbershop.rs
+++ b/examples/barbershop.rs
@@ -1,24 +1,24 @@
 use simcore_rs::{Time, SimContext, Facility, RandomVar, Process};
-use rand::{rngs::SmallRng, SeedableRng, Rng};
+use rand::Rng;
 use std::cell::RefCell;
 
+// helper constants
+const SEED_A: u64  = 100000;
+const SEED_S: u64  = 200000;
+
 /// Globally shared data.
-struct Shared {
-	rng_a: RefCell<SmallRng>,
-	rng_s: RefCell<SmallRng>,
+struct Shared<R: Rng> {
+	rng_a: RefCell<R>,
+	rng_s: RefCell<R>,
 	joe: Facility,
 	wait_time: RandomVar
 }
 
-// helper constants
-const SEED_A: u64  = 100000;
-const SEED_S: u64  = 200000;
-
 /// Customer process with access to the barber and a random processing delay.
 struct Customer;
 
 impl Customer {
-	pub async fn actions(self, sim: SimContext<'_,Shared>) {
+	pub async fn actions(self, sim: SimContext<'_,Shared<impl Rng>>) {
 		// access the barber and record the time for the report
 		let arrival_time = sim.now();
 		sim.shared().joe.seize().await;
@@ -33,7 +33,7 @@ impl Customer {
 	}
 }
 
-async fn barbershop(sim: SimContext<'_,Shared>, duration: Time) {
+async fn barbershop<'b>(sim: SimContext<'b, Shared<impl Rng + 'b>>, duration: Time) {
 	// activate a process to generate the customers
 	sim.activate(async move {
 		loop {
@@ -54,6 +54,8 @@ async fn barbershop(sim: SimContext<'_,Shared>, duration: Time) {
 
 #[cfg(not(test))]
 fn main() {
+	use rand::{rngs::SmallRng, SeedableRng};
+	
 	let result = simcore_rs::simulation(
 		// global data
 		Shared {
@@ -81,9 +83,9 @@ mod slx;
 mod bench {
 	use super::*;
 	use criterion::{Criterion, BenchmarkId, BatchSize, PlotConfiguration,
-	                AxisScale, SamplingMode, criterion_group};
-	use std::time::Duration;
+	                AxisScale, criterion_group};
 	
+	#[cfg(feature = "odemx")]
 	mod odemx {
 		use std::os::raw::c_double;
 		
@@ -93,11 +95,13 @@ mod bench {
 		}
 	}
 	#[cfg(windows)]
-	const SLX_PATH: &'static str = "C:/Wolverine/SLX/se64.exe";
+	const SLX_PATH: &'static str = "C:\\Wolverine\\SLX";
 	const RANGE: u32 =   10;
 	const STEP: Time = 1000.0;
 	
 	fn barbershop_bench(c: &mut Criterion) {
+		use rand::{rngs::SmallRng, SeedableRng};
+		
 		let mut group = c.benchmark_group("Barbershop");
 		
 		// set-up the benchmark parameters
@@ -106,16 +110,26 @@ mod bench {
 			PlotConfiguration::default()
 				.summary_scale(AxisScale::Logarithmic)
 		);
-		//group.sampling_mode(SamplingMode::Linear);
-		//group.measurement_time(Duration::from_secs(300));
+		// group.sampling_mode(criterion::SamplingMode::Linear);
+		// group.measurement_time(std::time::Duration::from_secs(300));
 		
-		if !cfg!(windows) {
-			println!("Not running under Windows, skipping SLX benchmarks!");
-		}
+		#[cfg(windows)]
+		let slx_path = {
+			let path = slx::slx_version(SLX_PATH);
+			
+			if path.is_none() {
+				println!("SLX not found, skipping SLX benchmarks!");
+			} else {
+				println!("Using SLX program at {:?}", path.as_ref().unwrap());
+			}
+			
+			path
+		};
 		
 		// vary in the length of the simulation run
 		for sim_duration in (0..RANGE).map(|c| Time::from(1 << c)*STEP) {
-			#[cfg(windows)] {
+			#[cfg(windows)]
+			if let Some(path) = slx_path.as_ref() {
 				let duration = sim_duration.to_string();
 				let args = [
 					"/silent",
@@ -133,7 +147,7 @@ mod bench {
 					BenchmarkId::new("SLX", sim_duration),
 					|b| b.iter_custom(|iters|
 						slx::slx_bench(
-							SLX_PATH,
+							path.as_os_str(),
 							&args,
 							iters as usize
 						).expect("couldn't benchmark the SLX program")
@@ -142,6 +156,7 @@ mod bench {
 			}
 			
 			// benchmark the C++ implementation
+			#[cfg(feature = "odemx")]
 			group.bench_function(
 				BenchmarkId::new("ODEMx", sim_duration),
 				|b| b.iter(
diff --git a/examples/ferry.rs b/examples/ferry.rs
index ac8dadecbab2dbf7b611c9b216678029a241329e..6c899954a1d08bb33c87cd8a53897427322d66c9 100644
--- a/examples/ferry.rs
+++ b/examples/ferry.rs
@@ -159,9 +159,9 @@ mod slx;
 mod bench {
 	use super::*;
 	use criterion::{Criterion, BenchmarkId, BatchSize, PlotConfiguration,
-	                AxisScale, SamplingMode, criterion_group};
-	use std::time::Duration;
+	                AxisScale, criterion_group};
 	
+	#[cfg(feature = "odemx")]
 	mod odemx {
 		use std::os::raw::{c_double, c_uint};
 		
@@ -171,7 +171,7 @@ mod bench {
 		}
 	}
 	#[cfg(windows)]
-	const SLX_PATH: &'static str = "C:/Wolverine/SLX/se64.exe";
+	const SLX_PATH: &'static str = "C:\\Wolverine\\SLX";
 	const RANGE: u32 =   10;
 	const STEP: Time = 1000.0;
 	
@@ -184,16 +184,26 @@ mod bench {
 			PlotConfiguration::default()
 				.summary_scale(AxisScale::Logarithmic)
 		);
-		//group.sampling_mode(SamplingMode::Linear);
-		//group.measurement_time(Duration::from_secs(600));
+		// group.sampling_mode(criterion::SamplingMode::Linear);
+		// group.measurement_time(std::time::Duration::from_secs(600));
 		
-		if !cfg!(windows) {
-			println!("Not running under Windows, skipping SLX benchmarks!");
-		}
+		#[cfg(windows)] 
+		let slx_path = {
+			let path = slx::slx_version(SLX_PATH);
+			
+			if path.is_none() {
+				println!("SLX not found, skipping SLX benchmarks!");
+			} else {
+				println!("Using SLX program at {:?}", path.as_ref().unwrap());
+			}
+			
+			path
+		};
 		
 		// vary in the length of the simulation run
 		for (i, sim_duration) in (0..RANGE).map(|c| Time::from(1 << c)*STEP).enumerate() {
-			#[cfg(windows)] {
+			#[cfg(windows)]
+			if let Some(path) = slx_path.as_ref() {
 				let duration = sim_duration.to_string();
 				let args = [
 					"/silent",
@@ -211,7 +221,7 @@ mod bench {
 					BenchmarkId::new("SLX", sim_duration),
 					|b| b.iter_custom(|iters|
 						slx::slx_bench(
-							SLX_PATH,
+							path.as_os_str(),
 							&args,
 							iters as usize
 						).expect("couldn't benchmark the SLX program")
@@ -220,6 +230,7 @@ mod bench {
 			}
 			
 			// benchmark the C++ implementation
+			#[cfg(feature = "odemx")]
 			group.bench_function(
 				BenchmarkId::new("ODEMx", sim_duration),
 				|b| b.iter(|| unsafe {
diff --git a/examples/philosophers.rs b/examples/philosophers.rs
index df1d7d347269cddd0c961dab92246b91dc5668db..e166a83161ba6370ae37861dbc68fc4cb0c3d870 100644
--- a/examples/philosophers.rs
+++ b/examples/philosophers.rs
@@ -154,9 +154,9 @@ mod slx;
 mod bench {
 	use super::*;
 	use criterion::{Criterion, BenchmarkId, PlotConfiguration, AxisScale,
-	                SamplingMode, criterion_group};
-	use std::time::Duration;
+	                criterion_group};
 	
+	#[cfg(feature = "odemx")]
 	mod odemx {
 		use std::os::raw::c_uint;
 		
@@ -166,7 +166,7 @@ mod bench {
 		}
 	}
 	#[cfg(windows)]
-	const SLX_PATH: &'static str = "C:/Wolverine/SLX/se64.exe";
+	const SLX_PATH: &'static str = "C:\\Wolverine\\SLX";
 	const RANGE:   u32 = 10;
 	const STEP:  usize =  3;
 	
@@ -179,16 +179,26 @@ mod bench {
 			PlotConfiguration::default()
 				.summary_scale(AxisScale::Logarithmic)
 		);
-		//group.sampling_mode(SamplingMode::Linear);
-		//group.measurement_time(Duration::from_secs(900));
+		// group.sampling_mode(SamplingMode::Linear);
+		// group.measurement_time(std::time::Duration::from_secs(900));
 		
-		if !cfg!(windows) {
-			println!("Not running under Windows, skipping SLX benchmarks!");
-		}
+		#[cfg(windows)]
+		let slx_path = {
+			let path = slx::slx_version(SLX_PATH);
+			
+			if path.is_none() {
+				println!("SLX not found, skipping SLX benchmarks!");
+			} else {
+				println!("Using SLX program at {:?}", path.as_ref().unwrap());
+			}
+			
+			path
+		};
 		
 		// vary the number of performed reruns in each experiment
 		for experiment_count in (0..RANGE).map(|c| (1 << c)*STEP) {
-			#[cfg(windows)] {
+			#[cfg(windows)]
+			if let Some(path) = slx_path.as_ref() {
 				let count = experiment_count.to_string();
 				let args = [
 					"/silent",
@@ -202,12 +212,11 @@ mod bench {
 				];
 				
 				// benchmark the SLX implementation
-				group.sampling_mode(SamplingMode::Linear);
 				group.bench_function(
 					BenchmarkId::new("SLX", experiment_count),
 					|b| b.iter_custom(|iters|
 						slx::slx_bench(
-							SLX_PATH,
+							path.as_os_str(),
 							&args,
 							iters as usize
 						).expect("couldn't benchmark the SLX program")
@@ -216,7 +225,7 @@ mod bench {
 			}
 			
 			// benchmark the C++ implementation
-			group.sampling_mode(SamplingMode::Auto);
+			#[cfg(feature = "odemx")]
 			group.bench_function(
 				BenchmarkId::new("ODEMx", experiment_count),
 				|b| b.iter(|| unsafe {
@@ -228,7 +237,6 @@ mod bench {
 			);
 			
 			// benchmark the Rust implementation
-			group.sampling_mode(SamplingMode::Linear);
 			group.bench_function(
 				BenchmarkId::new("Rust", experiment_count),
 				|b| b.iter(||
diff --git a/examples/slx/mod.rs b/examples/slx/mod.rs
index f38c7cd1ad9006fe54c2a3f687f526c62dd67e05..089844acc2f21dc43004abc236999130c8acb0d7 100644
--- a/examples/slx/mod.rs
+++ b/examples/slx/mod.rs
@@ -1,11 +1,12 @@
-use std::{process::Command, time::Duration, iter::once};
+use std::{process::Command, time::Duration, path::Path, iter::once};
+use std::ffi::{OsString, OsStr};
 use itertools::Itertools;
 
 /// Runs the SLX runtime environment once for an SLX program that measures its
 /// own duration and returns it on the standard output.
 /// 
 /// Errors during this execution are returned back to the caller.
-fn slx_run_once(program: &str, arguments: &[&str], iterations: usize) -> Result<Duration, (i32, String)> {
+fn slx_run_once(program: &OsStr, arguments: &[&str], iterations: usize) -> Result<Duration, (i32, String)> {
 	// start the SLX runtime and wait for its return
 	let rc = Command::new(program)
 		.args(arguments)
@@ -45,7 +46,7 @@ fn slx_run_once(program: &str, arguments: &[&str], iterations: usize) -> Result<
 /// 
 /// The SLX program in question has to report its own real-time duration using
 /// the standard output.
-pub fn slx_bench(program: &str, arguments: &[&str], iterations: usize) -> Result<Duration, String> {
+pub fn slx_bench(program: &OsStr, arguments: &[&str], iterations: usize) -> Result<Duration, String> {
 	// try to complete the iterations in a single run of the SLX program
 	slx_run_once(program, arguments, iterations)
 		.or_else(|(code, desc)| {
@@ -77,3 +78,25 @@ pub fn slx_bench(program: &str, arguments: &[&str], iterations: usize) -> Result
 			}
 		})
 }
+
+/// Attempts to find the best SLX version for the benchmarks, falling back on
+/// the free version if no SLX license can be found.
+pub fn slx_version(base: impl AsRef<Path>) -> Option<OsString> {
+	if base.as_ref().exists() {
+		let programs = ["se64.exe", "se32.exe", "sse.exe"];
+		let args = ["/silent", "/noicon", "/nowarn", "/noxwarn", "bad_file.slx"];
+		
+		for path in programs.iter().map(|p| base.as_ref().join(p)) {
+			match Command::new(&path).args(&args).status() {
+				Err(_) => continue,
+				Ok(rc) => if let Some(code) = rc.code() {
+					if code == -10003 {
+						return Some(path.into_os_string())
+					}
+				}
+			}
+		}
+	}
+	
+	None
+}