SCCM PowerShell Get Configuration Baseline computers - powershell

I am working with Configuration Baselines. I would like to start from "Get-CMBaseline -Name MyBaselineName" and work my way to the name of the machines. I am try to figure out how to get the machines names that are "Compliant", "Error", and "Non-Compliant". I see the names of the machines in "Deployment Status" but I need them via PowerShell.

There are many things that are possible via the built in cmdlets but some just are not (yet?). However it is almost always possible to get the same behavior the console has with wmi (because the console uses wmi itself)
To find out how it is good to know that there is a log file "SMSProv.log" that tells you what the console does for every dialog you open. It is located on the site server wherever you installed the ConfigMgr in a sub-folder Logs (so default would be %Program Files%\Microsoft Configuration Manager\Logs).
So if you use that when checking the deployment status of a baseline you will notice that it basically translates to 3 commands (All in the namespace
Root\SMS\site_<SiteCode>
on your siteserver):
SELECT * FROM SMS_DCMDeploymentCompliantAssetDetails WHERE AssignmentID=<AssignmentID>
SELECT * FROM SMS_DCMDeploymentNonCompliantAssetDetails WHERE AssignmentID=<AssignmentID>
SELECT * FROM SMS_DCMDeploymentErrorAssetDetails WHERE AssignmentID=<AssignmentID>
where AssignemtID is the ID you would get e.g. from
(Get-CMBaselineDeployment -Name "<Your Baslines Name>").AssignmentID
A little exception would be that the console filters the error further by error type but to me it seems like this is maybe not even what you want and you could easily do it in Powershell later if you need to.
The SQL command is also available in most cases in the SMSProv.log, and in some cases it leads to a faster execution. However in this one probably not really and it is a lot more complex most of the time.

Related

Powershell script to show file extensions in File Explorer

I'm fairly new to the world of Powershell and currently I'm trying to push a Powershell script via Intune to the company devices (all Windows 10 21H2 machines) that will show the file extensions in File Explorer.
So far, I've found this:
Set-Itemproperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'HideFileExt' -value 0
The PS script is pushed via Intune to a test device and the monitor tells me the policy is applied successfuly but the file extensions are still not visible.
Is there something wrong with the line of code?
My original comment which helped:
The script works fine. I am positive that it is not applied successfully, despite Intune telling you it did. While it is not part of that question, I suppose you should check the user context in which the script is applied and if the eventvwr or any other possible source tells you why the script did not apply correctly. Also, after trying the script locally for myself, you need to refresh the explorer tab via f5 for the change to apply.
Solution was to set it as system/device rights, since it was indeed run as user context, hence solving the problem.
This was the solution:
"The script works fine. I am positive that it is not applied successfully, despite Intune telling you it did. While it is not part of that question, I suppose you should check the user context in which the script is applied and if the eventvwr or any other possible source tells you why the script did not apply correctly. Also, after trying the script locally for myself, you need to refresh the explorer tab via f5 for the change to apply" –
Bowshock

Command line showing nothing no output

I have been studying privilege escalation on windows and came across some powershell script that look up vulnderabilties.
When i run these ( multiple scripts) I get no output while the documentation i find on them and video's all show output. Unless I specifically tell it to output it to a file,
This makes me think it has something to do with my system. I am running windows 7 64-bit on a local standard user.
For example i used:
https://github.com/rasta-mouse/Sherlock
and:
https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerUp
Did you try to check if your current user has changed to Administrator ?Maybe there is a GPO or theses privileges esclations are not working for your version

PowerShell: Start-Process Firefox, how do he know the path?

