Trouble with -TargetPath

This topic contains 4 replies, has 3 voices, and was last updated by Profile photo of Jack Neff Jack Neff 1 year, 9 months ago.

  • Author
    Posts
  • #23165
    Profile photo of Odie
    Odie
    Participant

    I am pretty new at powershell but I am trying to write a script to gather all the Domain Controllers and then Loop through them adding a new DFSN Root Target. I can't my current object to resolve correctly in the -TargetPath parameter of the script. I can get it to work if I replace the variable manually. I am totally lost on this by now and would love some help.

    #Get a list of all Domain Controllers
    Get-ADDomainController -Filter * | Select Name |

    #Start For-Each Loop
    % {

    #Displays the server currently being accessed
    write-host "Starting Process on:" $_.name

    #Create a new directory
    invoke-command -computername $_.name -scriptBlock {new-item C:\DFSRoots\UsersNetBackup -type directory}

    #Share the Directory
    invoke-command -computername $_.name -scriptBlock {new-smbshare -name UsersNetBackup -Path C:\DFSRoots\UsersNetBackup -FullAccess Everyone}

    #Add current server to the DFS using the new directory and share just created
    invoke-command -computername $_.name -scriptBlock {new-DfsnRootTarget -Path "\\yourdomain\UsersNetBackup" -TargetPath "\\$($_.name)\UsersNetBackup"}

    [blockquote]the above line is where my script errors out
    [/blockquote]

    #Shows the current server again after everything is done.
    Write-Host "Done with Processes on:" $_.name
    }

    #Everyting is done. If there are no errors, you did a good job 🙂
    Write-Host "Done will all servers"

  • #23168
    Profile photo of Jack Neff
    Jack Neff
    Participant

    I think this is one of the powershell "Gotchas". The problem is variables created outside the scriptblock curly braces aren't recognized inside the braces. Therefore you have to pass it the variable as you would a parameter to a function. Example:

    Invoke-Command -ComputerName $_.Name -ScriptBlock { param($ServerName); New-DfsnRootTarget -Path "\\yourdomain\UsersNetBackup" -TargetPath "\\$Servername\UsersNetBackup" } -ArgumentList $_.Name

    Notice how outside the braces the server's name is represented as "$_.Name". Then it's passed in to the scriptblock as an argument and loaded into a new variable called "$ServerName" via the param block.

    For more info on variable scope type this in your shell:

    Get-Help about_scopes
  • #23178
    Profile photo of Odie
    Odie
    Participant

    You are a life saver Jeff 🙂

    I was reading through the about_scopes as you indicated and noticed that the method your suggest is from Powershell 2 and there is a newer way (both should work though). I am pasting Example 5 from the help file for reference. I will test all this today and let everyone know the results:

    Example 5: Using a Local Variable in a Remote Command

    To indicate that a variable in a remote command was created in the
    local session, use the Using scope modifier. By default, Windows
    PowerShell assumes that the variables in remote commands were created
    in the remote session.

    The syntax is:
    $Using:

    For example, the following commands create a $Cred variable in the
    local session and then use the $Cred variable in a remote command:

    $Cred = Get-Credential
    Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $Using:Cred}

    The Using scope was introduced in Windows PowerShell 3.0.

    In Windows PowerShell 2.0, to indicate that a variable was created in
    the local session, use the following command format.

    $Cred = Get-Credential
    Invoke-Command $s {param($c) Remove-Item .\Test*.ps1 -Credential $c} -ArgumentList $Cred

  • #23180
    Profile photo of Odie
    Odie
    Participant

    Thanks again Jeff,

    I was able to get the script to work using the Powershell 3 commands. I had to assign a variable to $_.name to using inside the scriptblock but it worked here is the completed script:

    #Get a list of all Domain Controllers
    Get-ADDomainController -Filter * | Select Name |

    #Start For-Each Loop
    % {

    #Displays the server currently being accessed
    write-host "Starting Process on:" $_.name

    #Create a new directory
    invoke-command -computername $_.name -scriptBlock {new-item C:\DFSRoots\UsersNetBackup -type directory}

    #Share the Directory
    invoke-command -computername $_.name -scriptBlock {new-smbshare -name UsersNetBackup -Path C:\DFSRoots\UsersNetBackup -FullAccess Everyone}
    $Currentcomputer = $_.name

    [blockquote]Above is the new variable[/blockquote]

    #Add current server to the DFS using the new directory and share just created
    invoke-command -computername $_.name -scriptBlock {New-DfsnRootTarget -Path "\\yourdomain\UsersNetBackup" -TargetPath "\\$($Currentcomputer)\UsersNetBackup" $Using:Currentcomputer}

    [blockquote]Notice the powershell 3 commands at the end of the scriptblock[/blockquote]

    #Shows the current server again after everything is done.
    Write-Host "Done with Processes on:" $_.name
    }

    #Everyting is done. If there are no errors, you did a good job 🙂
    Write-Host "Done Creating Namespace Servers"

  • #23202
    Profile photo of Jack Neff
    Jack Neff
    Participant

    Great! Glad you got it. In my environment, the vast majority of my Win7 machines are still on PoSh 2.0 so even though there are way more delicious features in 3, 4 and 5 I generally stick to what is most compatible.

You must be logged in to reply to this topic.