We developed an ActiveX form control to be installed in IE8+.
This control checks for a registry key then download and install a small setup if needed.
For administrator everything work as expected on Windows 7 and 8 with any IE version 8+.
With non-admin users, the control runs (it must be installed by admin, but it's ok), it downloads the executable client_setup.exe in path C:\users\user\AppData\Local\Temp\Low\ but when it tries to run executable (shellexec or createprocess produce same result) an administrative account is required and UAC elevation prompt appears.
If non-admin user download and install same setup, no administration privilege is required (we declared this in exe manifest). This setup is entirely installed in user profile and HKCU registry.
I understand that ActiveX control runs with low privileges like IE process. But why elevation is required in this case? Our setup do not requires privileges.
I tried to add ActiveX control in Low Rights elevation policy exceptions here
HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft\Internet Explorer\Low Rights\ElevationPolicy
but still UAC prompt appears.
I want to allow to run this setup for all users. We can run once as administrator a script to give permission for the whole system. Can someone help with this task?
TEST 1
As non-admin user, I tried to manually install the .exe downloaded by the ActiveX and I get a system error, cannot write to temp directory. If I download the same exe file with Internet Explorer I can install this with no problems.
I checked with ICACLS and on exe downloaded by ActiveX control there is a Mandatory Label\Low Mandatory Level:(I)(NW)
TEST 2
Site was added to trusted sites as Taxilian suggested. As non-admin user, ActiveX now saves .exe setup to C:\users\user\AppData\Local\Temp (no Low), .exe hasn't low level label anymore. But still, CreateProcess raises UAC prompt and fails.
This is my CreateProcess code. It's Delphi code but it should be readable.
function RunProcess(FileName: string; ShowCmd: DWORD; wait: Boolean; ProcID: PDWORD): Longword;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
StartupInfo.wShowWindow := ShowCmd;
if not CreateProcess(nil,
#Filename[1],
nil,
nil,
False,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo)
then
Result := WAIT_FAILED
else
begin
if wait = FALSE then
begin
if ProcID <> nil then
ProcID^ := ProcessInfo.dwProcessId;
result := WAIT_FAILED;
exit;
end;
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
GetExitCodeProcess(ProcessInfo.hProcess, Result);
end;
if ProcessInfo.hProcess <> 0 then
CloseHandle(ProcessInfo.hProcess);
if ProcessInfo.hThread <> 0 then
CloseHandle(ProcessInfo.hThread);
end;
This is .exe manifest. It is a simple setup that copies some files to user profile and add a registry key in HKCU.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="JR.Inno.Setup" processorArchitecture="x86" version="1.0.0.0" type="win32" />
<description>Inno Setup</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
</application>
</compatibility>
</assembly>
Windows UAC uses some heuristics to detect installers.
From http://blogs.msdn.com/b/uac/archive/2006/01/13/512776.aspx :
The O/S makes a decision that the application looks like an installer
or updater and will automatically invoke elevation to run the program
with administrative permissions/privileges when a user runs it. This
decision is based on a heuristic. Here are some of the heuristic
detection points, although this list is not exhaustive:
File name detection – looks for the words “setup”, “update”,
“install” in the filename
Our setup name is client_setup.exe, so UAC is triggered even if it's not needed, asking for administration privileges, totally ignoring exe manifest. Let's call this a feature.
It was enough to rename client_setup.exe to client.exe, then run it. No UAC prompt appears and setup completes successfully.
This looks like a recent change from Microsoft. As recent as 4 months ago, our setup was launched without errors.
It isn't the activex control that has to be registered to run as a medium integrity process, it's the EXE that you are launching from said activex control.
Related
The situation/context/intent
I try to run a task (on windows 10) which activate or deactivate auto logon depending on the NetConnection name (to see if I am home). The script works and is executed, but I guess the task is too late, since auto logon use the pre-existing value over the one set by the script. Or, is it that the script is delayed by the Wi-Fi, which maybe still launching, allowing auto logon to do its things or something like that?
What I tried
Well first, I look on the internet, but all I could find was how to activate auto logon and nothing near what I try to do.
Then, on stackoverflow, I did found something call gina.dll. Turn out, it has bean replace by credential provider. Which look like an aventure better avoided and, I think, it is just the interface to logon anyway.
Then I tried to use the event, kernel-Boot id 30, which, should be monitoring the start up process. "Maybe this would be earlier than the default startup", I thought. But, I observe the same result as with "on startup". (Maybe it is the same thing as "on startup".)
The script (PowerShell)
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
if((Get-NetConnectionProfile | select -ExpandProperty Name) -ceq "The connection name"){
Set-ItemProperty $RegPath "AutoAdminLogon" -Value "1" -type String
}else{
Set-ItemProperty $RegPath "AutoAdminLogon" -Value "0" -type String
}
The exported task
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2022-01-02T17:37:14.7356723</Date>
<Author>LAPTOP\admin</Author>
<Description>Connexion automatique à admin</Description>
<URI>\Tâche personalisé\Connexion automatique</URI>
</RegistrationInfo>
<Triggers>
<BootTrigger>
<Enabled>true</Enabled>
</BootTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>I probably do not want that out there</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1M</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>PowerShell</Command>
<Arguments>C:\ScriptPersonnalise\ConnexionAutomatique.ps1</Arguments>
</Exec>
</Actions>
</Task>
Sorry David, my mistake, I didn't get your point. You were perfectly right with your analyse.
But You won't be able to do what you want by using scheduled tasks. Even when configured at boot time, the scheduled task/script will be execute after the processing of AutoAdminLogon by the system.
For your script to be executed before the system gets there, you need to use Group Policies. Two thing to do:
Start Group Policy Console by running gpedit.msc
Add you script to the computer startup scripts
Computer Configuration\Windows Settings\Scripts (Startup/Shutdown)
Startup (add your powershell script here)
Enable the synchronous processing of startup scripts
Computer Configuration\Administrative Templates\System\Logon ->
Always wait for the network at computer startup and logon: Enabled
Et voilà!
consider using a tool from SysInternals called AutoLogon that can help you achieve your goal in a slightly more secure way as it allows you to use an encrypted password.
Starting with the obvious comment of this being insecure, you could likely default autologon to a second account with a custom shell. The custom shell would wait for network, update autologon appropriately, the logoff.
As far as you define the environment of Windows 10 and knowledge of plain tex username/password you can implement your own Credential Provider.
Your provider will be called for ICredentialProvider::SetUsageScenario and ICredentialProvider::GetCredentialCount.
This time you can take a decision to do autologon or not.
As a result of your evaluation you may return TRUE at pbAutoLogonWithDefault parameter.
Later your provider will be called for ICredentialProviderCredential::GetSerialization where you can serialize username and password.
Using Wix installer (win 8), I have a custom action that runs the application after successful installation, using Wix:
<CustomAction Id='LaunchFile'
Directory='TARGETDIR'
Impersonate="no"
Execute="immediate"
ExeCommand='[SystemFolder]cmd.exe start CMD /c ""[TARGETDIR]ManagerAndControl.exe""'
Return="asyncNoWait" />
This works great, but for some reason, the CMD window remains open, and when the application is closed it is closed too.
I couldn't find anything similar in google, anyone encounterd a similar problem?
Thank you
EDIT:
I'm trying, as #Rolo suggested, the QtExecCmdLine:
<Property Id="QtExecCmdLine" Value='C:\Users\User\Desktop\tests.exe'/>
<CustomAction Id="QtExecExample" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="immediate" Return="check"/>
And also:
<Publish Event='DoAction' Value='QtExecExample'>(NOT Installed) AND (LAUNCHPRODUCT = 1)
</Publish>
But nothing happens, and the log says:
Action start 11:02:49: QtExecExample.
MSI (c) (E0:20) [11:02:49:911]: Invoking remote custom action. DLL: C:\Users\User\AppData\Local\Temp\MSIAD42.tmp, Entrypoint: CAQuietExec
MSI (c) (E0:EC) [11:02:49:913]: Cloaking enabled.
MSI (c) (E0:EC) [11:02:49:913]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (E0:EC) [11:02:49:913]: Connected to service for CA interface.
MSI (c) (E0!00) [11:02:49:944]: PROPERTY CHANGE: Deleting QtExecCmdLine property. Its current value is 'C:\Users\User\Desktop\tests.exe'.
Action ended 11:02:49: QtExecExample. Return value 3.
DEBUG: Error 2896: Executing action QtExecExample failed.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2896. The arguments are: QtExecExample, ,
Action ended 11:02:49: FinishedForm. Return value 3.
Action ended 11:02:49: INSTALL. Return value 1.
Filling lost here
Use the "Quiet Execution Custom Action" instead.
http://wixtoolset.org/documentation/manual/v3/customactions/qtexec.html
Update:
I'll have to update my answer. You should use the WixShellExec custom action. It works pretty similar to Quiet Execution CA, but it will allow you to launch the app without waiting for it to close.
However it can only be used as an immediate custom action.
There is a full example of the implementation you need here:
http://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/run_program_after_install.html
http://wixtoolset.org/documentation/manual/v3/customactions/shellexec.html
Edit your execommand like this
> ExeCommand='[SystemFolder]cmd.exe start CMD /c ""[TARGETDIR]ManagerAndControl.exe"" & exit'
EDIT
> ExeCommand='"[TARGETDIR]ManagerAndControl.exe"'
I've just tried this for me and it's worked after I recreated your original problem. However, where you have [TARGETDIR] I use [INSTALLDIR] - I assumed that this was referencing your install directory. You need to be aware of your use of inverted commas.
Thanks for your help, finally I solved it:
<Property Id="WixShellExecTarget" Value='[TARGETDIR]ManagerAndControl.exe' />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<!-- UI code here -->
<Publish Event='DoAction' Value='LaunchApplication'>(NOT Installed) AND (LAUNCHPRODUCT = 1)</Publish>
Wix 3.6. I'm trying to run a bundle :
<Bundle Name="Setup" Version="1.0.0.0" Manufacturer="Bentley" UpgradeCode="37d68094-0b98-4b16-bfbe-7f0d3015064a">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage SourceFile="path/to/MyMsiFileWhichIsFine.msi" Cache="yes" Compressed="no" InstallCondition="1"/>
</Chain>
Result from execution :
0x800b0109 A certification chain processed, but terminated in a root certificate which is not trusted by the trust provider.
The log file says :
Detected partially cached package: MyMsiFileWhichIsFine.msi, invalid payload: MyMsiFileWhichIsFine.msi, reason: 0x80070570
I signed this msi. The bootstrapper was also signed using (cf this link):
insignia -ib Setup.exe -o engine.exe
signtool engine.exe (extra parameters excluded for simplicity)
insignia -ab engine.exe Setup.exe -o Setup.exe
signtool Setup.exe
One possibility is the msi was created externally rather than using Heat.exe that comes as part of WIX. I've had similar issues when I was trying to work with VB6 files, and had to add in flags to ignore those checks. But in your case, Bootstrapper might not be able to interpret the msi correctly. How did the msi get created? Did you use Heat? Can you post the Heat lines if so?
I found a solution ! I just skip the signing verification like this :
<ExePackage SourceFile="MyPath\MyFileToLaunch.exe" Compressed="no" SuppressSignatureVerification="yes"/>
I'm working on moving a set of installers from VS2010 to WIX and have encountered an error with our NT Service applications.
After creating and installing the NT Service using the WIX installer, the service is not looking for the app.config named as you would expect (ApplicationName.exe.config). Our application name is akin to XXX.YYYYYYYY and when injecting the debugger into the service during start up, i can see that it is looking for XXX.config instead of XXX.YYYYYYY.exe.config.
I've tried running the application via the console and when I do, it looks for the correct app.config file name. Using the VS2010 installer also has the service looking for the correct app.config file name.
Is there some setting in wxi3.8 that I am missing, or putting the incorrect value into, that would cause this? Here is the segment of the wxs that controls the service:
<Component Id="Service" Guid="DCE18608-D25F-4DC0-9E1B-C2E3575D0BFE">
<File Id="ServiceComponentMain" Name="$(var.XXX.YYYYYYY.TargetName)" Source="$(var.HHG.SpecOrderLoadSync.TargetPath)"
DiskId="1" Vital="yes" KeyPath="yes"/>
<ServiceInstall Id="Service" Name="$(var.XXX.YYYYYYY.TargetName)" Type="ownProcess" DisplayName="$(var.XXX.YYYYYYY.TargetName)"
Description="$(var.XXX.YYYYYYY.TargetName)" Start="auto" Account="NT AUTHORITY\LocalService" ErrorControl="normal">
<util:PermissionEx User="Everyone" ServicePauseContinue="yes" ServiceQueryStatus="yes"
ServiceStart="no" ServiceStop="yes" ServiceUserDefinedControl="yes"/>
</ServiceInstall>
<ServiceControl Id="Service" Stop="both" Remove="both" Name="$(var.XXX.YYYYYYY.TargetName)" Wait="no"/>
Finally figured this out after digging around the registery. It appears that with my current wsx file it isn't registering the full path to the executable including ".exe" at the end. This is what is causing the config file name to be confused. Why in the world this makes a difference is beyond me, but just another thing to annoy me about windows i guess...
To fix, changing the Name on the File element in the segment above to be $(var.XXX.YYYYYYY.TargetName).exe instead of just $(var.XXX.YYYYYYY.TargetName) seems to work.
I am creating Datadriven Unit(MS Unit Test) Test using Excel(*.xlsx) file as data source.
it is erroring out with the following error
Result Message: The unit test adapter failed to connect to the data
source or to read the data. For more information on troubleshooting
this error, see "Troubleshooting Data-Driven Unit Tests"
(http://go.microsoft.com/fwlink/?LinkId=62412) in the MSDN Library.
Error details: ERROR [IM014] [Microsoft][ODBC Driver Manager] The
specified DSN contains an architecture mismatch between the Driver and
Application
I have set the Copy to Output directory : always for the DateRangeTest.xlsx
I also tried defaultdir=.\;, defaultdir=.;, and defaultdir=c:\projectName\bin\debug\;
Here is the section from app.config
<configSections>
<section
name="microsoft.visualstudio.testtools"
type="Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection, Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</configSections>
<connectionStrings>
<add name="DateRangeConstr"
connectionString="Dsn=Excel Files;dbq=DateRangeTest.xlsx;defaultdir=.\; driverid=790;maxbuffersize=2048;pagetimeout=5"
providerName="System.Data.Odbc" />
</connectionStrings>
<microsoft.visualstudio.testtools>
<dataSources>
<add name="DateRangeTestDataSource"
connectionString="DateRangeConstr"
dataTableName="Sheet1$"
dataAccessMethod="Sequential"/>
</dataSources>
</microsoft.visualstudio.testtools>
There are (2) options here - you can either remove the DSN requirement or install the opposite Excel/Access runtime bitness of the Office product you have installed.
Option 1 - remove DSN from Connection String
Change from this:
<add name="DateRangeConstr"
connectionString="Dsn=Excel Files;dbq=DateRangeTest.xlsx;defaultdir=.\; driverid=790;maxbuffersize=2048;pagetimeout=5"
providerName="System.Data.Odbc" />
To this:
<add name="DateRangeConstr"
connectionString="dbq=DateRangeTest.xlsx;defaultdir=.\; driverid=790;maxbuffersize=2048;pagetimeout=5"
providerName="System.Data.Odbc" />
Option 2 - Install ODBC Drivers for Opposite Bitness
For Office x64, install Microsoft Access Database Engine 2010 Redistributable for x86 (AccessDatabaseEngine.exe)
For Office x64, install Microsoft Access Database Engine 2010 Redistributable for x64 (AccessDatabaseEngine_x64.exe).
This fix should be the same whether you have Office 2010 or Office 2013.
To test this change - you should be able to configure the Excel Files DSN for both x86 and x64 once installed.
32-bit ODBC: %WINDIR%\SysWOW64\odbcad32.exe
64-bit ODBC: %WINDIR%\System32\odbcad32.exe
Click on "Excel Files" and then click "Configure" and you should see a dialog. If an error occurs when you click "Configure" - you don't have the proper office driver installed for that bitness.
We need not to install anything to our system to run the external excel data driven unit tests.
We need to simply run the Data Source Wizard present under Visual Studio Data Source Explorer.
Watch this video. This Tutorial tells how to run Data Driven (Parameters) unit tests using Visual Studio Testing Tools.