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.
Related
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>
I have a very simple batch that backs up a set of folders. I run the batch manually without any issue, but when I schedule it to run it start to run fine but never completes. It creates the appropraite dated folder and stops before it ever copies any folders/files.
Here is the code from the .bat
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set "dt=%%a"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set datestamp=%MM%-%DD%-%YYYY%
echo datestamp: "%datestamp%"
md F:\MyArchives\%datestamp%
xcopy U:\Kristi\Project\*.* F:\MyArchives\%datestamp%\ /f/s
I have it set to run as my user name whether I am logged on or not. I have it set to run the highest privileges. It is sched for 1:45 am every day. I have checked Wake the computer to run this task. I am running Windows 7 Enterprise
When I look at the history in Scheduler, it states the following:
Task Triggered on Scheduler
Task Engine received message to start task
Tast Started
Action started
Created Task Process
Action completed
Task completed
I am at a loss. I have searched this site extensively and I have also googled it until I am blue in the face.
I have also exported the Task xml file and it is listed below:
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2014-11-04T10:50:29.1301378</Date>
<Author>AMERICAS\jfges</Author>
<Description>Backs up the Projects folder to the Passport Drive every night. This will create a dated folder that will need to be deleted eventually for space. Batch is to run every night</Description>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2014-11-04T01:45:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>AMERICAS\jfges</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>true</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>false</UseUnifiedSchedulingEngine>
<WakeToRun>true</WakeToRun>
<ExecutionTimeLimit>PT8H</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT10M</Interval>
<Count>3</Count>
</RestartOnFailure>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Users\jfges\Desktop\backup.bat</Command>
</Exec>
</Actions>
</Task>
I have tried to provide you guys with everything that I have seen anyone ask for on similar questions that I have read on here. I REALLY hope that someone is able to help me with this.
The only other thing that I can think to tell you is that I am trying to back up approx 17G of data each night. I wouldn't think that would matter since it is not even starting to copy the data over, but I thought I would mention it.
Any help would be greatly apprectiated!
There could be some reasons this doesn't work.
1. try to run the batch from cmd to see if it works (I assume you did that already)
2. xcopy to/from netword drive need mapping/privileges set - so do that
3. try adding "" around folders/path data as this might help, even with short names (even if having no space in their names)
4. you might need to use runas if no user is logged on (unsure in case of xcopy but if I remember right you'll need this)
5. Last but not least, check Event Viewer eventvwr.msc for the error. Hopefully you'll find indication of what went wrong. If not, make the task visible and try to repeat
If still struggling, "schedule the batch" to run when Windows starts (to see if Task Manager messes up something)
If all fails, please update the question accordingly (i.e. with the new data/information you collected).
I provided a path like this as the Property Value: [INSTALLFOLDER]Program Scripts\Script1.rss
where INSTALLFOLDER is C:\Program Files (x86)\ABCCompany\DEFProductInstaller\
But it somehow gets interpreted like this:
C:\Windows\SysWOW64\C:\Program Files (x86)\ABCCompany\DEFProductInstaller\Program Scripts\Script1.rss
This is the Property and the associated CustomAction
<Property Id="CreateDataSources"
Value=""rs.exe" -i "[INSTALLFOLDER]Program Scripts\Script1.rss""/>
<CustomAction Id="CreateDataSources" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
This is the log:
Property(S): SystemFolder = C:\Windows\SysWOW64\
...
MSI (s) (8C:44) [14:41:41:202]: Executing op: CustomActionSchedule(Action=CreateDataSources,ActionType=3073,Source=BinaryData,Target=CAQuietExec,CustomActionData="rs.exe" -i "[INSTALLFOLDER]Program Scripts\Script1.rss" -s http://localhost/ReportServer -v DataSourcePath="" -v DBServer="." -v InitialCatalog="MyDB" -v UserId="" -v Password="" -v IntegratedSecurity="True")
MSI (s) (8C:78) [14:41:41:211]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIFB.tmp, Entrypoint: CAQuietExec
MSI (s) (8C:90) [14:41:41:211]: Generating random cookie.
MSI (s) (8C:90) [14:41:41:213]: Created Custom Action Server with PID 16716 (0x414C).
MSI (s) (8C:C4) [14:41:41:237]: Running as a service.
MSI (s) (8C:C4) [14:41:41:238]: Hello, I'm your 32bit Impersonated custom action server.
CAQuietExec: Could not find a part of the path 'C:\Windows\SysWOW64\C:\Program Files (x86)\ABCCompany\DEFProductInstaller\Program Scripts\Script1.rss'.
CAQuietExec: Error 0x80070001: Command line returned an error.
CAQuietExec: Error 0x80070001: CAQuietExec Failed
Any idea as to what I'm doing wrong?
UPDATE Changing the <Property> value to an absolute path fixes this issue.
<Property Id="CreateDataSources"
Value='"rs.exe" -i "C:\Program Files (x86)\ABCCompany\DEFProductInstaller\Program Scripts\Script1.rss"/>
But I need it to work with INSTALLFOLDER
The log isn't failing the way I expect it to fail (perhaps there has been a recent WiX change) but in my experience the call to rs.exe has to not only be wrapped in quotes but it has to be an absolute path. "[SystemFolder]rs.exe"
BTW, it seems you are using RS.exe to deploy reporting services changes. I don't believe that file is legally redistributable. I was working for a company about 6 years ago where I wrote a table driven C#/DTF custom action that consumed the SSRS web service to publish directories, reports and datasources. I never implemented rollback though. Also this is one type where Impersonate=No may end poorly. This is due to the fact that in some situations the logged on user might have writes to the SSRS web service and the SYSTEM account may not.
You need to provide a full path to the .exe you want to run. CreateProcess does not use the system path: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx
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.
I have a post build step in an msbuild config which executes a powershell script. The powershell script works perfectly if I call it directly from Powershell but fails via msbuild.
It seems it fails after it tries to use classes from the import:
Import-Module WebAdministration
I get the error "Error : Retrieving the COM class factory for component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error : 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))"
I've tried changing the version of powershell loaded by msbuild from 64bit to 32bit but it makes no difference.
Here is the msbuild step:
<Target Name="DevPostBuild">
<PropertyGroup>
<PowerShellExe Condition=" '$(PowerShellExe)'=='' ">%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe</PowerShellExe>
<ScriptLocation Condition=" '$(ScriptLocation)'=='' ">$(ProjectDir)DevPostBuild.ps1</ScriptLocation>
</PropertyGroup>
<Message Text="$(ScriptLocation)" />
<Exec Condition="Exists($(ScriptLocation))" Command="$(PowerShellExe) -NonInteractive -executionpolicy Unrestricted -command "& { &'$(ScriptLocation)' } "" />
I'm using VS2010 on a 64bit machine.
Thanks!
Visual Studio 2010 is a 32bit process. Powershell will then run as a 32bit process. The WebAdministration module is 64bit only. Try using %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe for PowerShellExe.
Same in Visual Studio 2017, using syswow64's powershell.exe gives no difference. I had similar challenge while controlling IIS from within MSBuild XML and go same error messages about clases not registered. The Stop-WebAppPool and Stop-Website are useless therefore in MSBuild XML, as all from WebAdministration module, not mentioning Stop-IISSite from IISAdministration module.
In my case I had to utilize old good AppCmd executable from IIS. Works smooth, no issues. I also had the case when application pools and web sites are already stopped so be aware I ignore any error codes.
<Exec Command="$(WinDir)\SysWOW64\inetsrv\appcmd.exe stop apppool /apppool.name:"My Application Pool"" IgnoreExitCode="true" />
<Exec Command="$(WinDir)\SysWOW64\inetsrv\appcmd.exe stop site /site.name:"My Web Site"" IgnoreExitCode="true" />