C-Sharp Abhängige Klassen in PowerShell implementieren
Hi zusammen,
da ich ein PowerShell Skript schreibe, welches parallel zu einem Programm läuft das ich geschrieben hatte, möchte ich zwei der im Projekt enthaltenen C# Klassen in PowerShell implementieren.
Hierfür habe ich mir die Klassen LogType.cs und LogWriter.cs auf einen freigegebenen Ordner kopiert.
LogType ist lediglich ein Enum:
LogWriter die Klasse, welche die Logdateien schreibt:
Diese möchte ich nun mit Add-Type für ein Skript in PowerShell hinzufügen:
Da die Klasse LogWriter in der Methode Write(LogType logtype, string content) aber die 1. Klasse kennen muss, bekomme ich beim Hinzufügen mit Add-Type fogende Fehlerausgaben:
Der Typ [Rechnungsverteiler.tools.LogType] wird problemlos hinzugefügt, jedoch wird diese beim Hinzufügen des Typs [Rechnungsverteiler.tools.LogWriter] nicht erkannt....
Wenn ich die Klasse ohne Namespace erzeuge (einfach namespace Zeilen löschen) wird mir der Typ [LogType] auch problemlos hinzugefügt, jedoch wird der Typ nicht beim Hinzufügen der [LogWriter] Klasse erkannt.
Auch wenn ich auf using Rechnungsvertieler.tools; in LogWriter verzichte und stattdessen Write(Rechnungsverteiler.tools.LogType....) verwende leider kein Erfolg.
In der Hilfe habe ich gesehen, dass man statt -TypeDefinition auch -UsingNamespace benutzen könnte, jedoch wird das in den Examples für den Import einer cs-Datei nicht mit aufgeführt.
Hätte jemand eine Ahnung wie ich noch vorgehen könnte?
da ich ein PowerShell Skript schreibe, welches parallel zu einem Programm läuft das ich geschrieben hatte, möchte ich zwei der im Projekt enthaltenen C# Klassen in PowerShell implementieren.
Hierfür habe ich mir die Klassen LogType.cs und LogWriter.cs auf einen freigegebenen Ordner kopiert.
LogType ist lediglich ein Enum:
namespace Rechnungsverteiler.tools
{
public enum LogType
{
Info,
Warning,
Error
}
}
LogWriter die Klasse, welche die Logdateien schreibt:
using System;
using System.IO;
using System.Text;
using Rechnungsverteiler.tools;
namespace Rechnungsverteiler.tools
{
public class LogWriter
{
private readonly FileInfo file;
/// <summary>
/// Creates LogWriter for specific logfile.
/// </summary>
/// <param name="filePath">Path to logfile.</param>
public LogWriter(string filePath)
{
try
{
if (!File.Exists(filePath))
NewLog(filePath);
file = new FileInfo(filePath);
}
catch
{
// Write-Mail
}
}
/// <summary>
/// Write new log message.
/// </summary>
/// <param name="logType">Type of log entry.</param>
/// <param name="content">Content of log entry.</param>
public void Write(LogType logType, string content)
{
try
{
file.IsReadOnly = false;
using (StreamWriter sw = new StreamWriter(file.FullName, true))
{
sw.WriteLine(String.Format("{0:dd.MM.yyyy hh:mm:ss} : {1,7} | {2}", DateTime.Now, logType, content));
}
}
catch
{
// Write-Mail
}
finally
{
try
{
file.IsReadOnly = true;
}
catch { }
}
}
/// <summary>
/// Splits the last log entry to new one by writing a bar of %%%%%%%%%%%%%.
/// </summary>
public void NewSession()
{
try
{
file.IsReadOnly = false;
using (StreamWriter sw = new StreamWriter(file.FullName, true))
{
sw.WriteLine("\r\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r\n");
}
}
catch
{
// Write-Mail
}
finally
{
try
{
file.IsReadOnly = true;
}
catch { }
}
}
/// <summary>
/// Create new logfile
/// </summary>
/// <param name="path">Path for logfile</param>
private void NewLog(string path)
{
try
{
using (StreamWriter sw = new StreamWriter(File.Create(path)))
{
sw.WriteLine(new StringBuilder("************************************************************\r\n").AppendLine(
"* *").AppendLine(
"* E-Invoice-LogDatei *").AppendLine(
"* ================== *").AppendLine(
"* *").AppendLine(
String.Format("* User: {0,-48} *", System.Security.Principal.WindowsIdentity.GetCurrent().Name)).AppendLine(
String.Format("* Date: {0,-48:dd.MM.yyyy} *", DateTime.Now)).AppendLine(
"* *").AppendLine(
"************************************************************\r\n").ToString());
}
File.SetAttributes(path, FileAttributes.ReadOnly);
}
catch
{
// Write-Mail
}
}
}
}
Diese möchte ich nun mit Add-Type für ein Skript in PowerShell hinzufügen:
Add-Type -TypeDefinition (Get-Content -Path .\LogType.cs | Out-String)
Add-Type -TypeDefinition (Get-Content -Path .\LogWriter | Out-String)
Da die Klasse LogWriter in der Methode Write(LogType logtype, string content) aber die 1. Klasse kennen muss, bekomme ich beim Hinzufügen mit Add-Type fogende Fehlerausgaben:
Der Typ [Rechnungsverteiler.tools.LogType] wird problemlos hinzugefügt, jedoch wird diese beim Hinzufügen des Typs [Rechnungsverteiler.tools.LogWriter] nicht erkannt....
Wenn ich die Klasse ohne Namespace erzeuge (einfach namespace Zeilen löschen) wird mir der Typ [LogType] auch problemlos hinzugefügt, jedoch wird der Typ nicht beim Hinzufügen der [LogWriter] Klasse erkannt.
Auch wenn ich auf using Rechnungsvertieler.tools; in LogWriter verzichte und stattdessen Write(Rechnungsverteiler.tools.LogType....) verwende leider kein Erfolg.
In der Hilfe habe ich gesehen, dass man statt -TypeDefinition auch -UsingNamespace benutzen könnte, jedoch wird das in den Examples für den Import einer cs-Datei nicht mit aufgeführt.
Hätte jemand eine Ahnung wie ich noch vorgehen könnte?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 6933815873
Url: https://administrator.de/forum/c-sharp-abhaengige-klassen-in-powershell-implementieren-6933815873.html
Ausgedruckt am: 30.12.2024 um 17:12 Uhr
10 Kommentare
Neuester Kommentar
Add-Type @'
using System;
using System.IO;
using System.Text;
namespace Rechnungsverteiler.tools
{
public enum LogType
{
Info,
Warning,
Error
}
public class LogWriter
{
private readonly FileInfo file;
/// <summary>
/// Creates LogWriter for specific logfile.
/// </summary>
/// <param name="filePath">Path to logfile.</param>
public LogWriter(string filePath)
{
try
{
if (!File.Exists(filePath))
NewLog(filePath);
file = new FileInfo(filePath);
}
catch
{
// Write-Mail
}
}
/// <summary>
/// Write new log message.
/// </summary>
/// <param name="logType">Type of log entry.</param>
/// <param name="content">Content of log entry.</param>
public void Write(LogType logType, string content)
{
try
{
file.IsReadOnly = false;
using (StreamWriter sw = new StreamWriter(file.FullName, true))
{
sw.WriteLine(String.Format("{0:dd.MM.yyyy hh:mm:ss} : {1,7} | {2}", DateTime.Now, logType, content));
}
}
catch
{
// Write-Mail
}
finally
{
try
{
file.IsReadOnly = true;
}
catch { }
}
}
/// <summary>
/// Splits the last log entry to new one by writing a bar of %%%%%%%%%%%%%.
/// </summary>
public void NewSession()
{
try
{
file.IsReadOnly = false;
using (StreamWriter sw = new StreamWriter(file.FullName, true))
{
sw.WriteLine("\r\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r\n");
}
}
catch
{
// Write-Mail
}
finally
{
try
{
file.IsReadOnly = true;
}
catch { }
}
}
/// <summary>
/// Create new logfile
/// </summary>
/// <param name="path">Path for logfile</param>
private void NewLog(string path)
{
try
{
using (StreamWriter sw = new StreamWriter(File.Create(path)))
{
sw.WriteLine(new StringBuilder("************************************************************\r\n").AppendLine(
"* *").AppendLine(
"* E-Invoice-LogDatei *").AppendLine(
"* ================== *").AppendLine(
"* *").AppendLine(
String.Format("* User: {0,-48} *", System.Security.Principal.WindowsIdentity.GetCurrent().Name)).AppendLine(
String.Format("* Date: {0,-48:dd.MM.yyyy} *", DateTime.Now)).AppendLine(
"* *").AppendLine(
"************************************************************\r\n").ToString());
}
File.SetAttributes(path, FileAttributes.ReadOnly);
}
catch
{
// Write-Mail
}
}
}
}
'@
(New-Object Rechnungsverteiler.tools.LogWriter "$home\Desktop\test.log").Write([Rechnungsverteiler.tools.LogType]::Error,"SampleError")
Oder eben zusammenfügen, Reihenfolge beachten (using Anweisungen müssen zu beginn stehen!)
Add-Type -TypeDefinition (Get-Content ".\LogWriter.cs",".\LogType.cs" -Raw | out-string)
Add-Type -Path "C:\Pfad\Logwriter.dll"
Hi,
die gängige Art C#-Code in PS anzuwenden geht so:
Mit dem Laden ist PS ein wenig eigen. Partial Classes sind ihm total egal. Manchmal bricht PS ab, weil es meint eine Klasse wäre bereits geladen. Hier also auf die Verwaltung achten, genau wie in C#
Zum Einbinden externer Assemblies zb:
Grüße!
die gängige Art C#-Code in PS anzuwenden geht so:
$myCode = @'
using ...
namespace mynamespace
{
public class myclass
{
public <retunvalue> myMethod(<type> value1, <type> value2, ...)
{
....
....
return value;
}
}
}
'@
Add-Type -TypeDefinition $myCode -Language CSharp <version explicit> -ErrorAction <ErrorAction> -WarningAction <-WarningAction>
return [mynamespace.myclass]::myMethod(valueA, valueB, ...);
Mit dem Laden ist PS ein wenig eigen. Partial Classes sind ihm total egal. Manchmal bricht PS ab, weil es meint eine Klasse wäre bereits geladen. Hier also auf die Verwaltung achten, genau wie in C#
Zum Einbinden externer Assemblies zb:
$ScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
[Void] [System.Reflection.Assembly]::LoadFile("$($ScriptRoot )\nlog.dll")
Grüße!
Lad doch einfach wie oben schon erwähnt das kompilierte .NET Assembly der Klasse ...
feddisch.
Add-Type -Path "C:\Pfad\Logwriter.dll"
in dem zwei Klassen importiert werden, von denen die eine die andere kennen muss. Das wär noch cool zu wissen.
Das geht problemlos, aber du kannst in PS nicht ein und die selben Namespace/Klasse doppelt definieren. Was du oben ja machst.Zitat von @michi.wtr:
aber ich definiere nicht 2x denselben Namspace/Klasse, einmal definiere ich Namespace/LogType, ein Enum um den Art des Logeintrags festzulegen und einmal definiere ich Namexpace/LogWriter um die Logdatei zu schreiben.
Ja aber für die PowerShell überschreibst du beim zweiten mal mit Add-Type quasi den ganzen Namespace den du vorher schon importiert hast und da beim zweiten mal der Typ nicht enthalten ist, peng.aber ich definiere nicht 2x denselben Namspace/Klasse, einmal definiere ich Namespace/LogType, ein Enum um den Art des Logeintrags festzulegen und einmal definiere ich Namexpace/LogWriter um die Logdatei zu schreiben.
Dir steht jederzeit frei das Enum in einen separaten Namespace zu packen wenn du nicht alles an einer Stelle beisammen hast.