WIndows - Check my user account has install privileges before install - windows

I am in the process of creating a script a user would run on their local machine to install an application by running msiexec. Unfortunately the install will fail if the user does not have to correct privileges.
msiexec does write to a log and will tell me that it's failed due to permissions but I do not find this to be a very elegant solution.
How can I find out locally from a Windows command line whether or not they can install applications?

I believe that there are policy settings which can allow a non admin user to run an msi, so you may need to incorporate that with an admin check just in case they are set.
#Echo Off
"%__APPDIR__%net.exe" Session >Nul 2>&1 && GoTo Success
Set "RKey=HKCU HKLM"
Set "SKey=SOFTWARE\Policies\Microsoft\Windows\Installer"
Set "KVal=AlwaysInstallElevated"
Set "KDat=0"
For %%A In (%RKey%) Do For /F "Tokens=3" %%B In (
'"%__APPDIR__%reg.exe" Query "%%A\%SKey%" /V "%KVal%" 2^>Nul'
) Do Set/A KDat+=%%B
If %KDat% NEq 2 Exit/B
:Success
Echo( You can install!
Timeout -1
Just change the code below :Success to run your .msi installer.

Related

Check if IIS is installed via .BAT

I'm using the cmd commands bellow to install IIS on my machine, as suggested Here.
start /w pkgmgr /iu:IIS-WebServerRole;IIS-WebServer;IIS-CommonHttpFeatures;IIS-StaticContent;IIS-DefaultDocument;IIS-DirectoryBrowsing;IIS-HttpErrors;IIS-HttpRedirect;
IIS-ApplicationDevelopment;IIS-ASPNET;IIS-NetFxExtensibility;IIS-ASP;IIS-CGI;IIS-ISAPIExtensions;IIS-ISAPIFilter;IIS-ServerSideIncludes;IIS-HealthAndDiagnostics;IIS-HttpLogging;IIS-LoggingLibraries;IIS-RequestMonitor;IIS-HttpTracing;IIS-CustomLogging;IIS-ODBCLogging;IIS-Security;IIS-BasicAuthentication;
IIS-WindowsAuthentication;IIS-DigestAuthentication;IIS-ClientCertificateMappingAuthentication;IIS-IISCertificateMappingAuthentication;IIS-URLAuthorization;IIS-RequestFiltering;IIS-IPSecurity;
IIS-Performance;IIS-HttpCompressionStatic;IIS-HttpCompressionDynamic;IIS-WebServerManagementTools;IIS-ManagementConsole;IIS-ManagementScriptingTools;IIS-ManagementService;IIS-IIS6ManagementCompatibility;IIS-Metabase;IIS-WMICompatibility;IIS-LegacyScripts;IIS-LegacySnapIn;IIS-FTPPublishingService;IIS-FTPServer;IIS-FTPManagement;WAS-WindowsActivationService;WAS-ProcessModel;WAS-NetFxEnvironment;WAS-ConfigurationAPI
I want to check first if it's already installed using CMD to include an if in my batch script. How can I do this using cmd?
As I have no installed IIS I can't fully test this. You can use the registry entries to check the version, installation dir and so on. You can use this in order to see if the IIS is installed:
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\VersionString" >nul 2>&1 && (
echo installed
)||(
echo NOT installed
)
Based on #npocmaka said in the first comment of my question, and also by following the explanation on this WEBPAGE
I've created this .bat file.
#echo off
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp /v VersionString
if %ERRORLEVEL% EQU 1 goto NOT_EXISTS
:EXISTS
echo "IIS installed :-)"
goto:END
:NOT_EXISTS
echo "IIS not installed :-( ... Begin installation"
start /w pkgmgr /iu:IIS-WebServerRole;IIS-WebServer;IIS-CommonHttpFeatures;IIS-StaticContent;IIS-DefaultDocument;IIS-DirectoryBrowsing;IIS-HttpErrors;IIS-HttpRedirect;
IIS-ApplicationDevelopment;IIS-ASPNET;IIS-NetFxExtensibility;IIS-ASP;IIS-CGI;IIS-ISAPIExtensions;IIS-ISAPIFilter;IIS-ServerSideIncludes;IIS-HealthAndDiagnostics;IIS-HttpLogging;IIS-LoggingLibraries;IIS-RequestMonitor;IIS-HttpTracing;IIS-CustomLogging;IIS-ODBCLogging;IIS-Security;IIS-BasicAuthentication;
IIS-WindowsAuthentication;IIS-DigestAuthentication;IIS-ClientCertificateMappingAuthentication;IIS-IISCertificateMappingAuthentication;IIS-URLAuthorization;IIS-RequestFiltering;IIS-IPSecurity;
IIS-Performance;IIS-HttpCompressionStatic;IIS-HttpCompressionDynamic;IIS-WebServerManagementTools;IIS-ManagementConsole;IIS-ManagementScriptingTools;IIS-ManagementService;IIS-IIS6ManagementCompatibility;IIS-Metabase;IIS-WMICompatibility;IIS-LegacyScripts;IIS-LegacySnapIn;IIS-FTPPublishingService;IIS-FTPServer;IIS-FTPManagement;WAS-WindowsActivationService;WAS-ProcessModel;WAS-NetFxEnvironment;WAS-ConfigurationAPI
goto:END
:END
pause

