PS1 uninstallation script in SCCM - powershell

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.

Related

Restarting an updated powershell script

I'm making a makeshift CI/CD system for my app, the app stops itself when notified of a push to a Github repo and the script automatically runs git pull to bring in changes and some more commands depending on the things that changed. Some of the changes could be to the script.
I want the script to restart itself, without infinite nesting where it could hog resources.
While ($true) {
git pull
# check for changes...
If ($runScriptChanged) {
Break
}
node index.js
}
# ???
Omitted error-checking parts and other updating parts for brevity
Calling itself will probably work, but again, it could hog resources infinitely until stopped
Making a new file to run the above script still leaves a file in the repo that cannot be updated automatically
Start-Process is the best I've found for this, but I'm not sure about it's behavior on Linux
When does the launching shell close? Is it the same as on Windows with -NoNewWindow (where it will stay open, as long as there's something using it)? (Currently I'm running it on Windows Server, so compatibility with Linux isn't a big concern, but it is nice to have)
Which way should I use? Thanks
You may consider using PowerShell jobs and the Start-Job cmdlet. It will start your processes in the background and also has some monitoring and management capabilities using other -Job cmdlets such as Get-Job, Wait-Job,Stop-Job, etc.
See about_Jobs for more information.

Trying to get a Powershell Script that will run in a 2nd window and monitor in real time other running scripts / report all Errors / ExitCodes

I am fairly new to writing code in Powershell. For my job I have to write multiple Powershell scripts to make changes in the Hardware and Software settings as well as the Registry and Group Policy Editor to get these applications to run. These applications are a little older. Upgrading these software applications or the hardware then run on is NOT an option. as an example, when Microsoft releases the new patches on like Patch Tuesday...when those patches are applied there is a high probability that something will be changed which is where I come in to write a script to fix the issue. I have multiple scripts that I run. When those scripts are ran they may end up terminating because of an Error Code or an Exit Code. A large part of the time I do not that the script has failed immediately.
I am trying to figure out a script that I can run in a 2nd PowerShell Console Window. I am thinking that the only purpose of this script is to just sit there on the screen and wait and monitor. Then when I execute a script or Application (the only file extensions that I am worried about are: EXE, BAT, CMD, PS1) if the script/application that I just ran ends with an exit code or an error code....then output that to the screen...in REAL TIME.
Below, I have a small piece of code that kind of works, but it is not what I am wanting.
I have researched online and read and read tons of stuff. But I just can't seem to find what I am looking for.
Could someone please help me with getting a script that will do what I am wanting.
Thank you for your help!!!!
$ExitErrorCode =
"C:\ThisFolder\ThatFolder\AnotherFolder\SomeApplication.EXE # (this
would
# either be an EXE or CMD or BAT or PS1)"
$proc = Start-Process $ExitErrorCode -PassThru
$handle = $proc.Handle # cache proc.Handle
$proc.WaitForExit();
if ($proc.ExitCode -ne 0) {
Write-Warning "$_ exited with status code $($proc.ExitCode)"
}
Possible duplicate of the approaches shown here:
Monitoring jobs in a PowerShell session from another PowerShell session
Monitoring jobs in a PowerShell session from another PowerShell session
PowerShell script to monitor a log and output progress to another
PowerShell script to monitor a log and output progress to another

How to install programs as admin in Powershell

I started to write a powershell script to automate the deployment of new Windows 10 PCs.
I've done a script to install the corporate apps and mapping the network folders and printers.
But I have a problem that I must input the admin password for each program I wish to install.
I've searched the internet and all I found was the runas command, I see that is similar to the su of Linux but I can't push the password.
This is how I made the install of all applications:
Set-Content "$DESTINO\program.bat" -value 'msiexec -i C:\progtemp\program.msi /quiet'
Start-Process $DESTINO\program.bat -Wait
Do you know a better method?
The two main ways to run something as an admin automated are as follows:
Create a Scheduled task to run a script, you can choose to run this escalated and store the credentials as required
Create a startup script using powershell (or batch file if you must!)
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/dn789190(v=ws.11)
Startup scripts run as the user system which is the highest privilege possible. Be aware that network access may not be available at startup and some things may not be accessible to system on your local network etc.
Highly recommend looking at Chocolatey https://www.chocolatey.org and possibly boxstarter: https://boxstarter.org/
to get you started with some automation and package management.
Microsoft also have a similar technology in early stages:
https://learn.microsoft.com/en-us/windows/package-manager/
But frankly Chocolatey is an open framework and its well established and mature at this stage.

PowerShell SCript to Execute CMD.exe with Arguments

SO I have surfed this site and the web and I feel as though I am missing something simple.
I find related questions but none that combine a scriptblock and remote calling of a 3rd party app (not a simply windows function or app)
I have the following string that I can copy into a command window and run without issue
"C:\Program Files (x86)\Vizient\Vizient Secure Channel v2.1\VizientSC.exe" UID=me#musc.edu PWD=XXXXXXXXX HCOID=123456 PRODTYPE=PRO-UHCSECURECHANNEL-CDB PACKAGETYPE=OTH FOLDERPATH="\\da\db5\MyFiles\Viz\20180413"
To simplify this, lets just assume I want to run this same String every time BUT with a REMOTE call.
I have written this many different ways but to no avail using
Invoke-Command -ComputerName "edwsql" -ScriptBlock { .........
I simply want to run the designated string using cmd.exe on a remote machine.
The EXE being run in the string is a 3rd party software that I do not want to install all all possible locations. Much simpler to run remote form the box it is already installed and is secure.
Can someone point me in the right direction???? Pls???? I'm new to PowerShell. I am trying to phase out some old PERL as the folks who can support that on the client site are few and far between these days.
You don't need to try so hard. PowerShell can run commands. If the command you want to run contains spaces, enclose in " (as you have done) and invoke it with the & (call or invocation) operator. This is all you need to do:
& "C:\Program Files (x86)\Vizient\Vizient Secure Channel v2.1\VizientSC.exe" UID=me#musc.edu PWD=XXXXXXXXX HCOID=123456 PRODTYPE=PRO-UHCSECURECHANNEL-CDB PACKAGETYPE=OTH FOLDERPATH="\\da\db5\MyFiles\Viz\20180413"
If a parameter on the executable's command line contains any characters that PowerShell interprets in a special way, you will need to quote it.

possible for PS script to install PS3 and continue on?

I have a PS script that automates server builds. Certain script operations require PS3.
The target environment is Windows Server 2008 R2 SP1 - which out-of-the-box includes PS2.
Is there a clever way for my script to install PS3 and then continue on ?
The goal is to trigger a single script to build the server.
Sure, there's probably a dozen crazy ways to do this. Let's tackle some high level concepts. So, how can might I structure such a script?
switch ($psversion.psversion.major) {
2 {
# trigger unattended install of powershell 3.0 forcing reboot
}
3 {
# do some powershell 3.0 specific stuff
}
}
So, that's a simple example of a single script that you might run twice, and the second time you run it, it will do something different. The other piece of the puzzle on how to run a script, reboot and continue the script can be read about here:
http://www.codeproject.com/Articles/223002/Reboot-and-Resume-PowerShell-Script
Hope this helps,