Skip to content

Commit

Permalink
Fix issue in setting the registry for auto logon and resolving the do…
Browse files Browse the repository at this point in the history
…main name for local user accounts
  • Loading branch information
🔥Nitin Gurram🔥 committed Mar 9, 2017
1 parent 7f120e3 commit cce533c
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 153 deletions.
224 changes: 90 additions & 134 deletions Tasks/DeployVisualStudioTestAgent/SetupTestMachineForUITests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,103 +6,7 @@
}
}

function IsAnySessionActive()
{
$wtssig = @'
namespace mystruct
{
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_INFO
{
public Int32 SessionID;
[MarshalAs(UnmanagedType.LPStr)]
public String pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
}
'@

$wtsenumsig = @'
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern int WTSEnumerateSessions(
System.IntPtr hServer,
int Reserved,
int Version,
ref System.IntPtr ppSessionInfo,
ref int pCount);
'@

$wtsopensig = @'
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern IntPtr WTSOpenServer(string pServerName);
'@

$wtsSendMessagesig = @'
[DllImport("wtsapi32.dll", SetLastError = true)]
public static extern bool WTSSendMessage(
IntPtr hServer,
[MarshalAs(UnmanagedType.I4)] int SessionId,
String pTitle,
[MarshalAs(UnmanagedType.U4)] int TitleLength,
String pMessage,
[MarshalAs(UnmanagedType.U4)] int MessageLength,
[MarshalAs(UnmanagedType.U4)] int Style,
[MarshalAs(UnmanagedType.U4)] int Timeout,
[MarshalAs(UnmanagedType.U4)] out int pResponse,
bool bWait);
'@

add-type $wtssig
$wtsenum = add-type -MemberDefinition $wtsenumsig -Name PSWTSEnumerateSessions -Namespace GetLoggedOnUsers -PassThru
$wtsOpen = add-type -MemberDefinition $wtsopensig -name PSWTSOpenServer -Namespace GetLoggedOnUsers -PassThru
$wtsmessage = Add-Type -MemberDefinition $wtsSendMessagesig -name PSWTSSendMessage -Namespace GetLoggedOnUsers -PassThru

[long]$count = 0
[long]$ppSessionInfo = 0

$server = $wtsOpen::WTSOpenServer("localhost")
[long]$retval = $wtsenum::WTSEnumerateSessions($server, 0, 1, [ref]$ppSessionInfo,[ref]$count)
$datasize = [system.runtime.interopservices.marshal]::SizeOf([System.Type][mystruct.WTS_SESSION_INFO])

[bool]$activeSession = $false

if ($retval -ne 0)
{
for ($i = 0; $i -lt $count; $i++)
{
$element = [system.runtime.interopservices.marshal]::PtrToStructure($ppSessionInfo + ($datasize* $i), [System.type][mystruct.WTS_SESSION_INFO])
Write-Verbose -Message("{0} : {1}" -f $element.pWinStationName, $element.State.ToString()) -Verbose
if ($element.State.ToString().Equals("WTSActive"))
{
$activeSession = $true
}
}
}

return $activeSession
}

function ConfigurePowerOptions([System.Management.Automation.PSCredential] $MachineCredential)
{
function ConfigurePowerOptions {
Try
{
Write-Verbose -Message ("Executing command : {0} " -f "powercfg.exe /Change monitor-timeout-ac 0 ; powercfg.exe /Change monitor-timeout-dc 0") -Verbose
Expand All @@ -117,6 +21,7 @@ function ConfigurePowerOptions([System.Management.Automation.PSCredential] $Mach
}

function Set-EnableAutoLogon($TestUserDomain, $TestUserName, $TestUserPassword) {
Write-Verbose -Message "Enabling auto logon"

# If the type has already been loaded once, then it is not loaded again.
Add-Type -Language CSharp -TypeDefinition @'
Expand Down Expand Up @@ -248,18 +153,18 @@ namespace MS.VS.TestTools.Config
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateService(
IntPtr serviceHandle,
string serviceName,
IntPtr serviceHandle,
string serviceName,
string serviceDisplayName,
ServiceAccessRights desiredAccess,
int type,
int startType,
int errorControl,
ServiceAccessRights desiredAccess,
int type,
int startType,
int errorControl,
string binaryPathName,
string loadOrderGroup,
string tagId,
string dependencies,
string accountName,
string loadOrderGroup,
string tagId,
string dependencies,
string accountName,
string password);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
Expand All @@ -278,7 +183,7 @@ namespace MS.VS.TestTools.Config
);
[DllImport("advapi32.dll", SetLastError = true, EntryPoint = "ChangeServiceConfig2", CharSet = CharSet.Unicode)]
public static extern int ChangeServiceDescription(IntPtr serviceHandle, ServiceConfig2InfoLevel dwInfoLevel,
public static extern int ChangeServiceDescription(IntPtr serviceHandle, ServiceConfig2InfoLevel dwInfoLevel,
[MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION serviceDescription);
[DllImport("advapi32.dll", SetLastError = true, EntryPoint = "ChangeServiceConfig2")]
Expand Down Expand Up @@ -326,7 +231,7 @@ namespace MS.VS.TestTools.Config
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
public static extern uint LsaOpenPolicy(
ref LSA_UNICODE_STRING SystemName,
Expand Down Expand Up @@ -390,7 +295,7 @@ namespace MS.VS.TestTools.Config
[DllImportAttribute("advapi32.dll", EntryPoint = "OpenProcessToken")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(
[InAttribute()]
[InAttribute()]
System.IntPtr ProcessHandle,
uint DesiredAccess,
out System.IntPtr TokenHandle);
Expand All @@ -415,7 +320,7 @@ namespace MS.VS.TestTools.Config
public String lpPolicyPath;
public IntPtr hProfile;
}
}
}
internal class LsaPolicy : IDisposable
{
Expand Down Expand Up @@ -458,7 +363,7 @@ namespace MS.VS.TestTools.Config
};
IntPtr handle = IntPtr.Zero;
uint hr = NativeMethods.LsaOpenPolicy(ref system, ref attrib, (uint) access, out handle);
uint hr = NativeMethods.LsaOpenPolicy(ref system, ref attrib, (uint)access, out handle);
if (hr != 0 || handle == IntPtr.Zero)
{
throw new Exception("OpenLsaFailed");
Expand Down Expand Up @@ -496,7 +401,7 @@ namespace MS.VS.TestTools.Config
uint winErrorCode = NativeMethods.LsaNtStatusToWinError(result);
if (winErrorCode != 0)
{
throw new Exception("FailedLsaStoreData: "+ winErrorCode);
throw new Exception("FailedLsaStoreData: " + winErrorCode);
}
}
Expand Down Expand Up @@ -536,8 +441,10 @@ namespace MS.VS.TestTools.Config
POLICY_NOTIFICATION = 0x00001000L
}
public static class RegHelper {
public static void SetAutoLogonPassword(string password){
public static class RegHelper
{
public static void SetAutoLogonPassword(string password)
{
using (LsaPolicy lsaPolicy = new LsaPolicy(LSA_AccessPolicy.POLICY_CREATE_SECRET))
{
lsaPolicy.SetSecretData(LsaPolicy.DefaultPassword, password);
Expand All @@ -547,36 +454,85 @@ namespace MS.VS.TestTools.Config
}
'@

Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoAdminLogon -Value 1 -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name ForceAutoLogon -Value 1 -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultUserName -Value $TestUserName -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultDomainName -Value $TestUserDomain -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability' -Name ShutdownReasonOn -Value 0 -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability' -Name ShutdownReasonUI -Value 0 -ErrorAction SilentlyContinue
try {
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoAdminLogon -Value 1 -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultUserName -Value $TestUserName -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultDomainName -Value $TestUserDomain -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability' -Name ShutdownReasonOn -Value 0 -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability' -Name ShutdownReasonUI -Value 0 -ErrorAction SilentlyContinue
Remove-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoLogonCount -ErrorAction SilentlyContinue
Remove-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultPassword -ErrorAction SilentlyContinue

[MS.VS.TestTools.Config.RegHelper]::SetAutoLogonPassword($TestUserPassword)
}
catch {
Write-Warning "Unable to set auto logon: $_"
}
}

# Getting rid of old Session check. WTSEnumerateSessions spits out if there are any active sessions are available
# And we are not checking if the active session belongs to the test user. if not, then the machine should get rebooted
# Most importantly, WTSEnumerateSessions throws all sort of sessions [Remote PS, RDP, Pings from remote machines]
# For UI testing, we need active local users logged in instead of sessions check
function IsTestUserCurrentlyLoggedIn($TestUserName)
{
$computer = $env:COMPUTERNAME
try {
$quserOut = quser.exe /SERVER:$computer 2>&1
}
catch {
return $false
}

Remove-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoLogonCount -ErrorAction SilentlyContinue
Remove-ItemProperty -Path 'REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultPassword -ErrorAction SilentlyContinue
[MS.VS.TestTools.Config.RegHelper]::SetAutoLogonPassword($TestUserPassword)
if ($quserOut -match "No user exists")
{
Write-Verbose "No users logged in" -Verbose
return $false
}

$users = $quserOut -replace '\s{2,}', ',' | ConvertFrom-CSV -Header 'username', 'sessionname', 'id', 'state', 'idleTime', 'logonTime'
$users = $users[1..$users.count]

foreach ($user in $users)
{
Write-Verbose "Logged in user: $($user.username) $($user.state)" -Verbose
if(($user.username -ieq $TestUserName) -and ($user.state -ieq 'active')) {
Write-Verbose "User $TestUserName has active session" -Verbose
return $true
}
}
return $false
}

function SetupTestMachine($TestUserName, $TestUserPassword) {

# For UI Test scenarios, we need to disable the screen saver and enable auto logon
$domainUser = $TestUserName.Split("\")
$domain = "."
if($domainUser.Length -gt 1){
$domain = $domainUser[0]
$DomainUser = $TestUserName.Split("\")
$Domain = "."
if($DomainUser.Length -gt 1)
{
$Domain = $DomainUser[0]
$TestUser = $DomainUser[1]
} else {
$TestUser = $TestUserName
}

Set-EnableAutoLogon($domain, $TestUserName, $TestUserPassword)
Set-DisableScreenSaverReg
Write-Verbose -Message "Test username $TestUser" -Verbose
Write-Verbose -Message "Test user domain $Domain" -Verbose

$isSessionActive = IsAnySessionActive
if (-not ($isSessionActive))
Set-DisableScreenSaverReg | Out-Null
ConfigurePowerOptions | Out-Null

$isTestUserLogged = IsTestUserCurrentlyLoggedIn -TestUserName $TestUser
if(-not $isTestUserLogged)
{
Write-Verbose -Message("Value returned {0}" -f $isSessionActive) -Verbose
Write-Verbose "No desktop session was found active, marking the machine for reboot"
Write-Verbose "Currently test user is not logged in. Rebooting machine." -Verbose
Set-EnableAutoLogon -TestUserDomain $Domain -TestUserName $TestUser -TestUserPassword $TestUserPassword
return 3010
}

Write-Verbose "Configuration for UI testing is completed" -Verbose
return 0
}

return SetupTestMachine -TestUserName $testUserName -TestUserPassword $testUserPassword
23 changes: 21 additions & 2 deletions Tasks/DeployVisualStudioTestAgent/TestAgentHelper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,24 @@ namespace CapabilityHelpers.VisualStudio.Setup.Com
}
}



function Remove-Service([String] $ServiceName)
{
if(Get-Service $ServiceName -ErrorAction SilentlyContinue)
{
$service = (Get-WmiObject Win32_Service -filter "name='$ServiceName'")
Write-Verbose -Message("Trying to delete service {0}" -f $ServiceName) -Verbose
if($service)
{
$service.StopService()
$deleteServiceCode = $service.Delete()
if($deleteServiceCode -eq 0)
{
Write-Verbose -Message ("Deleting service {0} failed with Error code {1}" -f $ServiceName, $deleteServiceCode) -Verbose
}
}
}
else
{
Write-Verbose -Message("{0} is not present on the machine" -f $ServiceName) -Verbose
}
}
41 changes: 26 additions & 15 deletions Tasks/DeployVisualStudioTestAgent/VerifyTestAgentInstalled.ps1
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
function CheckTestAgentIsRunning([string] $ProcessName) {
$dtaProcess = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
if (-not $dtaProcess)
{
Write-Verbose "Test Agent is not running as it's not configured against Team Foundation Service" -verbose
$dtaProcess = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue

if (-not $dtaProcess)
{
Write-Verbose "DTAExecutionHost is not running" -Verbose
return
}
Write-Verbose "Test Agent is already running" -verbose
}

Write-Verbose "Test Agent is already running" -Verbose
Write-Verbose "Stopping the current DTAExecutionHost process" -Verbose
Stop-Process $dtaProcess -ErrorAction SilentlyContinue
}

function RemoveTestAgentServiceIfExists([string] $ServiceName) {
# Stop DTA Services if anything is running or registered
# This is to make sure DTAv1 doesn't cause trouble during *reboots* for DTAv2
Remove-Service -ServiceName "DTAAgentExecutionService" | Out-Null
}

function CheckTestAgentInstalled([string] $ProductVersion = "14.0") {
Write-Verbose "Query for Testplatfrom version: $ProductVersion"
Write-Verbose "Query for Testplatfrom version: $ProductVersion"

$versionInstalled = Get-TestAgentInstalledVersion -ProductVersion $ProductVersion # Get installed test agent version as per user requested version
if($versionInstalled -ne "0.0") {
Write-Verbose -Message ("Test Agent already exists") -verbose
Write-Verbose -Message ("Version: $versionInstalled") -verbose
$versionInstalled = Get-TestAgentInstalledVersion -ProductVersion $ProductVersion # Get installed test agent version as per user requested version
if($versionInstalled -ne "0.0") {
Write-Verbose -Message ("Test Agent already exists") -Verbose
Write-Verbose -Message ("Version: $versionInstalled") -Verbose

CheckTestAgentIsRunning -ProcessName "DTAExecutionHost"
} else {
Write-Verbose -Message ("Test Agent does not exists") -verbose
}
RemoveTestAgentServiceIfExists -ServiceName "DTAAgentExecutionService"
CheckTestAgentIsRunning -ProcessName "DTAExecutionHost"
} else {
Write-Verbose -Message ("Test Agent does not exists") -Verbose
}
}

CheckTestAgentInstalled -ProductVersion $ProductVersion
Loading

0 comments on commit cce533c

Please sign in to comment.