Enabling/Disabling a task in Windows 7

I work for a company where I've developed a batch script which needs to be enabled or disabled at times. I have my main batch file which executes a long process and then two other files to enable or disable it. Both work fine in Windows XP but in Windows 7 when I want to disable the task in task scheduler the cmd prompt comes up and gives me an access denied error. However, this does work successfully if I right click and run as administrator.
Well, this is meant to be an automated process so no one is going to be there to do the right click option and this is being deployed for a large scale of people. So, is there something I can put at the top of the batch script, that will cause a .bat to run as administrator by default?
This script too works for you! Just paste it into the top of your bat file. If you want to review the output of your script, add a "pause" command at the bottom of your batch file.
#echo off
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"=""
echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
pushd "%CD%"
CD /D "%~dp0"
:--------------------------------------
<YOUR BATCH SCRIPT HERE>
Force a batch to run as different user via RunAs command. This snippet checks the USERNAME environment variable. If it is not Administrator then it automatically restart the batch with Administrator credentials using the RunAs command. Administrator password is required.
#echo off
echo.Current User is '%USERNAME%'
rem -- Let's make sure this batch runs as Administrator --
set "RunAsUser=Administrator"
if "%USERNAME%" NEQ "%RunAsUser%" (
RUNAS /user:%RunAsUser% "cmd /c %~f0"||PAUSE
GOTO:EOF
)
rem -- your code goes below here --
echo.Hello World
ECHO.&PAUSE&GOTO:EOF

Batch file to uninstall a program

