I am trying to run following powershell cmdlet on my azurewebsite
public string RunPowerShellScript()
{
try
{
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
//Here's how you add a new script with arguments
Command myCommand = new Command("Set-AzureWebsite");
myCommand.Parameters.Add("Name", "rmssimple");
myCommand.Parameters.Add("HostNames ", "#('test.posxyz.com', 'xyz.com')");
pipeline.Commands.Add(myCommand);
var results = pipeline.Invoke();
return Content(results[0].ToString());
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
but i get bellow error
The term 'Set-AzureWebsite' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
firts question : why do you wan tto do it like that? second, if you want to do it , you need to import the module first and the Powershell tools need to be installed. Importing the module is as follwos in PoSh : import-module Azure
Related
I have this Powershell command that I would like know how to execute from Java / JavaFx:
powershell.exe Get-WMIObject Get-WMIObject Win32_SerialPort | Select-Object Name,DeviceID,Description,Caption, PNPDeviceID,Status | Out-File -FilePath C:\\path\\to\\file\\test.txt
I've read and tried several examples I found online and in forums. But I'm still stuck! This is the JavaFx method I'm using:
public void PowerShellCommand() throws IOException
{
String command = "powershell.exe Get-WMIObject Get-WMIObject Win32_SerialPort | Select-Object Name,DeviceID,Description,Caption, PNPDeviceID,Status | Out-File -FilePath C:\\path\\to\\file\\test.txt";
Process powerShellProcess = Runtime.getRuntime().exec(command);
powerShellProcess.getOutputStream().close();
}
Executing the command directly in PowerShell produces the right results.
A .txt file with content is created. Like this one (which is correct):
Name : Kommunikationsanschluss (COM1)
Description : Kommunikationsanschluss
Caption : Kommunikationsanschluss (COM1)
PNPDeviceID : ACPI\PNP0501\1
Status : OK
(Goal is to fetch the various results out of the .txt file content and display them on a UI).
But using the code in the above method creates an empty .txt file. I'm certainly doing something wrong, and would need some help to fix it.
Do you have any ideas? Your time and help is very much appreciated!
AveJoe
PS: I'm using a Windows 10 Pro machine.
I believe you are actually asking several questions, including
How to execute powershell command from java?
How to read a file in java?
How to display contents of a text file in JavaFX GUI?
I will answer the first question.
(Indeed, I believe a post should contain a single question.)
The ProcessBuilder constructor takes an array of String. Each word in your command becomes a single element in the array. Words are separated by one or more space characters.
Also you need to read the Process output and error output. I recommend creating two separate threads - one for output and another for error. And since you can easily write the Process output to a file, there is no need to use Out-File in your powershell command.
Here is a java program to execute the powershell command from your question.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class ProcBldr {
public static void main(String[] args) {
ProcessBuilder procBldr = new ProcessBuilder("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"Get-WMIObject",
"Win32_SerialPort",
"|",
"Select-Object",
"Name,DeviceID,Description,Caption,PNPDeviceID,Status");
Process proc;
try {
proc = procBldr.start(); //throws java.io.IOException
Thread out = new Thread(new ProcOutput(proc.getInputStream(), new File("C:\\Users\\USER\\stdout00.txt")));
Thread err = new Thread(new ProcOutput(proc.getErrorStream(), new File("C:\\Users\\USER\\stderr00.txt")));
out.start();
err.start();
int exitCode = proc.waitFor(); //throws java.lang.InterruptedException
out.join();
err.join();
System.out.println("\nExited with error code : " + exitCode);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
class ProcOutput implements Runnable {
private BufferedReader buffReader;
private PrintWriter pw;
public ProcOutput(InputStream is, File f) throws IOException {
InputStreamReader isr = new InputStreamReader(is);
buffReader = new BufferedReader(isr);
pw = new PrintWriter(f);
}
public void run() {
try {
String line = buffReader.readLine();
while (line != null) {
pw.append(line);
pw.append(System.lineSeparator());
line = buffReader.readLine();
}
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
finally {
pw.close();
try {
buffReader.close();
}
catch (IOException xIo) {
// Ignore.
}
}
}
}
The output of the powershell command is written to file stdout00.txt. The file contains the following...
Name : Communications Port? (COM1)
DeviceID : COM1
Description : Communications Port
Caption : Communications Port? (COM1)
PNPDeviceID : ACPI\PNP0501\0
Status : OK
I recommend you read the article When Runtime.exec() won't. It is very old and was written before class ProcessBuilder was part of the JDK but it also applies to ProcessBuilder and therefore, in my opinion, still relevant to the latest JDK version (12.0.1 at time of writing this).
Note that my environment is Windows 10 (64 bit) and Oracle JDK 12.0.1 (also 64 bit)
I am writing a service which controls docker containers. I want to have the mounted volume as an Azure share, and thus need to use the SMB Global Mapping. If I use the usual WNetAddConnection2A then I can mount the share just fine in my code, but the containers cannot see it as it is not "global". I can't find source for the PowerShell New-SmbGlobalMapping command (is there a way to see it?) and I can't find a suitable API to call. I hope someone knows the magic incantation I can put in my .NET code.
I can't find source for the PowerShell New-SmbGlobalMapping command
(is there a way to see it?) and I can't find a suitable API to call. I
hope someone knows the magic incantation I can put in my .NET code.
PowerShell uses WMI
In your case, it calls
Create method of the MSFT_SmbMapping class (MSFT_SmbGlobalMapping exactly)
You can use WMI Code Creator to generate/test C# code
EDIT : Test with PowerShell.Create
Test as Admin ("requireAdministrator" in manifest) on Windows 10
Test code (C#, VS 2015) =>
// PowerShell calls CredUIPromptForCredentialsW to display the User/Password dialog (you can call it with P/Invoke if needed)
string sUser = "user#provider.com";
string sPassword = "myPassword";
System.Net.NetworkCredential networkCredential = new System.Net.NetworkCredential(sUser, sPassword, null);
System.Security.SecureString securePassword = new System.Security.SecureString();
foreach (var c in networkCredential.Password)
securePassword.AppendChar(c);
// Add reference to :
// C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
// Add :
// using System.Management.Automation;
PSCredential psCredential = new PSCredential(networkCredential.UserName, securePassword);
// Error handling must be improved : if I pass an invalid syntax for "RemotePath" or not launched as Admin,
// nothing happens (no error, no result) (on Windows 10)
string sLocalPath = "Q:";
string sRemotePath = "\\\\DESKTOP-EOPIFM5\\Windows 7";
using (var ps = PowerShell.Create())
{
ps.AddCommand("New-SmbGlobalMapping");
ps.AddParameter("LocalPath", sLocalPath);
ps.AddParameter("RemotePath", sRemotePath);
ps.AddParameter("Credential", psCredential);
//ps.AddParameter("RequireIntegrity", false);
//ps.AddParameter("RequirePrivacy", false);
try
{
System.Collections.ObjectModel.Collection<PSObject> collectionResults = ps.Invoke();
foreach (PSObject psObl in collectionResults)
{
Console.WriteLine("Status : {0}", psObl.Members["Status"].Value.ToString());
Console.WriteLine("Local Path : {0}", psObl.Members["LocalPath"].Value.ToString());
Console.WriteLine("Remote Path : {0}\n", psObl.Members["RemotePath"].Value.ToString());
}
}
catch (ParameterBindingException pbe)
{
System.Console.WriteLine("\rNew-SmbGlobalMapping error : {0}: {1}",
pbe.GetType().FullName, pbe.Message);
}
}
// To get and remove the test mapping in PowerShell :
// Get-SmbGlobalMapping
// Remove-SmbGlobalMapping -RemotePath "\\DESKTOP-EOPIFM5\Windows 7" -Force
So I am running a powershell script within my script, whenever it fails the line number of the exception is the line number of where I call the dot sourced file in my parent script.
I tried to catch the exception, but that didn't contain the full exception, only the actual exception text (no line numbers or categories).
Has anyone solved this? I've been searching high and low and haven't found anything about this.
Error objects have a number of properties.
Output of $Error[0] | Get-Member | Select Name | Set-Clipboard:
Name
Equals
GetHashCode
GetObjectData
GetType
ToString
CategoryInfo
ErrorDetails
Exception
FullyQualifiedErrorId
InvocationInfo
PipelineIterationInfo
ScriptStackTrace
TargetObject
PSMessageDetails
So, you could throw the details to the console via a function, for example:
Function Write-ErrorDetails($ErrorObject)
{
$thisError = [PSCustomObject]#{
Exception = $ErrorObject.Exception
Message = $ErrorObject.Exception.Message
FQID = $ErrorObject.FullyQualifiedErrorId
InovcationInfo = $ErrorObject.InvocationInfo
ScriptStackTrace = $ErrorObject.ScriptStackTrace
TargetObject = $ErrorObject.TargetObject
}
return $thisError
}
In your script, if you have a try/catch block, you could catch exceptions and call your function:
BEGIN
{
Function Write-ErrorDetails($ErrorObject)
{
$thisError = [PSCustomObject]#{
Exception = $ErrorObject.Exception
Message = $ErrorObject.Exception.Message
FQID = $ErrorObject.FullyQualifiedErrorId
InovcationInfo = $ErrorObject.InvocationInfo
ScriptStackTrace = $ErrorObject.ScriptStackTrace
TargetObject = $ErrorObject.TargetObject
}
return $thisError
}
}
PROCESS
{
try
{
Do-SomeNonExistentCommand
}
catch
{
Write-ErrorDetails -ErrorObject $Error[0]
}
}
END{}
If saved inside of a file called 123.ps1 and run, your output would look like this:
Exception : System.Management.Automation.CommandNotFoundException: The term
'Do-SomeNonExistentCommand' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again.
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(
FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(Int
erpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
.Run(InterpretedFrame frame)
Message : The term 'Do-SomeNonExistentCommand' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try
again.
FQID : CommandNotFoundException
InovcationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at <ScriptBlock><Process>, C:\Users\Pythagoras\desktop\123.ps1: line 22
at <ScriptBlock>, <No file>: line 1
TargetObject : Do-SomeNonExistentCommand
The ScriptStackTrace property might be helpful for troubleshooting, especially if you are writing scripts/tools for an audience and not just your own use. You could add additional functions to do logging with the objects Write-ErrorDetails can provide, etc etc
I need to execute some powershell code from a web api which I have deployed in an Azure App Service. I couldn't achieve to se 'Set-ExecutionPolicy' because I need to set it to unrestricted but I get an error
File D:\home\powershell\teams_v2.psm1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170
.
I have the following code
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
var script = String.Format(#"Import-Module 'D:\home\powershell\teams_v2.psm1'
connect-teamsservice -user admin#contoso.onmicrosoft.com -tenant contoso.onmicrosoft.com
new-Team -displayname '{0}' -description '{1}' -smtpaddress '{2}' -alias '{3}' -type 'private'",
group.Name, group.Description, String.Format("{0}#contoso.onmicrosoft.com", group.MailNickName), "team");
RunspaceInvoke scriptInvoker = new RunspaceInvoke();
// set powershell execution policy to unrestricted
//scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(script);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection <PSObject> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
}
How can I achieve this to correctly load the ps module and use its functions.
Need your help in solving this following issue.
We have a powershell script like:
invoke-command -ScriptBlock { [cmdletbinding()]
param(
[parameter(mandatory=$True)]
[string] $ticktfilepath
)
$ticketdetails=get-content $ticktfilepath |%{if ( $_ -like '"AB*' ) {$_}}|%{echo "$($_.Split(',')[7].Split('"')[1])=$($_.Split(',')[3].Split(':')[0].Split(' ')[$_.Split(',')[3].Split(':')[0].Split(' ').length-1])=$($_.Split(',')[0].Split('"')[1]);"}
write-output $ticketdetails } -ArgumentList 'D:\file.csv'
This script reads a csv file and for those lines in the csv with “AB…” at the start, does some string parsing. The csv file passed has rows with the “AB…” and hence result are returned. This runs perfectly when executing through powershell console or ISE.
But as per our requirement, where we trying to execute the same script through:
1. System.Diagnostics.Process with process start info having file name as powershell.exe and the argument at the above script. It fails for –like. i.e at |%{if ( $_ -like '"AB*' ). It is always false for the condition even though it is expected to be true.
N.B. other powershell script works perfectly with this approach
2. Exactly Similar issue when executed through System.Management.Automation.Runspaces
So looks like some constraint using the “–like” operator.
We even with the System.Diagnostics.Process approach tried writing the script line by line leveraging the Process.StandardInput.WriteLine(line) but then powershell hangs.
Any pointer to address this will be highly appreciated.
While using System.Diagnostics.Process, I used something like:
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.FileName = "powershell.exe";
processStartInfo.Arguments = <ScriptContent>;
Process powerShellProc = new Process();
powerShellProc.StartInfo = processStartInfo;
powerShellProc.Start();
string successMessage = powerShellProc.StandardOutput.ReadToEndAsync().Result;
string errorMessage = powerShellProc.StandardError.ReadToEndAsync().Result;
powerShellProc.WaitForExit();
where,
ScriptContent- is the above powershell script.
Instead of like, even tried with startswith but then also the same result. But with powershell console or iSE, it works perfectly.
It's probably too late to answer :)
You shouldn't call powerShellProc.StandardOutput.ReadToEndAsync().Result before process actually finished. You can use Invoke-Executable function from How to capture process output asynchronously in powershell?
The following order is working
$outTask = $oProcess.StandardOutput.ReadToEndAsync();
$errTask = $oProcess.StandardError.ReadToEndAsync();
$bRet=$oProcess.WaitForExit($TimeoutMilliseconds)
$outText = $outTask.Result;
$errText = $errTask.Result;