Im stuck on USMT migration. Here is my code:
$scriptA = "\\PL-HVEZDAP\backup\USMTBin\scanstate.exe \\PL-HVEZDAP\backup /ue:* /ui:$name /o /i:'\\PL-HVEZDAP\backup\USMTBin\miguser.xml' /i:'\\PL-HVEZDAP\backup\USMTBin\migapp.xml' /c"
$scriptB = "\\PL-HVEZDAP\backup\USMTBin\loadstate.exe \\PL-HVEZDAP\backup /ue:* /ui:$name /i:'\\PL-HVEZDAP\backup\USMTBin\miguser.xml' /i:'\\PL-HVEZDAP\backup\USMTBin\migapp.xml' /c"
$scriptA = [scriptblock]::Create($scriptA)
$scriptB = [scriptblock]::Create($scriptB)
Invoke-Command -ComputerName $computer -scriptblock $scriptA
Invoke-Command -ComputerName $remcomputer -scriptblock $scriptB
There is a problem on last row - I get error:
The term '\\PL-HVEZDAP\backup\USMTBin\loadstate.exe' is not recognized as the name of a cmdlet, function, script file,
or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
+ CategoryInfo : ObjectNotFound: (\\PL-HVEZDAP\ba...n\loadstate.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
but if I run $scriptb = get-process, everything works like charm...
Can somebody help me with this? Thanks a lot.
Looks like a kerberos double-hop problem. Once you connect to a remote computer with Invoke-Command, you can't use any commands that implicitly use your authentication again (this includes cmdlets, executables, and connecting to file shares).
This is a function of how Kerberos is designed. You can use a different type of authentication called CredSSP with Invoke-Command to delegate credentials but this requires some set up on both ends.
Often it's easier to re-think where the pieces are stored and/or executed.
Since you make extensive use of a file share, you might consider not using Invoke-Command to a remote machine and instead executing the backup script locally on the target machine.
One way to do this, while still being able to store the script centrally is to make a scheduled task on the target machine that runs this script. It can even be pushed out via GPO if you're in a domain.
Then you can start the task when you want that code to run.
You can even use Invoke-Command -ComputerName $remcomputer -ScriptBlock { schtasks.exe /Run /TN "My Task" } and that will work.
Related
I am trying to generate some IDs using a adobe tool called adobe-licensing-toolkit.exe.
I need to run the command remotely in 100 computers.
Executing the command manually works flawless
C:\temp\adobe-licensing-toolkit.exe -c -f \\XXXXXXX\c$\temp\IDs.csv
Adobe Licensing Toolkit (1.1.0.98)
Operation Successfully Completed
Now I tried to replicate that using remote PS without success. I think it is a matter of parameters.
The following command ends correctly but it generates the file locally in the remote computer.
Invoke-Command -ComputerName $comp -ScriptBlock { param($whatToDo,$targetCSV) &('C:\TEMP\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV "C:\temp\ID.csv"} -ArgumentList "generateChallengeKey","filepath"
If I try to use the UNC in the parameter, the result is Operation failed.
Invoke-Command -ComputerName $comp -ScriptBlock { param($whatToDo,$targetCSV) &('\\XXXXXXXX\c$\TEMP\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV "C:\temp\ID.csv"} -ArgumentList "generateChallengeKey","filepath"
I also tried to add path in the parameter. In that case is powershell who complains.
Invoke-Command -Session $Server01 -ScriptBlock { param($whatToDo,$targetCSV) &('C:\TEMP\FRL\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV } -ArgumentList #("generateChallengeKey","filepath \\XXXXXXX\c$\temp\ID.csv")
unknown option -- filepath \\XXXXX\c$\temp\ID.csv
+ CategoryInfo : NotSpecified: (unknown option ...c$\temp\ID.csv:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : XXXXXXX
I have the feeling that the issue is in the way parameter is passed but I haven't managed to find the solution.
The exe file is already present in all target computers.
Any suggestion?
Thanks
I would presume you have toolkit present in all remote computer in path: "C:\TEMP\adobe-licensing-toolkit.exe". You can simply use
Invoke-Command -ComputerName $comp -ScriptBlock { & "C:\TEMP\adobe-licensing-toolkit.exe" -c -f \\XXXXX\$env:Computername-IDs.csv}
Adding $env:Computername in share path would generate unique file for each computer.
I'm trying to run the following PS command from server A on server B (10.11.12.13) which is supposed to run a PS script locally but from a UNC path. So I have:
Invoke-Command -ComputerName 10.11.12.13 -Credential $cred -ScriptBlock {powershell.exe -ExecutionPolicy Bypass "\\netshare\PSScript.ps1"}
After I enter my credentials it fails with the error:
*\\netshare\PSScript.ps1 : The term '\\netshare\Powershell\PSScript.ps1' is not recognized as
+CategoryInfo: NotSpecified: (\\netshare\Pow... recognized as :String) [],
RemoteException
+FullyQualifiedErrorId: NativeCommandError
+PSComputerName: 10.11.12.13*
In my command if I replace the unc path with a local path such as C:\files\PSScript.ps1 it runs fine.
The remote server is running PS v4. I've already run the command:
Set ExecutionPolicy Unrestricted on server B. I also tried adding -File after Bypass but that also fails with a different error.
How do I get that script to run from server B? Solutions like copying a script to server B first will not work. I also need this to run from the command line (not from a script).
Three things:
There is no reason to invoke powershell.exe from within PowerShell. Invoke the script by the call-operator &
Pay attention to the double-hop issue. If you connect to a remote computer by network logon you can't authenticate from within this remote connection to another remote computer (here network share).
Use Invoke-Command -FilePath C:\PSScript.ps1 -ComputerName 10.11.12.13 instead. Thereby you don't have to copy the file to every remote computer in advance.
Finally got it working with this:
Invoke-Command -FilePath \\netshare\PSScript.ps1 -ComputerName 10.11.12.13 -Credential $cred
Would still have liked to figure out how to run it inside a ScriptBlock however.
I'm trying to create a script to query members of a sccm2012 device collection so that I can pipe that into put into maintenance window. I need to run this from a remote machine.
Here's what I have - if I run each line by line it works fine.
But if I run it as a script continuously fails. If you could point me in the right direction please or solve for me. PS I'm not that good at PS but getting better.
PS F:\Install\Scritps> Enter-PSSession -ComputerName SERVER -ConfigurationName Microsoft.PowerShell32
Import-module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
cd P01:\
Import-module : The specified module 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' was not loaded because no
valid module file was found in any module directory.
At line:4 char:1
+ Import-module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConso ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (C:\Program File...ionManager.psd1:String) [Import-Module], FileNotFoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
cd : Cannot find drive. A drive with the name 'P01' does not exist.
At line:6 char:1
+ cd P01:\
+ ~~~~~~~~
+ CategoryInfo : ObjectNotFound: (P01:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
I would guess that Enter-PSSession fails becauase it is designed for interactive use, and not to be used in a script. If that fails, then the following commands would fail because you're missing the SCCM 2012 Admin Console.
To run remote commands in a script, use Invoke-Command. Combine it with New-PSSession if you need a special configuration, different credentials etc.
$sess = New-PSSession -ComputerName SERVER -ConfigurationName Microsoft.PowerShell32
Invoke-Command -Session $sess -ScriptBlock {
Import-module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
cd P01:\
gci
}
Powershell Equivalent to Query in SCCM UI
I'm guessing you'd like to script the same queries as SCCM allows you to specify in this device collection query rules property dialog box:
The most reliable way to run such a query on an SCCM server from powershell on a workstation is using CIM. The trick is figuring out how to run the query so that it is interpreted in exactly the same way as if SCCM itself runs the query. Doing it this way seems to achieve that goal:
$SiteCode = 'ST1' # replace this with your SCCM site code
$SccmServerName = 'sccm01' # replace this with your server name
# replace this with your query
$query = #'
select
SMS_R_SYSTEM.ResourceID,
SMS_R_SYSTEM.ResourceType,
SMS_R_SYSTEM.Name,
SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,
SMS_R_SYSTEM.Client from SMS_R_System
inner join
SMS_G_System_COMPUTER_SYSTEM
on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId
where
SMS_G_System_COMPUTER_SYSTEM.Manufacturer like "%Microsoft%"
'#
$params = #{
ComputerName = $SccmServerName
Query = $query
NameSpace = "Root\SMS\Site_$SiteCode"
}
Get-CimInstance #params
The query above happens to be for a device collection of Hyper-V guests . You can change $query to whatever you want. Once you get the query working here, you should be able to copy and paste it to/from the SCCM device colleciton UI.
On Powershell Remoting
If the call to Get-CimInstance results in an error that indicates that Powershell remoting or CIM is not working in your case, then you should probably focus on understanding that aspect of your environment. Powershell remoting has some nuanced limitations and prerequisites that depend, among other things, on firewall settings, enabling remoting, and what version of Powershell and operating systems you're running. It's not worth remembering all the details. The reference I use is Chapter 10 of Powershell in Depth, second edition.
If it turns out you must use WMI instead of CIM, it should be fairly straightforward to translate the call to Get-CimInstance to Get-WmiObject.
Frode F. you are the man
yep it works real good.
at the end after the } i put "Remove-PSSession -ComputerName SERVER"
so that when you run it a few times the concurrent session fill up. with this extra line no worries.
PSEXEC started to give me some trouble, and I decided to recode in PowerShell.
This batch command used to work for me, before PSEXEC started messing things up:
psexec -accepteula \\<ServerToBeUpdated> -u <User> -p <Password> cmd /c "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe /silent /Update"
I'm trying to do this with Invoke-Command in Powershell, but with no luck so far.
I've tried many combinations, and googled a lot, and overall it seems that PowerShell is not fond of the UNC path I'm trying to install from.
Here is what I've got:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Start-Process -FilePath "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe" -ArgumentList "/update /silent" -wait }
I get this error message:
This command cannot be run due to the error: Access is denied.
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
+ PSComputerName : DE5441
Some people say that the setup.exe has be copied locally on the remote server. But this does not seem to be an option for me, mainly for two reasons.
My setup.exe identifies that it is not in the right path, then it kills the local the setup.exe process, and automatically starts a new setup.exe from the UNC path.
I also need the ExitCode from my setup.exe, which gets lost when the "killing" starts as mentioned in reason number 1.
As a final note, I did grant access for PowerShell to run remotely with the Enable-PSRemoting command, and I also get expected results from this simple test:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Hostname }
You are experiencing a so called double-hop authentication issue. If using normal authentication you will not be able to authenticate to a second computer from the machine you are invoking the command on.
To solve this you can use CredSSP.
To enable CredSSP on the machine that is being called:
Enable-WSManCredSSP -Role Server -force
To enable CredSSP on the client:
Enable-WSManCredSSP -Role Client -DelegateComputer server.domain.com -force
The -delegateComputer parameter expects a FQDN but also takes wildcards.
After enabling CredSSP you can use it to invoke your command with the parameter -authentication CredSSP
It seems that most common commands are gone when using workflow sessions in powershell:
PS P:\> $session = New-PSWorkflowSession -ThrottleLimit 3
PS P:\> Invoke-Command $session {Write-Output "test"}
The term 'Write-Output' is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Write-Output:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
What can I do to make all the common commands normally available in workflows available through a session?
Since you are working with a workflow session, you will want to put your commands in a workflow.
$session = New-PSWorkflowSession -ThrottleLimit 3
Invoke-Command $session {
workflow test {
Write-Output -Input "test"
}
test
}
For more info, check out PowerShell Workflows: Restrictions and High Level Architecture of Windows PowerShell Workflow (Part 1)