I'm trying to uninstall a program EXE via batch file and am not having any success.
The uninstall string found in the registry is as follows:
C:\PROGRA~1\Kofax\Capture\ACUnInst.exe /Workstation
C:\PROGRA~1\Kofax\Capture\UNWISE.EXE /U
C:\PROGRA~1\Kofax\Capture\INSTALL.LOG
If I run that from CMD or batch it does nothing.
If I run C:\PROGRA~1\Kofax\Capture\UNWISE.EXE /U from CMD it will open up a dialog box to point to the INSTALL.LOG file and then proceed to uninstall.
At the end, it will ask me to click finish.
I need this to be silent, can you point me in the right direction? This is on XP and 7.
Every program that properly installs itself according to Microsoft's guidelines makes a registry entry in either HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall (for machine installs) or HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall (for user profile installs). Usually, the key for the program will be its GUID, or else the name of the program. Within that key will be an entry called UninstallString. This contains the command to execute to uninstall the program.
If you already know ahead of time what you will be uninstalling, it should be easy enough to just put that in your batch file. It gets tricky when you try to automate that process though. You can use the reg command to get data from the registry, but it returns a lot of text around the actual value of a given key, making it hard to use. You may want to experiment with using VBscript or PowerShell, as they have better options for getting data from the registry into a variable.
This might help you further.....
How to Create a script via batch file that will uninstall a program if it was installed on windows 7 64-bit or 32-bit
I've had the same problem and this is what I came up with.
Before you start using this method though, you might wanna look up the name of the application on WMIC using CMD so..
First you wanna do: WMIC product > C:\Users\"currentuser"\Desktop\allapps.txt
I'd recommend to output the command to an TXT file because it's really confusing to read it in the Cmd prompt, plus is easier to find the data you are looking for.
Now what you wanna do is find the actual name of the app... If you look at the code I put in, the app name says SkypeT because skype has "™" in the end of it and the command prompt can't interpretate that as it is.
After you got the app name, just put in the find in the 4th line and substitute, a few lines which contain my examples with skype...
Also you can probably creat a variable called %APP% and not worry as much, but at it's current it works just fine...
One thing to note! with me the msi /quiet command did not work, the program would not install or uninstall so I used /passive, which lets the users see what's going on.
#Echo off
CD %cd%
:VerInstall
for /f "tokens=12,*" %%a in ('wmic product list system ^| Find /I "SkypeT"') do (
if Errorlevel = 0 (
Echo Skype is installed! )
if Errorlevel = 1 ( Echo Skype is not installed, proceding to the installation!
Ping localhost -n 7 >nul
goto :Reinstall )
)
:Status
tasklist /nh /fi "IMAGENAME eq "APP.exe" | find ":"> nul
if errorlevel = 1 goto :force
goto :Uninstall
:Force
echo We are killing the proccess... Please do not use the application during this process!
Ping localhost -n 7 > nul
taskkill /F /FI "STATUS eq RUNNING" /IM APP* /T
echo The task was killed with success! Uninstalling...
Ping localhost -n 7 > nul
:Uninstall
cls
for /f "tokens=12,*" %%a in ('wmic product list system ^| Find /I "SkypeT"') do (
set %%a=%%a: =%
msiexec.exe /x %%a /passive /norestart
)
:DoWhile
cls
Tasklist /fi "IMAGENAME eq msi*" /fi "STATUS eq RUNNING" | Find ":" >nul
if errorlevel = 1 (
echo Installation in progress
Goto :DoWhile
)
echo Skype is Uninstalled
:Reinstall
msiexec.exe /i SkypeSetup.msi /passive /norestart
:reinstallLoop
Tasklist /fi "IMAGENAME eq msi*" /fi "STATUS eq RUNNING" | Find ":" >nul
if errorlevel = 1 (
echo Installation in progress
goto :reinstallLoop
)
echo Skype is installed
:end
cls
color 0A
Echo Done!
exit
One last thing. I used this as an Invisible EXE task, so the user couldn't interact with the command prompt and eventually close the window (I know, I know, it makes the whole echoes stupid, but it was for testing purposes).for that I used BAT to EXE converter 2.3.1, you can put everything to work on the background and it will work very nicelly. if you want to show progress to users just write START Echo "info" and replace the info with whatever you want, it will open another prompt and show the info you need.
Remember, Wmic commands sometimes take up to 20 seconds to execute since it's querying the conputer's system, so it might look like it's doing nothing at first but it will run! ;)
Good luck :)
We needed a batch file to remove a program and we couldn't use programmatic access to the registry.
For us, we needed to remove a custom MSI with a unique name. This only works for installers that use msi or integrate such that their cached installer is placed in the Package_Cache folder. It also requires a unique, known name for the msi or exe. That said, it is useful for those cases.
dir/s/b/x "c:\programdata\packag~1\your-installer.msi" > removeIt.bat
set /p RemoveIt=< removeIt.bat
echo ^"%RemoveIt%^" /quiet /uninstall > removeIt.bat
removeIt.bat
This works by writing all paths for 'your-installer.msi' to the new file 'removeIt.bat'
It then assigns the first line of that bat file to the variable 'RemoveIt'
Next, it creates a new 'removeIt.bat' that contains the path/name of the .msi to remove along with the needed switches to do so.
Finally, it runs the batch file which executes the command to uninstall the msi. This could be done with an .exe as well.
You will probably want to place the 'removeIt.bat' file into a known writable location, for us that was the temp folder.

