Reputation: 55
Im trying to run a ps1 script out of the resource Folder in c#
Thanks to Yevhen Cherkes
.NET Get embedded Resource File
Load C# Embedded Resource Path into PowerShell Command Class
Got me closer.
Changing
private void button1_Click_1(object sender, EventArgs e)
{
PowerShell ps = PowerShell.Create();
string skriptpfad = $@"C:\Users\username\Desktop\1Tool_Final\WinformsTool\bin\Debug\zuordnung.ps1";
ps.AddCommand(skriptpfad);
ps.AddParameter("Source", folderBrowserDialog1.SelectedPath);
ps.AddParameter("Destination", folderBrowserDialog2.SelectedPath);
ps.Invoke();
}
to
private void button1_Click_1(object sender, EventArgs e)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "zuordnung_test.Resources.zuordnung.ps1";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string skriptpfad = reader.ReadToEnd();
PowerShell ps = PowerShell.Create();
//string skriptpfad = $@"C:\zuordnung.ps1";
ps.AddCommand(skriptpfad);
ps.AddParameter("Source", folderBrowserDialog1.SelectedPath);
ps.AddParameter("Destination", folderBrowserDialog2.SelectedPath);
ps.Invoke();
}
}
This only throws an exception with the whole ps script - not known as cmdlet - though, it does read it but addcommand
ran the script before. Is it simply AddScript now or am i still approaching it wrong ?
Thanks in Advance
Upvotes: 1
Views: 1220
Reputation: 439597
Let me add some background information to your own (effective) answer:
Note: Your problem came down to having to switch from .AddCommand()
for script-file execution (.ps1
) to .AddScript()
for source-code string execution (from a resource). The following focuses mainly on when to use .AddCommand()
vs. .AddScript()
for script-file execution.
.AddCommand()
is the right PowerShell SDK method for invoking script files (.ps1
) and other command forms, namely cmdlets, functions, and external programs.
A potential problem is that the effective PowerShell execution policy may prevent execution of script files. On pristine machines running Windows desktop editions, script-file execution is by default disabled altogether (Restricted
), whereas it is RemoteSigned
on server machines.
Assuming the effective execution policy doesn't prevent script-file execution via GPOs (Group Policy Objects), you can solve this problem by setting the execution policy for the current PowerShell session (only), via the SDK; RemoteSigned
(browser-downloaded files must have a valid signature) is usually the safe choice:
// Create an initial default session state.
var iss = InitialSessionState.CreateDefault2();
// Set its script-file execution policy (for the current session only).
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned;
// Create a PowerShell instance with a runspace based on the
// initial session state.
PowerShell ps = PowerShell.Create(iss);
// ...
// Now, .AddCommand() should work fine.
ps.AddCommand(skriptpfad);
// ...
.AddScript()
as workaround, as discussed next - but do note that is has limitations and side effects.The somewhat confusingly named .AddScript()
method is for invoking PowerShell source code provided directly as a string, the content of a script file, so to speak, or, as in your case, a piece of PowerShell code retrieved from a resource embedded in an assembly.
Therefore, as long as a given script file's content (code) doesn't (directly or indirectly[1]) invoke other script files, you can use .AddScript()
to bypass PowerShell's execution policies (which apply only to script files).
That is, as shown in your answer, you can read a .ps1
file's content into a string in memory up front, and pass that string to .AddScript()
; the simplest way to dot that is to use System.IO.File.ReadAllText
:
ps.AddScript(File.ReadAllText(skriptpath));
// Call ps.AddParameter() as needed.
Caveat: A side effect of this technique is that the script-file body invoked this way will be unaware of the script file's original file name and location.
[1] Note that some modules automatically execute .ps1
files during their import, and that the module import itself may happen automatically.
Upvotes: 3
Reputation: 55
private void button1_Click_1(object sender, EventArgs e)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "%projectname%.Resources.%script.ps1%";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string skriptpath = reader.ReadToEnd();
PowerShell ps = PowerShell.Create();
ps.AddScript(skriptpath);
//ps.AddParameter...
ps.Invoke();
}
}
is the solution for my question. I included the solutions of the mentioned above threads and changed AddCommand to AddScript ( idk why addcommand worked with reading it from the local file and doesnt in this case )
Upvotes: 2