My initial impression is that there is nothing in your application that would make F# a compelling choice. That said, here are a few examples of ways you could use F# features to simplify your logic:
// Bring the namespace into scope, like using in C#
open System.Diagnostics
// Methods with descriptive parameter names are good
let Create counter_category counter_name =
match PerformanceCounterCategory.Exists(counter_category) with
// Using a guard eliminates a second level of if/then or matching
| true when PerformanceCounterCategory.CounterExists(counter_name, counter_category)
-> printfn "Performance counter %A already exists" counter_name
| true -> printfn "Performance counter category %A already exists" counter_category
// _ is effectively an "else" clause, or a switch's default
| _ -> let CounterDatas = new CounterCreationDataCollection()
let cdCounter1 = new CounterCreationData()
cdCounter1.CounterName <- counter_name
cdCounter1.CounterType <- PerformanceCounterType.NumberOfItems64
CounterDatas.Add(cdCounter1) |> ignore
printf "Creating category and counter: "
PerformanceCounterCategory.Create(counter_category, "", PerformanceCounterCategoryType.SingleInstance, CounterDatas) |> ignore
printfn "Success."
// Fake implementations, left as an exercise
let Scan counter_category counter_name directory =
printfn "%s %s %s %s" "Scan" counter_category counter_name directory
let Remove counter_category counter_name =
printfn "%s %s %s" "Remove" counter_category counter_name
// The only place we need to specify a type
let ParseArgs (args : string array) =
let app = args.[0]
match args.Length with
| 1 -> printfn "Usage: %A [create|scan|remove]" app
// By pairing up the op and number of arguments...
| n -> match args.[1],n with
// We can easily handle good cases...
| "create",4 -> Create args.[2] args.[3]
| "scan",5 -> Scan args.[2] args.[3] args.[4]
| "remove",4 -> Remove args.[2] args.[3]
// And bad cases...
| "create",_ -> printfn "Usage: %A create <CounterCategory> <CounterName>" app
| "scan",_ -> printfn "Usage: %A scan <CounterCategory> <CounterName> <Directory>" app
| "remove",_ -> printfn "Usage: %A remove <CounterCategory> <CounterName>" app
| op,_ -> printfn "Invalid operation: %A" op
// Sys.argv is just for compatibility
ParseArgs (System.Environment.GetCommandLineArgs())