Calling a function within a function with invoke-command Powershell - function

I am hoping to call a function within a function in invoke-command. It looks like I am not doing this properly. I get "get-group_users" is not recognized error. Everything is in one ps1 script.
Truncated Script:
function get-session {
$session = New-PSSession -ComputerName $ip -Credential $cred -Auth CredSSP
$ComputerName = $cred.Replace('\Admin',"")
$csv = "C:\Scripts\Serverlists\" + $ComputerName + ".txt"
$subcomps = import-csv $csv | foreach-object {$_.Name}
foreach ($ComputerName in $subcomps)
{
$ComputerName
$xmlWriter.WriteStartElement("Computer",$ComputerName)
Invoke-Command -Session $session -ScriptBlock { (get-groups_users -ComputerName $ComputerName) } -ArgumentList $ComputerName
$xmlWriter.WriteEndElement()
}
Remove-PSSession -ComputerName $ip
}
$ip = '172.16.24.11'
$ComputerName = "COMP1"
$user = '\Admin'
$cred = $ComputerName + $user
(get-groups_users -ComputerName $ComputerName)
(get-session -Credential $cred -ComputerName $ip)
So, I'm leaving out the get-groups_users function. I can post it if someone thinks it will help explain everything. It is a long one. Also i am leaving out the $xmlwriter definitions.
get-groups_users works when it runs on COMP1, but once I enter PSSession and try and use it in invoke-command for the sub comps it doesn't recognize it.
What am I forgetting?

You have to include the get-groups_users function definition inside the -ScriptBlock parameter when you call Invoke-Command. If you don't, the remote session has no knowledge of the get-groups_users function.
Here's how to fix that:
$ScriptBlock = {
function get-groups_users {
############ Put your function's code here ############
}
(get-groups_users -ComputerName $ComputerName)
};
Invoke-Command -Session $session -ScriptBlock $ScriptBlock -ArgumentList $ComputerName

Related

Using PowerShell to verify that a specific service exists from a .txt list of server names

I am trying to verify that a specific service exists from a .txt list of server names and then output to a file. In this case I need to also add credentials so I need to use the Invoke-Command. What am I doing wrong here?
clear
start-transcript -path .\Log.txt
$servers = Get-Content .\Resources\Lab.txt
$cred = get-credential domain\Username
$name = Read-Host -Prompt 'Input your service name'
function Getinfo() {foreach($server in $servers)
{
Get-Service | Where-Object { $_.Name -eq $name}-and {$_.Status -eq "Running"}| Format-Table -AutoSize
}
}
Invoke-Command -credential $cred -ComputerName $servers -ScriptBlock ${function:Getinfo}
Stop-Transcript
I think you mean this?
$servers = Get-Content .\Resources\Lab.txt
$cred = Get-Credential domain\Username
$name = Read-Host -Prompt 'Input your service name'
Invoke-Command -Credential $cred -ComputerName $servers -ScriptBlock {
param($name)
Get-Service | Where-Object { $_.Name -eq $name -and $_.Status -eq "Running"}
} -ArgumentList $name | Format-Table -AutoSize

Powershell Export to CSV with three coumns

function getServerInfo
{
$serverList = Get-Content -Path "C:\Users\username\Desktop\list.txt"
$cred = Get-Credential -Credential "username"
foreach($server in $serverList)
{
$osVersion = gwmi win32_operatingSystem -ComputerName $server -ErrorAction SilentlyContinue
if($osVersion -eq $null)
{
$osVersion = "cannot find osversion"
}
$psv = Invoke-Command -ComputerName $server -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore
if($psv -eq $null)
{
$psv2 = Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore
Write "$server has $($osVersion.Caption)and PSVersion is $psv2"
}
else{
Write "$server has $($osVersion.Caption)and PSVersion is $psv"
}
}
}
I am trying to create a csv file with 3 columns.
First column will have $server, second column will have $osVersion and third will have $psv. Please help. thank you!
Rather than using the foreach loop, consider using the ForEach-Object cmdlet so that the results can be piped to other commands. Inside of the ForEach-Object script block, you can calculate the 3 values you need, and then its easy to create CSV string using string interpolation. The results can then be piped to the appropriate output file.
Get-Content -Path C:\Users\username\Desktop\list.txt | ForEach-Object {
$Server = $_
$OSVersion = gwmi Win32_OperatingSystem -ComputerName $Server -ErrorAction SilentlyContinue
$PSVersion = Invoke-Command -ComputerName $Server -ScriptBlock { $PSVersionTable.PSVersion.Major }
"$Server,$OSVersion,$PSVersion"
} | Out-File outputFilename.csv
To export to a CSV using the Export-CSV cmdlet, PowerShell expects an array of objects with the same set of properties to output. For your case you can do that fairly simply as such:
$cred = Get-Credential -Credential "username"
$AllServers=foreach($server in $serverList)
{
[PSCustomObject]#{
'Server' = $Server
'osVersion' = gwmi win32_operatingSystem -ComputerName $server -ErrorAction SilentlyContinue | Select -Expand Caption
'psv' = Invoke-Command -ComputerName $server -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore -Credential $cred
}
}
$AllServers | Export-Csv c:\path\to\output.csv -notype