When I call the following code:
Start-Process Firefox
Then the PowerShell opens the browser. I can do that with several other programs and it works. My question is: How does the PowerShell know which program to open if I type Firefox? I mean, Im not using a concrete Path or something ...
I though it has something to do with the environment variables ... But I cannot find any variable there which is called Firefox ... How can he know?
I traced two halves of it, but I can't make them meet in the middle.
Process Monitor shows it checks the PATHs, and eventually checks HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe so that's my answer to how it finds the install location, and then runs it.
That registry key is for Application Registration which says:
When the ShellExecuteEx function is called with the name of an executable file in its lpFile parameter, there are several places where the function looks for the file. We recommend registering your application in the App Paths registry subkey.
The file is sought in the following locations:
The current working directory.
The Windows directory only (no subdirectories are searched).
The Windows\System32 directory.
Directories listed in the PATH environment variable.
Recommended: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
That implies PowerShell calls the Windows ShellExecuteEx function, which finds FireFox as a registered application, or it tries the same kind of searching itself internally.
Going the other way to try and confirm that, the Start-Process cmdlet has a parameter set called UseShellExecute. The 'Notes' of that help says:
This cmdlet is implemented by using the Start method of the System.Diagnostics.Process class. For more information about this method, see Process.Start Method
Trying to trace through the source code on GitHub:
Here is the PowerShell source code for Start-Process.
Here, at this line it tries to look up the $FilePath parameter with CommandDiscovery.LookupCommandInfo.
Here it checks else if (ParameterSetName.Equals("UseShellExecute"))
Then Here is the .Start() function which either starts it with ShellExecute or Process.Start()
OK, not sure if ShellExecute and ShellExecuteEx behave the same, but it could be PS calling Windows, which is doing the search for "FireFox".
That CommandSearcher.LookupCommandInfo comes in here and follows to TryNormalSearch() which is implemented here and immediately starts a CommandSearcher which has a state machine for the things it will search
SearchState.SearchingAliases
Functions
CmdLets
SearchingBuiltinScripts
StartSearchingForExternalCommands
PowerShellPathResolution
QualifiedFileSystemPath
and there I get lost. I can't follow it any further right now.
Either it shortcuts straight to Windows doing the lookup
Or the PowerShell CommandSearcher does the same search somehow
Or the PowerShell CommandSearcher in some way runs out of searching, and the whole thing falls back to asking Windows search.
The fact that Process Monitor only logs one query in each PATH folder for "firefox.*" and then goes to the registry key suggests it's not doing this one, or I'd expect many more lookups.
The fact that it logs one query for "get-firefox.*" in each PATH folder suggests it is PowerShell's command searcher doing the lookup and not Windows.
Hmm.
Using Process Monitor I was able to trace the PowerShell.
It first searches the $env:path variable, then the $profile variable.
In my case firefox wasn't found and then it searches through a whole lot in the Registry and somehow finds it.
It might have something to do with how firefox is installed on the system.

PS1 uninstallation script in SCCM