How to detect if CMD is running as Administrator/has elevated privileges?

From inside a batch file, I would like to test whether I'm running with Administrator/elevated privileges.
The username doesn't change when "Run as Administrator" is selected, so that doesn't work.
If there were a universally available command, which has no effect, but requires administrative privileges, then I could run that and check for an error code in order to test for privileges. So far, I haven't found such a command. The commands I have found seem to return a single, non-specific error code, which could indicate anything, and they're prone to failure for a variety of reasons.
I only care about Windows 7, though support of earlier operating systems would be nice.
This trick only requires one command: type net session into the command prompt.
If you are NOT an admin, you get an access is denied message.
System error 5 has occurred.
Access is denied.
If you ARE an admin, you get a different message, the most common being:
There are no entries in the list.
From MS Technet:
Used without parameters, net session displays information about all
sessions with the local computer.
ADDENDUM: For Windows 8 this will not work; see this excellent answer instead.
Found this solution here: http://www.robvanderwoude.com/clevertricks.php
AT > NUL
IF %ERRORLEVEL% EQU 0 (
ECHO you are Administrator
) ELSE (
ECHO you are NOT Administrator. Exiting...
PING 127.0.0.1 > NUL 2>&1
EXIT /B 1
)
Assuming that doesn't work and since we're talking Win7 you could use the following in Powershell if that's suitable:
$principal = new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
$principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
If not (and probably not, since you explicitly proposed batch files) then you could write the above in .NET and return an exit code from an exe based on the result for your batch file to use.
I like Rushyo's suggestion of using AT, but this is another option:
whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" && goto :isadministrator
This approach would also allow you to distinguish between a non-administrator and a non-elevated administrator if you wanted to. Non-elevated administrators still have BUILTIN\Administrators in the group list but it is not enabled.
However, this will not work on some non-English language systems. Instead, try
whoami /groups | findstr /c:" S-1-5-32-544 " | findstr /c:" Enabled group" && goto :isadministrator
(This should work on Windows 7 but I'm not sure about earlier versions.)
Pretty much what others have put before, but as a one liner that can be put at the beginning of a batch command. (Well, usually after #echo off.)
net.exe session 1>NUL 2>NUL || (Echo This script requires elevated rights. & Exit /b 1)
The easiest way to do this on Vista, Win 7 and above is enumerating token groups and looking for the current integrity level (or the administrators sid, if only group memberhip is important):
Check if we are running elevated:
whoami /groups | find "S-1-16-12288" && Echo I am running elevated, so I must be an admin anyway ;-)
Check if we belong to local administrators:
whoami /groups | find "S-1-5-32-544" && Echo I am a local admin
Check if we belong to domain admins:
whoami /groups | find "-512 " && Echo I am a domain admin
The following article lists the integrity level SIDs windows uses: http://msdn.microsoft.com/en-us/library/bb625963.aspx
Here's a slight modification of Harry's answer that focuses on elevated status; I'm using this at the start of an install.bat file:
set IS_ELEVATED=0
whoami /groups | findstr /b /c:"Mandatory Label\High Mandatory Level" | findstr /c:"Enabled group" > nul: && set IS_ELEVATED=1
if %IS_ELEVATED%==0 (
echo You must run the command prompt as administrator to install.
exit /b 1
)
This definitely worked for me and the principle seems to be sound; from MSFT's Chris Jackson:
When you are running elevated, your token contains an ACE called Mandatory Label\High Mandatory Level.
the solution:
at >nul
if %ErrorLevel% equ 0 ( echo Administrator ) else ( echo NOT Administrator )
does not work under Windows 10
for all versions of Windows can be do so:
openfiles >nul 2>&1
if %ErrorLevel% equ 0 ( echo Administrator ) else ( echo NOT Administrator )
I read many (most?) of the responses, then developed a bat file that works for me in Win 8.1. Thought I'd share it.
setlocal
set runState=user
whoami /groups | findstr /b /c:"Mandatory Label\High Mandatory Level" > nul && set runState=admin
whoami /groups | findstr /b /c:"Mandatory Label\System Mandatory Level" > nul && set runState=system
echo Running in state: "%runState%"
if not "%runState%"=="user" goto notUser
echo Do user stuff...
goto end
:notUser
if not "%runState%"=="admin" goto notAdmin
echo Do admin stuff...
goto end
:notAdmin
if not "%runState%"=="system" goto notSystem
echo Do admin stuff...
goto end
:notSystem
echo Do common stuff...
:end
Hope someone finds this useful :)
A "not-a-one-liner" version of https://stackoverflow.com/a/38856823/2193477
#echo off
net.exe session 1>NUL 2>NUL || goto :not_admin
echo SUCCESS
goto :eof
:not_admin
echo ERROR: Please run as a local administrator.
exit /b 1
I know I'm really late to this party, but here's my one liner to determine admin-hood.
It doesn't rely on error level, just on systeminfo:
for /f "tokens=1-6" %%a in ('"net user "%username%" | find /i "Local Group Memberships""') do (set admin=yes & if not "%%d" == "*Administrators" (set admin=no) & echo %admin%)
It returns either yes or no, depending on the user's admin status...
It also sets the value of the variable "admin" to equal yes or no accordingly.
Here's a simple method I've used on Windows 7 through Windows 10. Basically, I simply use the "IF EXIST" command to check for the Windows\System32\WDI\LogFiles folder. The WDI folder exists on every install of Windows from at least 7 onward, and it requires admin privileges to access. The WDI folder always has a LogFiles folder inside it. So, running "IF EXIST" on the WDI\LogFiles folder will return true if run as admin, and false if not run as admin. This can be used in a batch file to check privilege level, and branch to whichever commands you desire based on that result.
Here's a brief snippet of example code:
IF EXIST %SYSTEMROOT%\SYSTEM32\WDI\LOGFILES GOTO GOTADMIN
(Commands for running with normal privileges)
:GOTADMIN
(Commands for running with admin privileges)
Keep in mind that this method assumes the default security permissions have not been modified on the WDI folder (which is unlikely to happen in most situations, but please see caveat #2 below). Even in that case, it's simply a matter of modifying the code to check for a different common file/folder that requires admin access (System32\config\SAM may be a good alternate candidate), or you could even create your own specifically for that purpose.
There are two caveats about this method though:
Disabling UAC will likely break it through the simple fact that everything would be run as admin anyway.
Attempting to open the WDI folder in Windows Explorer and then clicking "Continue" when prompted will add permanent access rights for that user account, thus breaking my method. If this happens, it can be fixed by removing the user account from the WDI folder security permissions. If for any reason the user MUST be able to access the WDI folder with Windows Explorer, then you'd have to modify the code to check a different folder (as mentioned above, creating your own specifically for this purpose may be a good choice).
So, admittedly my method isn't perfect since it can be broken, but it's a relatively quick method that's easy to implement, is equally compatible with all versions of Windows 7, 8 and 10, and provided I stay mindful of the mentioned caveats has been 100% effective for me.
Works for Win7 Enterprise and Win10 Enterprise
#if DEFINED SESSIONNAME (
#echo.
#echo You must right click to "Run as administrator"
#echo Try again
#echo.
#pause
#goto :EOF
)
If you are running as a user with administrator rights then environment variable SessionName will NOT be defined and you still don't have administrator rights when running a batch file.
You should use "net session" command and look for an error return code of "0" to verify administrator rights.
Example;
- the first echo statement is the bell character
net session >nul 2>&1
if not %errorlevel%==0 (echo
echo You need to start over and right-click on this file,
echo then select "Run as administrator" to be successfull.
echo.&pause&exit)
Unfortunately, "S-1-5-32-544" that others have suggested is not proof of elevation.
Windows 10 and higher, a language independent approach is:
whoami /groups | find "S-1-16-12288"
this is the "High Mandatory Level", which is actually escalated.
Regular command prompt:
C:\> whoami /groups | find "S-1-16-12288"
C:\>
Administrator command prompt:
C:\> whoami /groups | find "S-1-16-12288"
Mandatory Label\High Mandatory Level Label S-1-16-12288
C:\>
To use in a .bat file:
whoami /groups | find "S-1-16-12288" && set ELEVATED=true || set ELEVATED=false
You can also use this from powershell:
function is_elevated() {
Param( [String] $ToGroup = "S-1-16-12288" )
return [bool] ( whoami /groups | select-string $ToGroup )
}
for example:
PS> cd c:/temp
PS> set-content is-elevated.ps1 "return [bool] ( whoami /groups | sls S-1-16-12288 )"
PS> ./is-elevated.ps1
False
PS> start -verb runas powershell.exe
...
PS C:\Windows\system32> cd \temp
PS C:\temp> ./is-elevated.ps1
True
Thanks Torin Darkflight,
Your method is the only one that work for me on Windows 11.
Here's an example script expanding on your post:
IF EXIST %SYSTEMROOT%\SYSTEM32\WDI\LOGFILES GOTO :Running_As_An_Admin
ECHO You are NOT an Administrator. This command requires admin rights. & Echo: & Echo Quitting......
#TIMEOUT /T 10
goto :QUIT
:Running_As_An_Admin
Echo Do Admin stuff here!!!
:QUIT

