none
How to use the invoke command on Remote Computers RRS feed

  • Question

  • Hi there, 

    I'm kind of confused how to use the remote powershell execution in the right way. I have a script which needs to run on an external computer so my support desk can perform various tasks. I've build a script to reset a registry key value in the following way:

    I just put the whole script in a scriptblock, but my understanding was that variables aren't returned when using a scriptblock between braces, anyhow the script runs just fine the way I put it in here:

    $readhost = read-host "enter a computername"

    Invoke-command –computername $readhost –scriptblock {

    $regkeypath= "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\15.0\Common\licensing"

    $value1 = (Get-ItemProperty $regkeypath).SharedComputerLicensing -eq 0

    If ($value1 -eq $False) {Set-ItemProperty -path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\15.0\Common\licensing -name SharedComputerLicensing -Value 0

    Write-Host "The key has been added"}

    Else {Write-Host "The SharedComputerActivation Key is already correct"} }

    Now i've build another script to repair an app-v package I did it in another way without putting the whole script into a scriptblock, this works also fine:

    $readhost = Read-Host "enter computername"

    $s = New-PSSession –computername $readhost

    Invoke-Command -session $s -ScriptBlock {taskkill.exe /f /im explorer.exe}

    Invoke-Command -session $s -ScriptBlock {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global}

    Restart-Computer -force -ComputerName bnl-11b-004  -wait –for winrm 

    The only thing is actually I want to grab the computername also with a variable. The script would be something like: 

    $readhost = Read-Host "enter computername"

    $s = New-PSSession –computername $readhost

    Invoke-Command -session $s -ScriptBlock {taskkill.exe /f /im explorer.exe}

    Invoke-Command -session $s -ScriptBlock {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global}

    Invoke-Command -session $s -ScriptBlock {restart-computer $readhost -force}

    Now the script fails on the $readhost value within the script block. I know I need to pass the variable defined locally into a parameter. But I don't see the use as I can just put a whole script in a scriptblock as shown in the first script. What am I not getting here? 

    Can someone explain what i'm doing wrong?

     

    Friday, July 17, 2015 5:58 PM

Answers

  • What you are looking for is called a workflow.  It can resume after a restart.  If you just want to run a couple of commands then here is an easy way.

    function Fix-App{
        Param($computername)
    
            Get-Process explorer.exe -ComputerName $computername|  Stop-Process
            Invoke-Command {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global} -Computer $computername
            Restart-Computer -wait -ComputerName $computername -Force 
            Invoke-Command -ComputerName $computername -ScriptBlock {Get-AppvClientPackage -name *office*} 
    }

    This can only be run remotely.  TO do this on the local system you must use a workflow.


    \_(ツ)_/


    • Edited by jrv Sunday, July 19, 2015 4:24 PM
    • Marked as answer by Jay2k_technet Sunday, July 19, 2015 6:50 PM
    Sunday, July 19, 2015 4:24 PM