I'm a nub scripter and am trying to write a really simple script to taskkill 2 programs and then uninstall 1 of them.
I wrote it in Powershell and stuck it in SCCM for deployment...however every time I deploy it, it's not running the last line to uninstall the program.
Here's the code:
# Closing Outlook instance
#
taskkill /IM outlook.exe /F
#
# Closing Linkpoint instance
#
taskkill /IM LinkPointAssist.exe /F
#
# Uninstalling Linkpoint via uninstall string if in Program Files
#
MsiExec.exe /X {DECDCD14-DEF6-49ED-9440-CC5E562FDC41} /qn
#
# Uninstalling Linkpoint via WmiObject if installed manually in AppData
Get-WmiObject -class win32_product -Filter "Name like '%Linkpoint%'" | ForEach-Object { $_.Uninstall()}
#
Exit
Can someone help? SCCM says the script completes with no error and I know it's able to execute it since the taskkills work...but it's not uninstalling the program.
Thanks in advance for any input.
So, SCCM is running this script, and nothing in the script is going to throw an error.
If you want to throw an error which SCCM can return to know how the deployment went, you need to add an extra step.
$result = Get-WmiObject -class win32_product -Filter "Name like '%Linkpoint%'" | ForEach-Object { $_.Uninstall()}
if ($result.ReturnValue -ne 0){
[System.Environment]::Exit(1603)
}else
{
[System.Environment]::Exit(0)
}
I see a lot of these kinds of questions come through on SO and SF: Someone struggling with unexpected behavior of an application, script, or ConfigMgr and very little information about the assumptions I can make about their environment. At that stage, it would typically be days of interaction to narrow the problem to a point where a solution is possible.
I'm hoping this answer can serve as a reference for future such questions. The first question to OP should be "Which of these 9 principles are you violating?" You could think of it as a sort of Joel Test for ConfigMgr application packaging.
Nine Steps to Better ConfigMgr Application Packages
I have found that installing and uninstalling applications reliably using ConfigMgr requires carefully sticking to a bunch of principles. I learned these principles the hard way. If you're struggling to figure out why an application is not working right under ConfigMgr, odds are that you will answer "no" to one of the following questions.
1. Are you testing the entire lifecycle?
In order to have any hope of reliably managing an application you need to test the entire lifecycle of an application. This is the sequence I test:
Detect: make sure the detection script result is negative
Install: install the application using your installation script
Detect: make sure the detection script result is positive when run
Uninstall: uninstall using your uninstallation script
I run this sequence repeatedly making tweaks to each step until the whole sequence is working.
2. Are you testing independently of ConfigMgr first?
Using ConfigMgr to test your application's lifecycle is slow and has its own ways of failing that can mask problems with your application package. The goal, then, is to be able to test an application's installation, detection, and uninstallation separate from but equivalent to the ConfigMgr client. In order to achieve that goal you end up with three separate scripts for each application:
Install-Application.bat - the entry point for your installation script
Detect-Application.ps1 - the script that detects whether the application is install
Uninstall-Application.bat - the entry point for your uninstallation script
Each of these three scripts can be invoked directly by either you or the ConfigMgr client. For applications installed as system you need to use psexec -s to invoke scripts in the same context as ConfigMgr (caveat).
3. Are you aware of context?
Installers can behave rather differently depending on the context they are invoked in. You need to consider whether an application is installed for a user or the system. If it is installed for the system, when you test independently of ConfigMgr, use psexec -s to invoke your script.
4. Are you aware of user interaction?
An installer can also behave rather differently depending on whether a user can interact with it. To test a script as system with user interaction, use psexec -i -s.
5. Did you match ConfigMgr to the tested context and user interaction?
Once you have the full lifecycle working, make sure you select the correct corresponding options for context (installed for user vs. system) and interaction (user can interact with application, or not). If you don't do this, the ConfigMgr client will be installing the application different from the way you tested, so you really can't expect success.
6. Are you aware of the possibility of application detection context mismatch?
The context that detection scripts run in depends on whether the application is deployed to users or systems. This means that in some cases the installation and detection contexts won't matched. Keep this in mind when you write your detection scripts.
7. Have you structured your scripts so that exit codes work?
ConfigMgr needs to see exit codes from your installation and uninstallation scripts in order to do the right thing. Installers signal failure or the need to reboot using exit codes. In order for exit codes to get to the ConfigMgr client you need to ensure that your install and uninstall scripts are structured correctly.
for batch scripts, use exit /b %errorlevel% to pass the exit code of your executable out to the ConfigMgr client
for PowerShell scripts, this is the only way I have seen work reliably
8. Are you using PowerShell scripts for detection?
ConfigMgr has a nice user interface for checking things like the presence of files, registry keys, etc as a proxy for whether an application is installed. The problem with that scheme is that there is no way to test application detection separately from and equivalent to the ConfigMgr client. If you want to test the application lifecycle independent of the ConfigMgr client (trust me, you want that), all your detection must occur using PowerShell scripts.
9. Have you structured your PowerShell detection scripts correctly?
The rules ConfigMgr uses to interpret the output of a PowerShell detection script are arcane. Thankfully, they are documented.

InstallShield Automation can't create object

