SCCM cmdlet from a remote PC - powershell

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.

Related

invoke-command with a parameter accessing UNC

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.

How to use Powershell to grant Windows application or executable to use your network profile?

Powershell newbie here. I am learning Powershell (yes, I have been ignoring it all these years) as I have never needed this one particular need of mine. I have looked at PS tutorial sites and, of course, StackOverflow for any tips. Seems like my need is unique.
Short story, how do you execute an application (for example, notepad.exe) on a local machine to open a network shared file but the local machine has a generic logged-on user but the network share requires a privileged user (like mine) to open the file. I want the app/executable to inherit my credentials but not set the local machine itself. I want to run a local app/executable as if I logged on to the local machine with my credentials.
I have read PS can do this exact thing so I have been experimenting with Powershell command line:
start-process "[SOME APP].exe" -FilePath "\DIRECTORY\PATH\WHERE\APP\IS\LOCATED]" -Credential (Get-Credential -Credential "DOMAIN\USERID")
I get an error prompt from the Powershell command line:
start-process : This command cannot be run due to the error: The
system cannot find the file specified. At line:1 char:1
+ start-process "[SOME APP].exe" -FilePath "[\DIRECTORY\PATH\WHERE\APP\IS\LOCATED] ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOp erationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.C
ommands.StartProcessCommand
I plan on using this Powershell script in my LabVIEW executable to assign the VI (virtual instrument) executable my own network login privilege to transfer files to/fro or modify a text file that resides in the network share.
Thanks for your help guys!
You could do something like the following. All you need to do is change the $app variable to the executable you want and save the script as a PS1 file. Someone can run it by right-clicking and selecting Run with PowerShell or opening a PowerShell console and typing in path\scriptname.ps1.
$App = "c:\windows\system32\notepad.exe"
$Credentials = Get-Credential
$WorkingDir = Split-Path $app
$Exe = Split-Path $app -Leaf
Start-Process -FilePath $Exe -WorkingDirectory $WorkingDir -credential $Credentials

Powershell VSCode invoke-command from localhost different user for SCCM

Because VSCode is not able to run a powershell console and debug it as a different user i am trying to get arround it with invoked credentials like this:
Start-Service -Name "WinRM"
$cred = Get-Credential -Credential domain\myuser
Invoke-command -Credential $cred -Computer "localhost" -scriptblock {
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
Set-Location 'XXX:' # my sccm site code
Import-CMComputerInformation -CollectionName "All Systems" -ComputerName "TestComputer" -MacAddress "00:00:00:00:00:69"
}
If i start it in the debugger of VSCode (F5) it starts but cant connect then to the SCCM Server infrastructure. Could someone help me to solve this issue?
Error:
Cannot find drive. A drive with the name 'XXX' does not exist.
+ CategoryInfo : ObjectNotFound: (XXX:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName : localhost
This command cannot be run from the current drive. To run this command you must first connect to a Configuration Manager drive.
+ CategoryInfo : DeviceError: (Microsoft.Confi...ormationCommand:ImportComputerInformationCommand) [Import-CMComputerInformation], InvalidOperationException
+ FullyQualifiedErrorId : CommandCannotExecuteFromCurrentDrive,Microsoft.ConfigurationManagement.Cmdlets.Oob.Commands.ImportComputerInformationCommand
+ PSComputerName : localhost
If i logoff from my machine and login with my admin credentials and execute everything in the invoke-command scriptblock it works.
As i am not allowed to work like this by our company policy's is there maybe a alternative way or something i can do to use the visual studio code debugger?
Have you logged onto the SCCM site server interactively with the credentials you are using and opened the console at least once? I believe this initial first opening is required before the drive is accessible remotely...

Powershell - usmt loadstate.exe - CommandNotFoundException

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.

Running a Setup.exe from a network share, via Invoke-Command in Powershell

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