All replies

  • I think after reading my onw scripts a few times I'm getting to a point where I understand it a bit better. 

    In the first script i'm only using the read-host variable to input the computername and not referring back to the local $readhost variable in the script. The other variables are set onto the remote session so the computer knows how to handle them. 

    In the second script I use a few seperate lines of codes which need to be run serial after eachother. Because I want to refer back to the $readhost as it's a local variable the remote computer can't get this value as it is not aware of it's presence. So I need to pass on a parameter with the readhost value. 

    Am I getting close? 

    Friday, July 17, 2015 6:13 PM
  • Invoke-Command -session $s -ScriptBlock {restart-computer $readhost -force}

    Should read

    Invoke-Command -session $s -ScriptBlock {restart-computer localhost -force}


    \_(ツ)_/

    Friday, July 17, 2015 6:42 PM
  • You really don't need to remote for any of this with the exception of the 'Repair" line.


    \_(ツ)_/

    Friday, July 17, 2015 6:44 PM
  • When I put in the localhost in the script the wait commando isn't working because it's being processed on the local computer. The -wait should be passed back to the computer where the script is started from... 
    Sunday, July 19, 2015 1:05 PM
  • I found a correct syntax in which the wait command works fine: 

    $readhost = Read-Host "enter computername"
    $s = New-PSSession –computername $readhost
    Restart-Computer -wait  -for WinRM -ComputerName $readhost -Force

    Sunday, July 19, 2015 1:11 PM
  • I found a correct syntax in which the wait command works fine: 

    $readhost = Read-Host "enter computername"
    $s = New-PSSession –computername $readhost
    Restart-Computer -wait  -for WinRM -ComputerName $readhost -Force

    Think carefully about what you are doing here.  Does it look like it makes sense?  What is $s used for?  Nothing.

    As I pointed out. You do not need remoting here.

    $readhost = Read-Host "enter computername"
    Restart-Computer -wait  -ComputerName $readhost -Force

    That is all you need.  You cannot use remoting with restart and wait.  It doesn't make sense.  How can a remote command wait when a computer is restarting.


    \_(ツ)_/

    Sunday, July 19, 2015 1:16 PM
  • Your absolutely right man, the $s is not used for anything in here! It doesn't make any sense. To get a clearer understanding of what i'm trying to achieve here and maybe there is a much more easier way than i'm thinking about now. 

    When a script runs sometimes it needs to continue after a reboot, so that's why i want to create the session and wait for the winrm service to come back up and let my script continue. 

    This is especially for whenever things are in use by memory and the computer needs a reboot first before the script can edit the settings I want on the computer. Or uninstall an application and install a new application after a reboot. 

    Sunday, July 19, 2015 3:48 PM
  • Here I created a script, when i'm good enough in writing powershell scripts I can pass these on to our support engineers so they can perform tasks remotely on computers. This scripts let's the app-v client package repair, check if the reboot is succesfully and then does a final check on the app-v package. This is why I want to have the -wait commando. Now the check is just a simple get-appvclientpackage, but it can be used for various tasks after the computer has been rebooted. (also error checking must be included in future scripts) This is just a very basic script with my limited knowledge. If you have any tips on how to perform these tasks differently, please share :).. 

    $readhost = read-host ‘enter a computername’
    If ($readhost –match '[bnl]+[-]+[\d]+[b]+[-]+[\d]')

    {
    $s = New-PSSession –computername $readhost
    Invoke-Command -session $s -ScriptBlock {taskkill.exe /f /im explorer.exe}
    Invoke-Command -session $s -ScriptBlock {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global}
    Restart-Computer -wait  -for WinRM -ComputerName $readhost -Force 

    Write-Host 'The computer has been succesfully rebooted, continuing the script'

    Invoke-Command -ComputerName $readhost -ScriptBlock {Get-AppvClientPackage -name *office*} 

    }

    else 
    { write-output “$readhost is not valid computername”
    }

    Sunday, July 19, 2015 4:09 PM
  • What you are looking for is called a workflow.  It can resume after a restart.  If you just want to run a couple of commands then here is an easy way.

    function Fix-App{
        Param($computername)
    
            Get-Process explorer.exe -ComputerName $computername|  Stop-Process
            Invoke-Command {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global} -Computer $computername
            Restart-Computer -wait -ComputerName $computername -Force 
            Invoke-Command -ComputerName $computername -ScriptBlock {Get-AppvClientPackage -name *office*} 
    }

    This can only be run remotely.  TO do this on the local system you must use a workflow.


    \_(ツ)_/


    • Edited by jrv Sunday, July 19, 2015 4:24 PM
    • Marked as answer by Jay2k_technet Sunday, July 19, 2015 6:50 PM
    Sunday, July 19, 2015 4:24 PM
  • How should I run this command... whenever I use this it only echo's the written text... I'm going to take a powershell course soon. I'm really feeling a nooby lol! 
    Sunday, July 19, 2015 4:45 PM
  • What command are you referring to?


    \_(ツ)_/

    Sunday, July 19, 2015 4:46 PM
  • I try to run this from powershell ISE but that isn't the correct method right? I saved it as a script and run it from powershell but nothing is returned back...
    Sunday, July 19, 2015 4:54 PM
  • It works without the function command in the script and running it from powershell. I run it like .\pstest1.ps1 -computername testcomputer01

        Param($computername)

            Get-Process explorer.exe -ComputerName $computername|  Stop-Process
            Invoke-Command {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global} -Computer $computername
            Restart-Computer -wait -ComputerName $computername -Force 
            Invoke-Command -ComputerName $computername -ScriptBlock {Get-AppvClientPackage -name *office*}

    Sunday, July 19, 2015 4:59 PM
  • Thanks so far I will dive more deeply into powershell... there are so many ways of doing stuff... 
    Sunday, July 19, 2015 5:36 PM
  • Your script actually just works fine :) I needed to sort out how a function really works. First I execute the script and the type in powershell: fixapp -computername hostname... am I right? Or can you also directly call the function the first time? 
    Sunday, July 19, 2015 6:00 PM
  • Look up "dot sourcing in powershell"

    \_(ツ)_/

    Sunday, July 19, 2015 6:06 PM
  • Thanks dude! I'm reading the resources you gave me.. i'm also following the cbt ultimate powershell course now.. 30 hours of powershelling lol! I still want the script to ask for a user input and don't let a support technician fill in the commands and just press enter when using the script (or build a gui when i'm very good). This is the last thing i'm going to post.. thanks for all of your help so far! 


        $computername = Read-Host 'please enter a computername'
        
        Function fixapp {param($computername)

            Get-Process explorer.exe -ComputerName $computername |  Stop-Process
            Invoke-Command {Get-AppvClientPackage -name *office* | Repair-AppvClientPackage -Global} -Computer $computername
            Restart-Computer -wait -ComputerName $computername -Force 
            Invoke-Command -ComputerName $computername -ScriptBlock {Get-AppvClientPackage -name *office*} }
            # 

            fixapp -computername $computername


    Sunday, July 19, 2015 6:38 PM
  • Sounds like a good plan.  You will do well in a very short period of time. Post back when you get stuck on some of the trickier details.

    Have fun and good luck.


    \_(ツ)_/

    Sunday, July 19, 2015 7:09 PM
  • Yeah :) I'm doing this for a bit longer than a week.. but I really like to do this and really make automation scripts for our support desk and so on. Thanks for letting me have a look at the functions.. will be really cool if I can load some powershell profiles at our support desk technicians and solve problems with just a simple powershell! Need to have a good error correction thought... won't be funny if the restart-computer accepts a name like *... oops! 
    Sunday, July 19, 2015 7:23 PM