Executing C# in PowerShell
by Ethan Alexander Shulman (February 10, 2024)

PowerShell is a high level console shell that is cross platform, it comes with Windows 10/11 but it can also be installed on Linux/Mac. PowerShell is based on .NET and can compile and interface with C# all within a single PowerShell script. In this post today I'm going to cover doing some basic automation using C# in PowerShell.


Compiling and Executing C#
Compiling C# into PowerShell involves using the Add-Type cmdlet to add a C# class to the PowerShell .NET instance. Once your class is compiled you can instantiate the class and call functions straight from PowerShell. To start here is a example that prints 'Hello PowerShell' to the console by a static function or creating an object to run the function.
Add-Type -TypeDefinition @" using System; public class CSharpClass { public void Hello() { Console.WriteLine("Hello PowerShell!"); } public static void HelloStatic() { Console.WriteLine("Hello PowerShell, I'm static!"); } } "@ $csclass = New-Object CSharpClass $csclass.Hello(); [CSharpClass]::HelloStatic();
Download Hello World Script
One key thing you need to know is that you can only add the same class once per PowerShell instance, if you change the C# and try to run it again in the same shell it will fail. This is because once you add a type with Add-Type it cannot be removed until you exit and restart PowerShell. Because of this it's suggested you mainly run scripts through double clicking, if you need to keep the shell open to read results use Read-Host.


Automating Tasks
Now if your fluent in C# and .NET you probably are already full of ideas on what you can do. But I thought I'd cover some essentials that I think are especially useful.

Modifying files is definitely the most common thing I automate, so to start here is a C# function which finds and replaces specific text across all the files in a folder.
using System; using System.IO; public class FileMod { public static void Apply(string path) { //get all files in directory string[] files = Directory.GetFiles(path); for (int i = 0; i < files.Length; i++) { //skip non .html files if (!files[i].EndsWith(".html")) continue; Console.WriteLine(files[i]); //replace class='lk' with class='lnk' string txt = File.ReadAllText(files[i]); txt = txt.Replace(" class='lk'", " class='lnk'"); File.WriteAllText(files[i], txt); } } } }
One potential issue is the C# code executes relative to PowerShell.exe, not the current working directory. So you may want to combine this with Get-Location to prepend the current directory to your file paths.

Probably the most powerful thing that C# gives you access to is direct native WinAPI interfacing. By using DllImport you can call native functions and with proper structures you can fully work with the native WinAPI from C#. Below you can see an example of resizing and moving a window using FindWindow and MoveWindow.
using System; using System.Runtime.InteropServices; public static class WinMove { //import native functions [DllImport("User32.dll")] static extern Boolean MoveWindow(IntPtr handle, Int32 x, Int32 y, Int32 w, Int32 h, Boolean repaint); [DllImport("User32.dll")] static extern IntPtr FindWindowW([MarshalAs(UnmanagedType.LPWStr)] string className, [MarshalAs(UnmanagedType.LPWStr)] string winName); public static void Move(string name, int x, int y, int width, int height) { //get window pointer by name IntPtr h = FindWindowW(null,name); if (h == IntPtr.Zero) Console.WriteLine("Error could not find window '"+name+"'!"); else { //move window to pixel coordinates and size MoveWindow(h,x,y,width,height,true); Console.WriteLine("Moved '"+name+"' to "+x+","+y+","+width+","+height+"."); } } }


Thanks for Reading!
If you have any questions feel free to reach out to me at xaloezcontact@gmail.com.

XALOEZ.com This website has no ads or tracking, support development via Patreon.