Powershell function throwing null exception

Okay, so I've read up on calling functions and passing parameters in powershell but maybe I'm not understanding something. I am calling a function and passing a couple parameters and everything works fine. It is variable defined within the function that seems to be null when it isn't.
Function:
function get-session {
$session = New-PSSession -ComputerName $ip -Credential $cred -Auth CredSSP
$subcomps = 'COMP1'
foreach ($Computer in $subcomps)
{
$Computer
Invoke-Command -Session $session -ScriptBlock { Get-WmiObject -ComputerName $Computer -Query "SELECT * FROM Win32_Group" }
}
Remove-PSSession -ComputerName $ip
}
Script:
$ip = '123.45.67.89'
$ComputerName = "HOPCOMP"
$user = '\Admin'
$cred = $ComputerName + $user
$ip
$cred
(get-session -ComputerName $ip -Credential $cred)
When I run this:
Cannot validate argument on parameter 'ComputerName'. The argument is null or empty.
Supply an argument that is not null or empty and then try the command again.
+ CategoryInfo : InvalidData: (:) [Get-WmiObject], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Of course, if I change $Computer in in the function Get-WMIObject line to COMP1 everything works great. But, the $Computer write out in the foreach loop writes COMP1 successfully.
What am I missing here?
You need to specify the -ArgumentList parameter with your Invoke-Command. For example:
Invoke-Command -Session $session -ScriptBlock {
param($Computer)
Get-WmiObject -ComputerName $Computer -Query "SELECT * FROM Win32_Group"
} -ArgumentList $Computer
The $IP is global and therefore known with the function. The -ArgumentList is needed or populate your $MyScriptBlock a line before acting on it with Invoke-Command.
The function does not know what $ip is.
You need to change the function to accept a parameter of $ip

Invoke-Command powershell trouble

Friend's i've got a trouble with this function, it will run on the remote server, but i've got the following output :
Invoke-Command : A positional parameter cannot be found that accepts argument '& C:\testNunit\dll\'.
At D:\test\Multithread.ps1:65 char:16
+ Invoke-Command <<<< -ComputerName $serv -ScriptBlock $command ([ScriptBlock]::Create("& $OneProject")) -credential $cred
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
function Nunit {
##Parse connection parameters
$Connection = #{"server" = "..."; "username" = "..."; "password" = "...."}
$serv = $connection.Get_Item("server")
$user = $connection.Get_Item("username")
$pass = $connection.Get_Item("password")
$securePassword = ConvertTo-SecureString -AsPlainText $pass -Force
#Create connection credentials object for Invoke-Command
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $user, $securePassword
$NunitExe = "C:\testNunit\bin\nunit-console.exe"
$OneProject = "C:\testNunit\dll\Foundation.Tests.dll"
$TestProjects = "C:\testNunit\dll\"
foreach( $OneProject in ( $TestProjects))
{
$WorkingDir = "c:\testNunit"
$NUnitOutput = "c:\testNunit" + $OneProject + ".xml"
$command = {&"$NunitExe" "$WorkingDir\$OneProject" \noshadow/framework:"net-3.5" /xml:$NUnitOutput}
}
Invoke-Command -ComputerName $serv -ScriptBlock $command ([ScriptBlock]::Create("& $OneProject")) -credential $cred
}
After the -Scriptblock parameter you are specifying two scriptblocks - one in $command and one via Create. There should only be one value provided to the parameter.
There are a couple issues. First, you need to pass in one parameter to the the script block, you essentially have two. Secondly, you need to pass in your variables as arguments in -ArgumentList, otherwise, the scriptblock won't recognize them.
Try this:
Invoke-Command -ComputerName $serv -ScriptBlock {
$command = args[0]
$OneProject = args[1]
$command & $OneProject} -ArgumentList #($command, $OneProject) -credential $cred

Invoke-Command run a script in a driver

I create a new remote session with powershell, in this way:
$pass = ConvertTo-SecureString "pass" -AsPlainText -force
$credential = New-Object System.Management.Automation.PsCredential("computername\admin", $securePassword)
try {
$s = New-PSSession -ComputerName "computername" -Authentication CredSSP -Credential $credential
Invoke-Command -ComputerName computername -FilePath "M:\revertToSnapshot Release1.ps1"
Remove-PSSession $s
and I don't figure out how can I run a script in the M drive.
If I try with the following:
Invoke-Command -ComputerName jm_ci -FilePath "m:\revertTosnapshot release1.ps1"
I got the following error: Invoke-Command : Cannot find drive. A drive with the name 'm' does not exist.
The user is a computer administrator.