Powershell remote : function with nested function - powershell

I'm new in Powershell and I have a question about remote.
I have a script.ps1
My script can be illustrated like this :
function Begin{
#Step 1 :
StartTodoSometing
#Step2 :
KeepDooingSomething
}
function StartTodoSometing{}
function KeepDoingSomething{}
This script have can be run on a local server or multiple remote server.
The nested function StartTodoSometing and KeepDoingSomething are public so I can't put it in the "Begin" function.
My question is, how can I run the "Begin" function on a remote computer ???
Thanks for your help !!! :)

I don't know what you mean with public, but if it's a fileshare or anything you should be able to use the following:
function Begin{
. .\POWERSHELLSCRIPT\LOCATION\StartTodoSometing.ps1
. .\POWERSHELLSCRIPT\LOCATION\KeepDoingSomething.ps1
#Step 1 :
StartTodoSometing
#Step2 :
KeepDooingSomething
}

Related

How to add a numeric switch to a PowerShell script

I know how to add switch parameters to PowerShell scripts, but the name of the switch is always a (valid) identifier like -Enable because the name is generated from the backing PowerShell variable.
[CmdletBinding()]
param(
[switch] $Enable = $false
)
Some tools have switches like -2008. Normally, one would name the switch $2008 but this is not a valid identifier.
How can I implement such a switch as a boolean value in PowerShell?
Or in other words: How to specify a different parameter name then the backing variable?
Edit 1
I wasn't aware of number only variables (which is very strange for a programming language...). Anyhow, I created that example:
function foo
{ [CmdletBinding()]
param(
[switch] $2008
)
Write-Host "2008=$2008"
}
For this code, which is accepted as valid PowerShell, I get a auto completion as wanted. But when providing that parameter, I get this error message:
foo : Es wurde kein Positionsparameter gefunden, der das Argument "-2008" akzeptiert.
In Zeile:1 Zeichen:1
+ foo -2008
+ ~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [foo], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,foo
Translation: No positional parameter was found, that accepts the argument "-2008".
The purpose of the script is to provide translations / wrappers for command line interfaces.
Here is a set of standardized executables with parameters:
vcom.exe -2008 design.vhdl
vsim.exe -2008 design
Translation:
ghdl.exe -a --std=2008 design.vhdl
ghdl.exe -e --std=2008 design
ghdl.exe -r --std=2008 design
I would like to keep the feature of auto completion for parameters, otherwise I could process all remaining parameters and translate them by hand.
PowerShell doesn't support numeric parameters (See this answer).
Could a validateset be an acceptable solution to your problem ?
Validate set does benefit from the autocompletion feature and this is the next best thing, in my opinion, of what you wanted.
Foo & Foos — both are the same, except Foos accept multiple parameters.
foo -std 2008
foos -std 2008,2009,2010
function foo
{ [CmdletBinding()]
param(
[ValidateSet("2008",
"2009",
"2010",
"2011","2012")][INT]$std
)
Write-Host "std:$std"
}
function foos
{ [CmdletBinding()]
param(
[ValidateSet("2008",
"2009",
"2010",
"2011","2012")][INT[]]$std
)
$std | foreach {Write-Host "std: $_"}
}
foo -std 2008
foos -std 2008,2009,2010

PowerShell - InvalidCastException when returning Boolean to explicitly declared variable [duplicate]

