Uygulama çalışırken server'dan veya herhangi bir yerden indirdiğimiz .cs dosyasındaki kodu runtime'da çalıştırıp kullanıcılara zoraki güncelleme getirmeden hafif değişiklikler nasıl yapılır diye araştırırken aklıma runtime'da dinamik olarak kod çalıştırabilmemize yarayan kütüphaneler geldi. Daha önce rastlamıştım fakat öğrenmek için vaktim yoktu ve ihtiyacımda o anlık yoktu. Şimdi ise ihtiyacım olduğu için yaptım ve sizlerle paylaşmak istiyorum.
C# projemizi oluşturuyoruz. Ben size göstermek amaçlı WinUI 3 .NET 9 açtım.
Öncelikle "Microsoft.CodeAnalysis.CSharp.Scripting" ve "Microsoft.CodeAnalysis.Scripting" kütüphanelerini ekleyelim:
Runtime'da ekleyeceğimiz kodun kullanılacaklar listesi:
Ben rastgele ekledim. Siz kendinize göre eklersiniz.
Önceki rehberde gösterdiğim gibi not defteri çalışınca çalıştırmak için:
Sayfa yüklenince çalışması için:
C# tarafı:
Kodun tam hâli:
Önemli not: Burada gösterilen kodları kötü niyetle kullanmayınız. Sorumlulukları red ediyorum.
Yakında çıkacak Windoc uygulamamı takip etmek için: Bilgisayarın sağlığını ve performansını kontrol eden uygulamam Windoc
C# projemizi oluşturuyoruz. Ben size göstermek amaçlı WinUI 3 .NET 9 açtım.
Öncelikle "Microsoft.CodeAnalysis.CSharp.Scripting" ve "Microsoft.CodeAnalysis.Scripting" kütüphanelerini ekleyelim:
Runtime'da ekleyeceğimiz kodun kullanılacaklar listesi:
C#:
private static readonly Assembly[] PredefinedAssemblies =
[
typeof(object).Assembly,
typeof(Uri).Assembly,
typeof(Enumerable).Assembly,
typeof(Application).Assembly,
typeof(Button).Assembly,
typeof(Debug).Assembly,
Assembly.GetExecutingAssembly()
];
private static readonly string[] PredefinedImports =
[
"System",
"System.Linq",
"System.Diagnostics",
"Microsoft.UI.Xaml",
"Microsoft.UI.Xaml.Controls"
];
Önceki rehberde gösterdiğim gibi not defteri çalışınca çalıştırmak için:
C#:
using ManagementEventWatcher watcher = new(
new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName='notepad.exe'"));
watcher.EventArrived += (_, ev) =>
{
var name = (string)ev.NewEvent.Properties["ProcessName"].Value;
var pid = (uint)ev.NewEvent.Properties["ProcessID"].Value;
Debug.WriteLine($"[{DateTime.Now:HH:mm:ss}] [{name}] başladı. PID={pid}");
};
watcher.Start();
XML:
<Window
x:Class="MSClientWepApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSClientWepApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="MSClientWepApp">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid Loaded="Grid_Loaded"> <!-- BURASI -->
</Grid>
</Window>
C#:
private void Grid_Loaded(object __, RoutedEventArgs ___) => CodeHelperAsync();
Kodun tam hâli:
C#:
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.UI.Xaml.Controls;
using System.Diagnostics;
using Microsoft.UI.Xaml;
using System.Management;
using System.Reflection;
namespace MSClientWepApp;
public sealed partial class MainWindow : Window
{
private static readonly ScriptGlobals _scriptGlobals = new();
private static readonly Assembly[] PredefinedAssemblies =
[
typeof(object).Assembly,
typeof(Uri).Assembly,
typeof(Enumerable).Assembly,
typeof(Application).Assembly,
typeof(Button).Assembly,
typeof(Debug).Assembly,
Assembly.GetExecutingAssembly()
];
private static readonly string[] PredefinedImports =
[
"System",
"System.Linq",
"System.Diagnostics",
"Microsoft.UI.Xaml",
"Microsoft.UI.Xaml.Controls"
];
public MainWindow()
{
InitializeComponent();
Activate();
using ManagementEventWatcher watcher = new(
new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName='notepad.exe'"));
watcher.EventArrived += (_, ev) =>
{
var name = (string)ev.NewEvent.Properties["ProcessName"].Value;
var pid = (uint)ev.NewEvent.Properties["ProcessID"].Value;
Debug.WriteLine($"[{DateTime.Now:HH:mm:ss}] [{name}] başladı. PID={pid}");
};
watcher.Start();
}
private static async void CodeHelperAsync()
{
string code = await GetCodeAsync();
var options = ScriptOptions.Default
.WithImports(PredefinedImports)
.WithReferences(PredefinedAssemblies);
try
{
await CSharpScript.EvaluateAsync(code, options, globals: _scriptGlobals, globalsType: typeof(ScriptGlobals));
}
catch (CompilationErrorException e)
{
Debug.WriteLine("Derleme hatası: " + string.Join(Environment.NewLine, e.Diagnostics));
}
}
private static async Task<string> GetCodeAsync() => await File.ReadAllTextAsync("Script.ini");
private void Grid_Loaded(object __, RoutedEventArgs ___) => CodeHelperAsync();
}
public class ScriptGlobals
{
public static void ShowMessage(string text) =>
mainWindow.DispatcherQueue.TryEnqueue(async () =>
{
ContentDialog dialog = new()
{
Title = "Script Çıktısı",
Content = text,
CloseButtonText = "Tamam",
XamlRoot = mainWindow.Content.XamlRoot
};
await dialog.ShowAsync();
});
public static void Log(string message) => Debug.WriteLine($"[Script Log] {message}");
}
Önemli not: Burada gösterilen kodları kötü niyetle kullanmayınız. Sorumlulukları red ediyorum.
Yakında çıkacak Windoc uygulamamı takip etmek için: Bilgisayarın sağlığını ve performansını kontrol eden uygulamam Windoc