The UAC prompt shows a temporary random Program Name for msi, can the correct name be displayed?

I'm building an MSI installer for windows and sign the installer using signtool. When I run the .msi to test it, the UAC (User Account Control) prompt shows up to ask me if I want to allow the installation to proceed. That's fine, but the prompt shows a number of fields, and for the Program Name field it displays something like "403b3.msi". This is not the name of the msi I'm running.
How can I get the correct Program Name to be displayed?
Use the /d command line argument with the required program name when executing signtool to sign the msi.
It appears that the windows installer creates a temporary copy of the msi file and assigns it a generated name before running it. If you don't use /d with signtool, you get to see the temporary filename which isn't very useful for your users.
this is an applied version of #Scott-langham's comment.
this was directly from the PostBuildEvent of a visual studio installer project - VDPROJ file
set signtool="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\signtool.exe"
set timestampurl=http://timestamp.digicert.com
set certpath="$(ProjectDir)CodeSigningCert.pfx"
:: Setup in your user environment variables
:: using something with low sort order to force off screen ZZCODECERTPASSWORD
if []==[%ZZCODECERTPASSWORD%] (
echo must set code signing certificate in ZZCODECERTPASSWORD environment variable. stopping build.
exit /b 2
)
:: need the filename with extension that is being generated
FOR /f %%i IN ("$(BuiltOuputPath)") DO (
SET outputfilename=%%~nxi
)
%signtool% sign /t %timestampurl% /f %certpath% /p %CODECERTPW% /d %outputfilename% "$(BuiltOuputPath)"
IF ERRORLEVEL 1 (
echo failed to sign MSI
exit /b 3
)
%signtool% sign /t %timestampurl% /f %certpath% /p %CODECERTPW% "$(ProjectDir)$(Configuration)\Setup.exe"
IF ERRORLEVEL 1 (
echo failed to sign boostrap setup EXE
exit /b 4
)

Resources