I am working with Installshield 2014 and 2011. I'm using major upgrades and automated build scripts to handle the build. InstallShield is the stand alone build ver. for both.
Now everything worked fine with Installshield 2011 on windows 2003 servers. I could use the automation interface to open a project, change the product code (for the major upgrade) then save it right before building the installer.
The code for such is in a vbs file as such:
Dim oISM, oGUID
Set oGUID = CreateObject("InstallShield.GUID")
Set oISM = CreateObject("IswiAuto17.ISWiProject")
oISM.OpenProject strInstallShieldProjectFile
oISM.ProductCode = "{" & oGUID.CreateGUID( ) & "}"
oISM.SaveProject : oISM.CloseProject : set oISM = Nothing
Now we've upgraded to windows 2012 servers and InstallShield 2014. I've double checked and according to InstallShield the only change needed is the ver number (17 changes to 21).
But now nothing works. If I take the code out and put it in it's own vbs file for testing and run it, I get this:
ActiveX component can't create object: 'InstallShield.GUID'
Looking on google I see that's from running in 64 bit mode.... but I'm not. I'm running a cmd prompt in 32 bit mode.
http://helpnet.flexerasoftware.com/installshield18helplib/AutomationInterface64Bit.htm
I tried calling the script with:
%WINDIR%\SYSWOW64\cmd.exe /c cscript
as suggested here:
How do I run a VBScript in 32-bit mode on a 64-bit machine?
and other places. This did not work as I got the same error.
I tried removing that line as I'm sure I can create a guid another way, and reran it.
Then I got this when it tries to create the project:
Unknown runtime error: 'CreateObject'
Once again google came up and I checked:
https://community.flexerasoftware.com/showthread.php?189788-Automation-error
and couple others. I tried ensuring the dll was registered using the regsvr32 and it said it was successful. But after rerunning, it gave the same error.
I tried directly coping the command from the InstallShield documentation to ensure no spelling mistakes but again same error.
I even tried switching the case of the "sw" as mentioned here:
Installshield Automation is failing while running vbscript with error unable to create object
Again though, same error.
I also tried switching to powershell as powershell is much easier to debug and read.
The powershell code is simple and is as follows:
$oIsm = new-object -comobject IswiAuto21.ISWiProject
$oISM.OpenProject("$file")
$oISM.ProductCode = "{" + [guid]::NewGuid() + "}"
$oISM.SaveProject(); $oISM.CloseProject(); $oISM = $null
But this also does not work despite these saying it should:
https://community.flexerasoftware.com/showthread.php?190769-Automation-using-Powershell
http://blogs.flexerasoftware.com/installtalk/2011/01/getting-started-with-installshield-automation-and-powershell.html
When I use the 32 bit powershell I get this error:
new-object : Creating an instance of the COM component with CLSID {78D393F9-76E3-438C-9CAB-6664EF5FE1F2} from the IClassFactory failed due to the following error:
800a801d Exception from HRESULT: 0x800A801D.
If I run solely the vbs without a cmd prompt I also see the error of 800A801D in a pop up box.
How can I fix this? I'd like to use powershell but a vbs fix would help as well at this point. I have tried everything I can think of and google says I'm doing it correctly (32 bit powershell/cmd, registering the dll, creating the object, etc).
Did you install the automation interface? Typically it's an optional feature that's set to absent when you install InstallShield.
Typically the HRESULT should tell you what's wrong, or be so generic that it doesn't help. In this case, it's a bit of an enigma as I haven't found its definition anywhere. The leading 0x800A... indicates FACILITY_CONTROL and the trailing ...801d happens to match the tail of TYPE_E_LIBNOTREGISTERED (0x8002801D), but I don't know whether that's meaningful. Unfortunately FACILITY_CONTROL is defined by the control that issues the error, and that's not clear here.
Let's try to figure out what's wrong. My bet is on COM registration. If you want, you can skip to a likely fix by running regsvr32 C:\...\System\ISWiAutomation21.dll.
So let's follow what CreateObject("IswiAuto21.ISWiProject") will do. First it has to look up the ProgID:
C:\>reg query HKCR\ISWiAuto21.ISWiProject\Clsid
HKEY_CLASSES_ROOT\ISWiAuto21.ISWiProject\Clsid
(Default) REG_SZ {78D393F9-76E3-438C-9CAB-6664EF5FE1F2}
Then it has to look up the CLSID, and in this case, its InprocServer32 key:
C:\>reg query HKCR\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\InprocServer32
HKEY_CLASSES_ROOT\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\InprocServer32
(Default) REG_SZ C:\...\ISWiAutomation21.dll
ThreadingModel REG_SZ Apartment
If either of these are missing, it will be unable to find the COM server. In addition, the TypeLib subkey and the Type Library it references are both important:
C:\>reg query HKCR\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\Typelib
HKEY_CLASSES_ROOT\Clsid\{78D393F9-76E3-438C-9CAB-6664EF5FE1F2}\Typelib
(Default) REG_SZ {92278CC1-987E-4A01-940C-47DCADF27496}
C:\>reg query HKCR\Typelib\{92278CC1-987E-4A01-940C-47DCADF27496}\1.1\0\win32
HKEY_CLASSES_ROOT\Typelib\{92278CC1-987E-4A01-940C-47DCADF27496}\1.1\0\win32
(Default) REG_SZ C:\...\ISWiAutomation21.dll
If any of this information is missing, it will have to be repaired. The COM Server itself may need to probe several additional IDs at this point, so there's a chance that even if this subset is okay, there are others that are missing or corrupted. Self-registering the COM server should fix this. So should running the installation's repair.
Note that all of these queries were done using the 32-bit command C:\Windows\SysWow64\reg.exe, or you can peruse the registry visually with C:\Windows\SysWow64\regedit.exe.