This question already has answers here:
Function return value in PowerShell
(10 answers)
Closed 5 years ago.
I've written a PowerShell script to perform some pre-installation setup for a series of patches I'm deploying to client computers across our estate and I'm hitting a bit of an odd issue that I can't wrap my head around.
The setup patch checks the 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe.config' file due to a "feature" of PowerShell 2.0 whereby the application uses .NET Framework 2.0.0 by default instead of 4.5.2, preventing certain functions from being executed. If the file doesn't exist or the evaluated values don't match a specification, I add the XML file and provide the necessary values.
The command I run is as follows:
$psConfigDir = "C:\Windows\System32\WindowsPowerShell\v1.0"
$psConfigFileName = "powershell.exe.config"
[boolean]$psExeXml = Set-PSRuntimeConfigs -FilePath ( [String]::Format("{0}\{1}", $psConfigDir, $psConfigFileName) ) -CLRVersions #("v4.0.30319", "v2.0.50727")
...and the Set-PSRuntimeConfigs method is found in a PowerShell Module I created with the code below:
Function Set-PSRuntimeConfigs {
[CmdletBinding()]
Param(
[String]$FilePath,
[System.Collections.ArrayList]$CLRVersions
)
Try {
$xmlWriter = New-Object System.Xml.XmlTextWriter($FilePath, $null)
$xmlWriter.Formatting = "Indented"
$xmlWriter.Indentation = 4
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteStartElement("configuration")
$xmlWriter.WriteStartElement("startup")
$xmlWriter.WriteAttributeString("useLegacyV2RuntimeActivationPolicy", $true)
$CLRVersions | ForEach-Object {
$xmlWriter.WriteStartElement("supportedRuntime")
$xmlWriter.WriteAttributeString("version", $_)
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
$xmlWriter.WriteEndElement()
$xmlWriter.WriteEndDocument()
$xmlWriter.Close()
$xmlWriter.Dispose()
return $true
} Catch {
echo "ERROR: Exception occurred during XML write process!"
echo "ERROR: Exception message: $($_.Exception.Message)"
return $false
}
}
However, the function is returning an InvalidCastException when trying to assign the result of the function to the $psExeXml variable. Oddly, PowerShell returns with an error stating that [System.Object()] cannot be converted to type [Boolean] despite the fact that only $true or $false is returned from the function.
My first thought is that an exception was being thrown by the function due to a code issue but the function is written to report the error in the prompt and just return $false in that case... Regardless, I'm stuck and can't figure out where to proceed with this...
If the function produces any output then the result will be an array containing the strings that were output and then the final element will be your boolean.
So for this code:
echo "ERROR: Exception occurred during XML write process!"
echo "ERROR: Exception message: $($_.Exception.Message)"
return $false
the function returns an array of two strings and a boolean.

Run process using CMD command fails if the argument is not hardcoded

I want to run cmd command and run process:
This function works fins:
function RunProcess($processPath)
{
&$processPath "my argument"
}
Usage:
RunProcess "myExe.exe"
Now if I want to make it more generic and send also the argument:
function RunProcess($processPath, $ar)
{
&$processPath $ar
}
Usage:
RunProcess "myExe.exe" "my argument"
This failed and I don't know why.
Your code is working for me, you could try this as well:
function RunProcess($processPath, $ar)
{
Start-Process $processPath -ArgumentList $ar
}

how do i prevent my script for waitnig for user input

i am writing a code that runs on remote computer using psexec, in some point of the code it stop and wait for user to press enter in order to continue , this only happens on remote! when i use local its fine, how do i prevent that and keep my code "rolling"?
code:
param(
[Parameter(ParameterSetName='database')] [string]$database,
[Parameter(ParameterSetName='file')] [string]$file,
[Parameter(ParameterSetName='server')] [string]$server,
[Parameter(ParameterSetName='mailbox')] [string]$mailbox,
[Parameter(ParameterSetName='all')] [switch]$all,
[string]$filename
)
if($mailbox) { $mailboxes = #(Get-Mailbox $mailbox) } ----->#it stop after this function#

how to establish and enter a remote session using runspace in powershell

I am trying to establish a session with a remote host B from my machine A, within a C# code. I am using runspace API for that. the code snippet is provided below
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
//constructing the vmname parameter here
vmname = useralias + DateTime.Now.ToString();
Pipeline pipeline = runspace.CreatePipeline();
string scripttext = "$secpasswd = ConvertTo-SecureString '222_bbbb' -AsPlainText –Force";
string scripttext1 = "$mycreds = New-object -typename System.Management.Automation.PSCredential('TS-TEST-09\\Administrator',$secpasswd)";
string scripttext2 = "$s = New-PSSession -ComputerName TS-TEST-09 -Credential $mycreds";
//not accepting session string here, only computername acceptable
**string scripttext3 = "Enter-PSSession -Session $s";**
//Command cmd = new Command(#"C:\mypath\helper.ps1", true);
//cmd.Parameters.Add("local_useralias", useralias);
//cmd.Parameters.Add("local_vmname", vmname);
//cmd.Parameters.Add("local_datastore", datastoredropdown.Text.ToString());
//cmd.Parameters.Add("local_architecture", architecturedropdown.Text.ToString());
pipeline.Commands.AddScript(scripttext);
pipeline.Commands.AddScript(scripttext1);
pipeline.Commands.AddScript(scripttext2);
pipeline.Commands.AddScript(scripttext3);
//pipeline.Commands.Add(cmd);
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
this code is expected to enter into a session with machine TS-TEST-09 and invoke the script helper.ps1 existing on that machine(that part is commented out in the code currently as i am not able to enter into the session with remote host).
now the problem is that i can't enter into the session $s using -Session parameter(highlighted at scripttext3) however i can enter into it using -Computername parameter.
the error that i get when using -Session parameter in scripttext3 is :
at
invokedSystem.Management.Automation.Internal.Host.InteralHost.GetIHostSupportsInteractiveSession()
at invokedSystem.Management.Automation.
Internal.Host.InteralHost.PushRunspace(Runspace runspace)
at Microsoft.Powershel.Commands.EnterPSSessionCommand.ProcessRecord()
at System.Management.Automation.Cmdlet.DoProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
end of inner exception stack trace
does it mean i have to write a custom PSHost and add support for the Enter-PSSession cmdlet with this parameter?
Is there any alternative to make this command work?
any help will be much appreciated.
Thanks,
Manish
The easiest way to open a remote session goes something like this:
string shell = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
var target = new Uri("http://myserver/wsman");
var secured = new SecureString();
foreach (char letter in "mypassword")
{
secured.AppendChar(letter);
}
secured.MakeReadOnly();
var credential = new PSCredential("username", secured);
var connectionInfo = new WSManConnectionInfo(target, shell, credential);
Runspace remote = RunspaceFactory.CreateRunspace(connectionInfo);
remote.Open();
using (var ps = PowerShell.Create())
{
ps.Runspace = remote;
ps.Commands.AddCommand("'This is running on {0}.' -f (hostname)");
Collection<PSObject> output = ps.Invoke();
}
You could also create remote pipelines from the remote runspace instance, but the new PowerShell object is a much more managable way to do this (since powershell v2.)
In powershell v3, you can just new up a WSManConnectionInfo and set the ComputerName property as the other properties adopt the same defaults as the above. Unfortunately these properties are read-only in v2 and you have to pass in the minimum as above. Other variants of the constructor will let you use kerberos/negotiate/credssp etc for authentication.
-Oisin
I wanted to leave a comment on the solution, as it helped me alot as well,
but one thing i was missing was the port for WSMan which is 5985
so this
var target = new Uri("http://myserver/wsman");
should be
var target = new Uri("http://myserver:5895/wsman");
in my case
Have you tried Invoke-Command? Enter-PsSession is there for interactive use. (see help Enter-PsSession -online).