Pass variables to the remotely imported powershell module - powershell

I am trying to create new PSSession, import ActiveDirectory module on the remote machine and then import-pssession to my local workstation - this works fine. The code looks like:
$rs = New-PSSession -ComputerName RemoteMachine
Invoke-Command -Session $rs -scriptblock {import-module ActiveDirectory}
Import-PSSession -Session $rs -Module Active Directory
And now I am able to call ActiveDirectory cmdlets, so e.g. Get-ADUser -Filter * works fine.
BUT
I am not able to pass variables to the ActiveDirectory cmdlets, I am not able to execute the following:
$name = 'John Smith'
Get-ADUser -Filter {name -eq $name}
It says $name is not defined. I cannot pass the variable to the Get-ADUser.
Any suggestions?
Thanks

I can't test it now but try to use double quotes instaed of a script block so the value of the variable can be expanded before it moves on to the target,
Get-ADUser -Filter "name -eq $name"

Related

Powershell Get-Childitem in ISE

please can you help me.
I'm missing some information.
Why when I execute the code:
Invoke-Command -ComputerName domainpc -ScriptBlock {Get-ChildItem -path C:\Users -Filter "username1"}
the result is: username1
And when I execute this script:
$user = Read-Host "Please enter username"
Invoke-Command -ComputerName domainpc -ScriptBlock {Get-ChildItem -path C:\Users -Filter "$user"}
the result is a list of folder contained in C:\Users
I don't understand why executing script get different results than execute code without variable.
Seems that the problem is the variable.
Please can you explain this?
Thanks.
You are hitting scope "problems".
The variable $user inside your script block -ScriptBlock is not known.
Take a look here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_variables?view=powershell-7.1#using-local-variables
Use $Using:user to get around.

Exporting mailadressen to CSV

I want our Marketing deparment to extract all mailadressen from our users to CSV.
I created and Constrained Endpoint by using a configuration file, but i keep getting errors
First i created the config file:
New-PSSessionConfigurationFile -Path 'c:\marketing.pssc' -SessionType 'RestrictedRemoteServer' -LanguageMode FullLanguage -ModulesToImport ActiveDirectory -VisibleCmdlets ('Get-ADUser', 'Get-ADGroupMember', 'Export-Csv', 'Select-Object')
Register-PSSessionConfiguration –Name ‘Marketing’ -ShowSecurityDescriptorUI –Path ‘c:\marketing.pssc’
Im trying to run this code:
Set-ExecutionPolicy remotesigned -Scope Process -Force
$session = New-PSSession -ComputerName name -ConfigurationName 'marketing'
Invoke-Command -Session $session -Scriptblock {
Get-ADGroupMember -Identity "groupname" -Recursive | Get-ADUser -Properties Mail | where {$_.mail -ne $null} | Select Name,Mail | Export-CSV -Path "\\somepathto\file.csv" -NoTypeInformation
}
Remove-PSSession $session
i Expect an CSV file with name and email adressen.
The script works when running as a domain admin, currently i get this error:
The term 'where.exe' is not recognized as the name of a cmdlet, function, script file, or operable program....
According to the get-aduser commandlet, you should provide at least a required input param. Currently, it is stating the one you provide(-properties) is not approved by the validateset of the input param set.
https://learn.microsoft.com/en-us/powershell/module/addsadministration/get-aduser?view=win10-ps
This will help you out:
Get-ADUser -LDAPFilter '(mail=*marketing)' | select-object Name,Mail
https://ss64.com/ps/get-aduser.html

Remoting Through an Array of Webservers to Deploy Code

I'm looking to pop through a few webservers and import-module WebAdministration in order to change some recycling properties.
The issue is, it seems like foreach doesn't like being used for remote sessions. I'm guessing this is because a single block of code can only be executed in 1 remote session? Is there a way to pop through multiple sessions or do I have to do that by hand?
Just looking for some input on how to write a code to deploy to all my apppools on all my servers.
I've tested wildcarding the appPool directory and that seems to work.
IIS10
Powershell 5.1.14393.2189
$servers = #("MyEnvironment-web01","MyEnvironment-web02","MyEnvironment-web03")
foreach ($server in $servers) {
enter-Pssession -ComputerName $server
Write-Host $server
Read-Host -Prompt "Press Enter to continue" #This was added because I thought maybe it just needed time to connect? Doesn't need to be in here.
import-module WebAdministration
Get-ItemProperty -Path IIS:\AppPools\*
exit-PSSession
}
Lots of this:
import-module : The specified module 'WebAdministration' was not loaded because no valid module file was found in any module directory.
At line:1 char:1
Which is odd because that works just fine if I run the for-each loop manually. Except about 20% of the time when it doesn't....
I'm willing to bet I'm going about this ALL wrong.
$Cred = Get-Credential -UserName <domain\user> -Message 'Enter Password'
$servers = #("myserver1"."myserver2","etc")
foreach ($server in $servers) {
Invoke-Command -ComputerName $server -Credential $cred {
import-module WebAdministration
Get-ItemProperty -Path IIS:\AppPools\*
}
}

