How to install programs as admin in Powershell - 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.

Related

Installing interactive msi in Remote Machine with Powershell

I have a .msi file in my remote machine which is in a different domain from my local machine. I am able to connect to the remote machine with powershell but how can I install the msi there. The installation process has a lot of inputs to be given along with pressing 'Next' and then again giving a particular input and radio buttons and many more. Thus it is an interactive installation. In my local I am able to do it with [System.Windows.Forms.SendKeys] to imitate the keyboard inputs but as the process will be running in background in the remote machine I don't think SendKeys will work. And 'psexec' is not an option here because in my remote machine I cannot include PSTools with my Powershell. Is there any way to do it with Invoke-Command and -ArgumentList??
If there is a way then how can I choose sequentially whether to input a text in a particular field or click the next button or click any other button within the application window??
I finally got to solve this puzzle with the help of a automation tool called AutoIt. This tool has its own scripting language and can create .exe files to run a particular application and do the corresponding installation steps based on each successive window the application installer pops. After creating the .exe I copied it to my remote machine using Copy-Item or you can use robocopy, then invoked the .exe remotely with the help of psexec. As I had the misconception previously about psexec, it only needs to be integrated with powershell at the local and thus it automatically creates a session of its own and interacts with the remote machine. This is the command to run the .exe on remote machine:-
psexec -i 2 -s -d \\remote_machine_name -u Username -p Password C:\Path_to_exe\installer.exe
You can actually log on to the remote machine and see in the GUI that it is happening. And yes, obviously you need to have the .msi which will be called to be present there in the remote machine so that the .exe can do its job locally in the remote session.

Is it possible to log all powershell commands run on a machine?

We have some .net applications running on a server that run powershell scripts. Is there a setting where we can log every single powershell command run on that machine, without modifying our existing applications? I already tried start-transcript . That command only captures the commands run in the current session.
I believe Microsoft calls what you're after "Over the Shoulder Transcription". It's described here, and will be available in WMF5.

Startup Task not running on Azure Cloud Service role

I'm having difficulties trying to setup a startup task in an Azure role.
The ultimate goal is to disable RC4 cipher, along with other SSL configurations. In my (VS2012Express) project (solution partially achieved following another answer here in SO that led me to https://gist.github.com/sidshetye/29d6d48dfa0c2f5488a4 ) I created a Startup.cmd file like this:
# Execute powershell command to disable RC4 and imporve SSL security settings
ECHO Batch started >> "StartupLog.txt" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\HardenSSL.ps1 >> log- HardenSSL.txt 2>&1
EXIT /B 0
HardenSSL.ps1 is the PowerShell script from the previous link. Both the .cmd and .ps1 scripts are placed in the application root directory, marked as "Content" with properties set to "CopyLocal=Always".
In my service definition, I put this:
<Startup>
<Task commandLine="Startup.cmd" executionContext="elevated" taskType="background"></Task>
</Startup>
Now, when I deploy the application to Azure, "nothing" happens. I configured the role instance to allow remote desktop, connected to the machine. I verified the scripts where published, and there were no log files, RC4 still enabled. I tried to manually run the .cmd and the machine runs the scripts to completion, disables RC4 and restarts. So the scripts are actually "correct".
The problem is that the scripts are not getting fired up at startup. I may be wrong, but I don't see anything related looking Windows events. Actually, the server now keeps all the configurations, but I have to be sure the scripts get executed in case I'll have to publish to new instances/cloud services.
I also tried to:
1. place the scripts on a child directory
2. create other 2 "simpler" .cmd that just create a log file with "script started" to exclude problems related to the .cmd calling the PowerShell script.
None of those scripts got executed.
Hope I've been sufficiently clear, any help would be greatly appreciated.
Thank you in advance,
Alberto
UPDATE 1
Reading through various discussions, I missed one very important thing: the script files are actually published in 2 distinct places, one being inside the /bin folder.
Ex: I placed my scripts in a /StartupScripts folder in my project, and when I connect via Remote Desktop to the Azure server I find the scripts both in "approot/StartupScripts" and in "approot/bin/StartupScripts".
The scripts the are actually executing are those placed inside the "bin" folder. the real problem is that I have probably a path problem inside the .cmd since I now found the execution logs with an error.
Now I will try to change it up and update the question here on SO.
Ok.
In the end it was indeed a problem with a path in my Startup.cmd file: .\HardenSSL.ps1 could not be found if the StartUp Task pointed to a subfolder.
Solution was to place both Startup.cmd and HardenSSL.ps1 files in the application root, remove the ".\" part when calling the PowerShell Script and all worked well.
Anyway, I would like to suggest anyone to pick this other solution I found in stack exchage:
https://security.stackexchange.com/a/79957
It links to a NuGet package that does the same thing as the script I found on the link to github in the original post, just "better"; mainly:
Better configuration of cipher suites, with support for ForwardSecrecy for all reference browsers on SSLLabs
Retain SSL support for Internet Explorer 8 on windows XP (unfortunately still a necessity for us)
Alberto.

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.

powershell remote installing apps

I am trying to install a msi from a network share remotely.
$app = [WMICLASS]"\\$pcname\ROOT\CIMV2:Win32_Product"
$app.Install($AppPath)
I am getting an err 1619. From some sources say that WMI cannot install remotely with first coping it to the local computer and running it. Some sources use this command to exactly.
That way works great, but I want to install via share so when the developer updates this msi, it will update the installed instances automagiclly. If I install them locally, the update would not be detected (not sure of this).
So I have tried using methods along these lines:
Invoke-Command -ComputerName $pcname{ msiexec /quiet /i "\\appsvr\apps\theapp.msi" }
Those commands seem to go off into the blackhole, those that command works when run locally.
Anyone have a method for doing this that works?
In your last scenario, you're credentials are likely getting lost. This is known as the "double-hop authentication" (or maybe it's "second-hop") problem. You're using creds from ServerA, to run something on ServerB, but it in the end has to connect to ServerC.
There's a fix if you have PowerShell v2 installed everywhere and are willing to accept the implications:
http://blogs.msdn.com/powershell/archive/2008/06/05/credssp-for-second-hop-remoting-part-i-domain-account.aspx