Powershell ForEach-Object {Start-Job -Scriptblock} not populating variables

Here is my code, it works and creates a job for each computer in the OU but does not populate the $Computer variable in my script block causing this to fail.
I am sure I am missing something small since I have never created jobs before in Powershell but after working on this for an hour or two I have been unable to figure out what I am missing.
#Gets all workstations that need to have software installed, if you don't want to uninstall all of the software from you will need to use a text document and Get-Content
$computers = Get-ADComputer -Filter * -SearchBase "OU=Workstation Test,OU=Workstations,OU=Workstations,DC=CONTOSO,DC=COM" | Select DNSHostName -ExpandProperty DNSHostname
$Computer
#Use Get-WMIObject to find the IdentifyingNumber
$Computers | ForEach-Object {Start-Job -Name "$Uninstall" -ScriptBlock {(Get-WmiObject -Class Win32_product -ComputerName $Computer -Filter {IdentifyingNumber LIKE '{CD95F661-A5C4-44F5-A6AA-ECDD91C2410B}'}).uninstall()}}
Instead of $computer you need to use $_.
$_ represents the current item in the pipeline.
Alternatively you could do:
ForEach ($Computer in $Computers) { Invoke-Command -ComputerName $Computer -ScriptBlock {(Get-WmiObject -Class Win32_product -Filter {IdentifyingNumber LIKE '{CD95F661-A5C4-44F5-A6AA-ECDD91C2410B}'}).uninstall()} }
Here you continue to use $Computer inside the foreach as it now gets populated with each item in the collection.
Also FYI your $computer line above the ForEach-Object is currently unnecessary (it's just outputting an empty variable, unless you've already populated it elsewhere).
Edit: per comments I also noticed that the start-job seemed redundant as -computername was being used on the wmi cmdlet. Invoke-command is preferred as it uses winrm, so I've modified it as such in my code above.

Powershell using Invoke-Command and Get-Childitem not delivering content

I am using Powershell 4.0 on a remote computer (rem_comp) to access another one (loc_comp; Powershell 2.0 installed here) in order to get the number of files listed without folders:
$var1 = 'H:\scripts'
Invoke-Command -Computername loc_comp -scriptblock {(Get-Childitem $var1 -recurse | Where-Object {!$_.PSIsContainer}).count}
However when using $var1 inside -scriptblock, it does not deliver anything (neither any error message).
When using
$var1 = 'H:\scripts'
Invoke-Command -Computername loc_comp -scriptblock {(Get-Childitem $ -recurse | Where-Object {!$_.PSIsContainer}).count}
it works!
Note: Changing var1 from ' to " does not help.
Running the command without Invoke-Command locally faces the same problem.
How to fix this?
To complement CmdrTchort's helpful answer:
PS v3 introduced the special using: scope, which allows direct use of local variables in script blocks sent to remote machines (e.g., $using:var1).
This should work for you, because the machine you're running Invoke-Command on has v4.
$var1 = 'H:\scripts'
Invoke-Command -Computername loc_comp -scriptblock `
{ (Get-Childitem $using:var1 -recurse | Where-Object {!$_.PSIsContainer}).count }
Note that using: only works when Invoke-Command actually targets a remote machine.
When you're using Invoke-command and a script-block , the scriptblock cannot access your params from the outer scope (scoping rules).
You can however, define the params and pass them along with the -Argumentlist
Example:
Invoke-Command -ComputerName "localhost" {param($Param1=$False, $Param2=$False) Write-host "$param1 $param2" } -ArgumentList $False,$True
The following should work for your example:
Invoke-Command -Computername loc_comp -scriptblock {param($var1)(Get-Childitem $var1 -recurse | Where-Object {!$_.PSIsContainer}).count} -ArgumentList $var1