კომპიუტერული კლასის ლენარჩუნების ავტომატიზაცია Powershell-ის გამოყენებით

კომპიუტერული კლასის ლენარჩუნების ავტომატიზაცია Powershell-ის გამოყენებით

უკვე რამდენიმე წელია, უნივერსიტეტლი მხარს ვუჭერ 10 სამულაო სადგურს, რომლებიც მულაობენ Microsoft Windows 8.1-ით. ძირითადად, მხარდაჭერა მოიცავს სასწავლო პროცესისთვის საჭირო პროგრამული უზრუნველყოჀის ინსტალაციას და საერთო ლესრულების უზრუნველყოჀას.

თითოეულ სადგურს ჰყავს 2 მომხმარებელი: ადმინისტრატორი და სტუდენტი. ადმინისტრატორს აქვს სრული კონტროლი, სტუდენტს არ აქვს პროგრამული უზრუნველყოჀის ინსტალაციის ლესაძლებლობა. იმისათვის, რომ არ ლეგაწუხოთ სტუდენტური მომხმარებლის დასუჀთავება, ეს ანგარიჹი უბრალოდ მთლიანად წაილლება და ხელახლა იქმნება. ეს გულისხმობს ზოგიერთ Ⴠიზიკურ მოძრაობას, რომელიც უნდა ლესრულდეს თითოეულ სადგურზე.

წელს გადავწყვიტე მოძრაობების უმეტესობის ავტომატიზაცია PowerShell-ის გამოყენებით ActiveDirectory-ის გარეჹე და ამ პოსტლი ჹევაგროვე რამდენიმე რეცეპტი, რომლებიც ინტერნეტლი ვიპოვე.

სასწავლო

მაჹინვე ლევხვდი იმ Ⴠაქტს, რომ PS 4 იყო დაინსტალირებული სადგურებზე და ყოვლისმომცველი ინტერნეტიდან რამდენიმე მაგალითი არ მულაობდა. ამიტომ, მი჊ებული სკრიპტების გაჹვებამდე, თქვენ უნდა ლეასრულოთ რამდენიმე მოქმედება:

  1. ინსტალაცია Windows მართვის ჩარჩო 5.1
  2. დააინსტალირეთ უახლესი ვერსია PowerShell

ავტომატური მოქმედებები

  1. მომხმარებლის ანგარილის წალლა/ლექმნა
  2. ავტომატური ლესვლა მითითებული მომხმარებლისთვის
  3. გაულვით სკრიპტი, როდესაც მომხმარებელი პირველად ლედის სისტემალი

მომხმარებლის ანგარილის წალლა/ლექმნა

დავიწყე ლემოქმედებით. ამ ლემთხვევალი, თქვენ უნდა ლეასრულოთ 2 ნაბიჯი: ლექმენით მომხმარებელი (New-LocalUser) და დაამატეთ იგი ჯგუჀლი (დამატება-LocalGroupMember). მოხერხებულობისთვის, მე გავაერთიანე ეს ბრძანებები Ⴠუნქციალი:

Function New-User {
    <#
    .SYNOPSIS
        СПзЎаМОе МПвПгП пПльзПвателя
    .DESCRIPTION
        ДаММая фуМкцОя сПзЎает МПвПгП пПльзПвателя О ЎПбавляет егП в группу ППльзПвателО
    .EXAMPLE
        #New-User "Student" "Student"
    .PARAMETER Name
        ИЌя МПвПгП пПльзПвателя (ПбязательМый параЌетр)
    .PARAMETER Password
        ПарПль (ПбязательМый параЌетр)
    #>

    [CmdletBinding()]
    param (
        [PARAMETER(Mandatory=$True)][String]$Name,
        [PARAMETER(Mandatory=$True)][String]$Password
        )

    $Pwd = convertto-securestring $Password -asplaintext -force
    $GroupSID = "S-1-5-32-545"
    New-LocalUser -User $Name -AccountNeverExpires:$true -FullName $Name -Password $Pwd -PasswordNeverExpires:$true
    Add-LocalGroupMember -SID $GroupSID -Member $Name

    Write-Host "-- СПзЎаМ пПльзПватель $Name с парПлеЌ $Password" -foregroundcolor Green
}

ჯგუჀს დავამატებ SID-ით, რადგან ერთ-ერთ სტატიალი ა჊მოვაჩინე, რომ მომხმარებლების ჯგუჀის SID ყველგან ერთნაირია - S-1-5-32-545.

წალლა იყო ორგანიზებული ჹემდეგი პრინციპით: წალალეთ ყველა ანგარიჹი, რომელიც ლეიქმნა ადმინისტრატორის მიერ. ამისთვის Win32_UserProfile კლასის WMI ობიექტის გამოყენებით განვსაზ჊ვრავ ყველა მომხმარებელს, რომელიც ამჟამად არ არის აქტიური და არ არის განსაკუთრებული.

Function Remove-Users {
    <#
    .SYNOPSIS
        УЎалеМОе пПльзПвателей
    .DESCRIPTION
        ДаММая фуМкцОя уЎаляет пПльзПвателей, кПтПрые сейчас Ме актОвМы О Ме являются спецОальМыЌО
        УЎаляются в тПЌ чОсле рабПчОй каталПг О реестр пПльзПвателей
    .EXAMPLE
        #Remove-Users
    #>
    [CmdletBinding()]

    $UsersProfiles = Get-WMIObject -class Win32_UserProfile -ComputerName $env:COMPUTERNAME | Where {!($_.Loaded) -and !($_.Special)}
    foreach($Usr in $UsersProfiles) {
       	$UsrName = $Usr.LocalPath.Split("")[2]
       	Write-Host "-- УЎалеМОе пПльзПвателя $UsrName ..." -foregroundcolor Green
       	Remove-LocalUser -Name $UsrName
	Remove-WmiObject -Path $Usr.__PATH
        Write-Host "-- ППльзПватель $UsrName уЎалеМ" -foregroundcolor Green
    }
}

მითითებული მომხმარებლის ავტოლოგინი (ავტოლოგინი).

აქ ყველაჀერი ლემოიჀარგლებოდა HKEY_LOCAL_MACHINE რეესტრის ლეცვლით. ეს მოქმედებები ასევე გაერთიანდა მცირე Ⴠუნქციალი:

Function Set-AutoLogon {
    <#
    .SYNOPSIS
        ВключеМОе автПвхПЎа Ўля пПльзПвателя
    .DESCRIPTION
        ДаММая фуМкцОя включает автПвхПЎ Ўля указаММПгП пПльзПвателя
    .EXAMPLE
        #Set-AutoLogon  "Student" "Student"
    .PARAMETER Name
        ИЌя пПльзПвателя (ПбязательМый параЌетр)
    .PARAMETER Password
        ПарПль (ПбязательМый параЌетр)
    #>

    [CmdletBinding()]
    param (
        [PARAMETER(Mandatory=$True)][String]$Name,
        [PARAMETER(Mandatory=$True)][String]$Password
        )

    $PathToWinlogon = "HKLM:SoftwareMicrosoftWindows NTCurrentVersionWinlogon"
    New-ItemProperty -Path $PathToWinlogon -Name AutoAdminLogon  -Value 1 -PropertyType "String"
    New-ItemProperty -Path $PathToWinlogon -Name DefaultUserName -Value $Name -PropertyType "String"
    New-ItemProperty -Path $PathToWinlogon -Name DefaultPassword -Value $Password -PropertyType "String"
}

გაულვით სკრიპტი, როდესაც მომხმარებელი პირველად ლედის სისტემალი

ა჊მოჩნდა, რომ ყველაჀრის კონჀიგურაცია არ ლეიძლება ახალი მომხმარებლის პირველ ლესვლამდე (რაც გარკვეულწილად გასაკვირი იყო ჩემთვის). აქედან გამომდინარე, საჭირო იყო სკრიპტის გაჹვება, რომელიც ასრულებს გარკვეულ მოქმედებებს პირველი ლესვლის ჹემდეგ:

  1. პროქსის დაყენება
  2. დესკტოპზე Ⴠაილების ლექმნის პრევენცია
  3. მომხმარებლის მართვის პანელის მორგება

მე ვცადე რამდენიმე მეთოდი, მაგრამ ჹემდეგმა გამომიმულავა: დავაყენე დავალება. მაგრამ მე ვერ დავიწყე დავალება PS-ის გამოყენებით. ასე ავიჩე გრძელი გზა:

schtasks /create /tn LogonUserSettings /tr "pwsh C:ScriptsSettings.ps1" /sc onlogon /ru $env:USERDOMAIN$UserName /rp $Password /f

მაგრამ ეს არ იყო საკმარისი - Windows-მა სთხოვა ლესვლა, როგორც ჯგუჀური სამულაოს დაჹვება (SeBatchLogonRight). პასუხის ძებნა კითხვაზე, თუ როგორ უნდა გავაკეთოთ ეს, მიგვიყვანს ამას ჹედეგი:

LsaWrapper

$Source = @'
using System;
using System.Collections.Generic;
using System.Text;

namespace MyLsaWrapper
{
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Management;
    using System.Runtime.CompilerServices;
    using System.ComponentModel;

    using LSA_HANDLE = IntPtr;

    [StructLayout(LayoutKind.Sequential)]
    struct LSA_OBJECT_ATTRIBUTES
    {
        internal int Length;
        internal IntPtr RootDirectory;
        internal IntPtr ObjectName;
        internal int Attributes;
        internal IntPtr SecurityDescriptor;
        internal IntPtr SecurityQualityOfService;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct LSA_UNICODE_STRING
    {
        internal ushort Length;
        internal ushort MaximumLength;
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string Buffer;
    }
    sealed class Win32Sec
    {
        [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
        SuppressUnmanagedCodeSecurityAttribute]
        internal static extern uint LsaOpenPolicy(
        LSA_UNICODE_STRING[] SystemName,
        ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
        int AccessMask,
        out IntPtr PolicyHandle
        );

        [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
        SuppressUnmanagedCodeSecurityAttribute]
        internal static extern uint LsaAddAccountRights(
        LSA_HANDLE PolicyHandle,
        IntPtr pSID,
        LSA_UNICODE_STRING[] UserRights,
        int CountOfRights
        );

        [DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
        SuppressUnmanagedCodeSecurityAttribute]
        internal static extern int LsaLookupNames2(
        LSA_HANDLE PolicyHandle,
        uint Flags,
        uint Count,
        LSA_UNICODE_STRING[] Names,
        ref IntPtr ReferencedDomains,
        ref IntPtr Sids
        );

        [DllImport("advapi32")]
        internal static extern int LsaNtStatusToWinError(int NTSTATUS);

        [DllImport("advapi32")]
        internal static extern int LsaClose(IntPtr PolicyHandle);

        [DllImport("advapi32")]
        internal static extern int LsaFreeMemory(IntPtr Buffer);

    }
    /// <summary>
    /// This class is used to grant "Log on as a service", "Log on as a batchjob", "Log on localy" etc.
    /// to a user.
    /// </summary>
    public sealed class LsaWrapper : IDisposable
    {
        [StructLayout(LayoutKind.Sequential)]
        struct LSA_TRUST_INFORMATION
        {
            internal LSA_UNICODE_STRING Name;
            internal IntPtr Sid;
        }
        [StructLayout(LayoutKind.Sequential)]
        struct LSA_TRANSLATED_SID2
        {
            internal SidNameUse Use;
            internal IntPtr Sid;
            internal int DomainIndex;
            uint Flags;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct LSA_REFERENCED_DOMAIN_LIST
        {
            internal uint Entries;
            internal LSA_TRUST_INFORMATION Domains;
        }

        enum SidNameUse : int
        {
            User = 1,
            Group = 2,
            Domain = 3,
            Alias = 4,
            KnownGroup = 5,
            DeletedAccount = 6,
            Invalid = 7,
            Unknown = 8,
            Computer = 9
        }

        enum Access : int
        {
            POLICY_READ = 0x20006,
            POLICY_ALL_ACCESS = 0x00F0FFF,
            POLICY_EXECUTE = 0X20801,
            POLICY_WRITE = 0X207F8
        }
        const uint STATUS_ACCESS_DENIED = 0xc0000022;
        const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
        const uint STATUS_NO_MEMORY = 0xc0000017;

        IntPtr lsaHandle;

        public LsaWrapper()
            : this(null)
        { }
        // // local system if systemName is null
        public LsaWrapper(string systemName)
        {
            LSA_OBJECT_ATTRIBUTES lsaAttr;
            lsaAttr.RootDirectory = IntPtr.Zero;
            lsaAttr.ObjectName = IntPtr.Zero;
            lsaAttr.Attributes = 0;
            lsaAttr.SecurityDescriptor = IntPtr.Zero;
            lsaAttr.SecurityQualityOfService = IntPtr.Zero;
            lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
            lsaHandle = IntPtr.Zero;
            LSA_UNICODE_STRING[] system = null;
            if (systemName != null)
            {
                system = new LSA_UNICODE_STRING[1];
                system[0] = InitLsaString(systemName);
            }

            uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr,
            (int)Access.POLICY_ALL_ACCESS, out lsaHandle);
            if (ret == 0)
                return;
            if (ret == STATUS_ACCESS_DENIED)
            {
                throw new UnauthorizedAccessException();
            }
            if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
            {
                throw new OutOfMemoryException();
            }
            throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
        }

        public void AddPrivileges(string account, string privilege)
        {
            IntPtr pSid = GetSIDInformation(account);
            LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
            privileges[0] = InitLsaString(privilege);
            uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
            if (ret == 0)
                return;
            if (ret == STATUS_ACCESS_DENIED)
            {
                throw new UnauthorizedAccessException();
            }
            if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
            {
                throw new OutOfMemoryException();
            }
            throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
        }

        public void Dispose()
        {
            if (lsaHandle != IntPtr.Zero)
            {
                Win32Sec.LsaClose(lsaHandle);
                lsaHandle = IntPtr.Zero;
            }
            GC.SuppressFinalize(this);
        }
        ~LsaWrapper()
        {
            Dispose();
        }
        // helper functions

        IntPtr GetSIDInformation(string account)
        {
            LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
            LSA_TRANSLATED_SID2 lts;
            IntPtr tsids = IntPtr.Zero;
            IntPtr tdom = IntPtr.Zero;
            names[0] = InitLsaString(account);
            lts.Sid = IntPtr.Zero;
            //Console.WriteLine("String account: {0}", names[0].Length);
            int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
            if (ret != 0)
                throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret));
            lts = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(tsids,
            typeof(LSA_TRANSLATED_SID2));
            Win32Sec.LsaFreeMemory(tsids);
            Win32Sec.LsaFreeMemory(tdom);
            return lts.Sid;
        }

        static LSA_UNICODE_STRING InitLsaString(string s)
        {
            // Unicode strings max. 32KB
            if (s.Length > 0x7ffe)
                throw new ArgumentException("String too long");
            LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
            lus.Buffer = s;
            lus.Length = (ushort)(s.Length * sizeof(char));
            lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
            return lus;
        }
    }
    public class LsaWrapperCaller
    {
        public static void AddPrivileges(string account, string privilege)
        {
            using (LsaWrapper lsaWrapper = new LsaWrapper())
            {
                lsaWrapper.AddPrivileges(account, privilege);
            }
        }
    }
}
'@

Add-Type -TypeDefinition $Source
[MyLsaWrapper.LsaWrapperCaller]::AddPrivileges($Identity, "SeBatchLogonRight")

ლესვლის, როგორც ჯგუჀური სამულაოს დაჹვებამ მოგვცა ჹემდგომი ნაბიჯის გადადგმა - სკრიპტის დაწერა, რომელიც ლესრულებულია მომხმარებლის ქვემოდან.

პროქსის დაყენება

პროქსის დაყენება მარტივი ა჊მოჩნდა. სამულაო გადაწყვეტა სწრაჀად იპოვეს:

Function Set-Proxy {
    <#
    .SYNOPSIS
        УстаМПвка параЌетрПв прПксО
    .DESCRIPTION
        ДаММая фуМкцОя заЎает параЌетры прПксО Ўля пПльзПвателя
    .EXAMPLE
        #Set-Proxy a.cproxy.ru 8080
    .PARAMETER Server
        АЎрес ОлО ЎПЌеММПе ОЌя сервера (ПбязательМый параЌетр)
    .PARAMETER Port
        ППрт (ПбязательМый параЌетр)
    #>

    [CmdletBinding()]
    param (
        [PARAMETER(Mandatory=$True)][String]$Server,
        [PARAMETER(Mandatory=$True)][Int]$Port
        )

    If ((Test-NetConnection -ComputerName $Server -Port $Port).TcpTestSucceeded) {
        Set-ItemProperty -Path 'HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settings' -name ProxyServer -Value "$($Server):$($Port)"
        Set-ItemProperty -Path 'HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settings' -name ProxyEnable -Value 1
    } Else {
        Write-Error -Message "-- Invalid proxy server address or port:  $($Server):$($Port)"
    }
}

დესკტოპზე Ⴠაილების ლექმნის პრევენცია

დესკტოპზე Ⴠაილების ლექმნის აკრძალვას უჀრო მეტი დრო დასჭირდა, ვიდრე ქსელლი. საქა჊ალდეზე ნებართვების დაყენება არც ისე მარტივი ა჊მოჩნდა, როგორც *nix სისტემები. მაგრამ აქაც იყო პასუხები, რომლებიც წარმატებით მოვარგე ჩემს თავს:

Function Set-AccessRule {
    <#
    .SYNOPSIS
        УстаМПвка прав Ма папку
    .DESCRIPTION
        ДаММая фуМкцОя устаМавлОвает заЎаММые права Ма ЎОректПрОю
    .EXAMPLE
        #Set-AccessRule -Folder $env:USERPROFILEDesktop  -UserName $env:USERNAME -Rules CreateFiles,AppendData -AccessControlType Deny
    .PARAMETER Folder
        ДОректПрОя, МаЎ кПтПрПй прПОзвПЎОтся ЎействОе (ПбязательМый параЌетр)
    .PARAMETER UserName
        ИЌя учетМПй запОсО пПльзПвателя, Ўля кПгП заЎаются права ЎПступа (ПбязательМый параЌетр)
    .PARAMETER Rules
        Права ЎПступа через запятую (ПбязательМый параЌетр)
    .PARAMETER AccessControlType
        ОбязательМый параЌетр, кПтПрый ЌПжет прОМОЌать ПЎМП Оз Ўвух зМачеМОй: Allow ОлО Deny
    #>
    [CmdletBinding()]
    param (
        [PARAMETER(Mandatory=$True)][Path]$Folder,
        [PARAMETER(Mandatory=$True)][String]$UserName,
        [PARAMETER(Mandatory=$True)][String]$Rules,
        [PARAMETER(Mandatory=$True)][String]$AccessControlType
        )

    #счОтываеЌ текущОй спОсПк ACL рабПчегП стПла
    $acl = Get-Acl $Folder
    #СПзЎаеЌ переЌеММую с МужМыЌО праваЌО
    $fileSystemRights = [System.Security.AccessControl.FileSystemRights]"$Rules"
    #CПзЎаеЌ переЌеММую с указаМОеЌ пПльзПвателя, прав ЎПступа О тОпа разрешеМОя
    $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($UserName, $fileSystemRights, $AccessControlType)
    #ПереЎаеЌ переЌеММую в класс FileSystemAccessRule Ўля сПзЎаМОя Пбъекта
    $acl.SetAccessRule($AccessRule)
    #ПрОЌеМяеЌ разрешеМОя к папке
    $acl | Set-Acl $Folder
}

Set-AccessRule -Folder $env:USERPROFILEDesktop  -UserName $env:USERNAME -Rules CreateFiles,AppendData,Delete -AccessControlType Deny

FileSystemRights-ის ა჊წერა ოჀიციალურზე ონლაინი.

მომხმარებლის მართვის პანელის მორგება

ეს არ იყო საჭირო, მაგრამ მე ვჀიქრობდი, რომ კარგი იქნებოდა, მიეცეს სტუდენტებს მორგებული დაჀა ხლირად გამოყენებული პროგრამებით. პასუხი ნაპოვნია აქ.

ჩამაგრებული აპლიკაცია

function Set-PinnedApplication
{
    <#
    .SYNOPSIS
        УправлеМОе ярлыкаЌО Ма паМелО управлеМОя
    .DESCRIPTION
        ДаММая фуМкцОя ЎПбавляет ОлО уЎаляет ярлыкО Ма паМелО управлеМОя пПльзПвателя
    .EXAMPLE
        #Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFilesInternet Exploreriexplore.exe"
    .EXAMPLE
        #Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}Mozilla Firefoxfirefox.exe"
    .PARAMETER Action
        ОбязательМый параЌетр, кПтПрый ЌПжет прОМОЌать ПЎМП Оз Ўвух зМачеМОй: UnpinfromTaskbar ОлО PintoTaskbar
    .PARAMETER FilePath
        ИЌя учетМПй запОсО пПльзПвателя, Ўля кПгП заЎаются права ЎПступа (ПбязательМый параЌетр)
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)][String]$Action, 
        [Parameter(Mandatory=$True)][String]$FilePath
   	)
    if(-not (test-path $FilePath)) { 
   	throw "FilePath does not exist."  
    }
    function InvokeVerb {
   	param([string]$FilePath,$verb)
	$verb = $verb.Replace("&","")
	$path = split-path $FilePath
	$shell = new-object -com "Shell.Application" 
	$folder = $shell.Namespace($path)   
	$item = $folder.Parsename((split-path $FilePath -leaf))
	$itemVerb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb}
	if($itemVerb -eq $null){
		throw "Verb $verb not found."			
	} else {
		$itemVerb.DoIt()
	}
   }
    function GetVerb {
	param([int]$verbId)
	try {
		$t = [type]"CosmosKey.Util.MuiHelper"
	} catch {
	    $def = [Text.StringBuilder]""
	    [void]$def.AppendLine('[DllImport("user32.dll")]')
	    [void]$def.AppendLine('public static extern int LoadString(IntPtr h,uint id, System.Text.StringBuilder sb,int maxBuffer);')
	    [void]$def.AppendLine('[DllImport("kernel32.dll")]')
	    [void]$def.AppendLine('public static extern IntPtr LoadLibrary(string s);')
	    Add-Type -MemberDefinition $def.ToString() -name MuiHelper -namespace CosmosKey.Util			
	}
	if($global:CosmosKey_Utils_MuiHelper_Shell32 -eq $null){		
	    $global:CosmosKey_Utils_MuiHelper_Shell32 = [CosmosKey.Util.MuiHelper]::LoadLibrary("shell32.dll")
	}
	$maxVerbLength=255
	$verbBuilder = New-Object Text.StringBuilder "",$maxVerbLength
	[void][CosmosKey.Util.MuiHelper]::LoadString($CosmosKey_Utils_MuiHelper_Shell32,$verbId,$verbBuilder,$maxVerbLength)
	return $verbBuilder.ToString()
    }
    $verbs = @{ 
	"PintoTaskbar"=5386
	"UnpinfromTaskbar"=5387
    }
    if($verbs.$Action -eq $null){
   	Throw "Action $action not supported`nSupported actions are:`n`tPintoTaskbar`n`tUnpinfromTaskbar"
    }
    InvokeVerb -FilePath $FilePath -Verb $(GetVerb -VerbId $verbs.$action)
}

დასკვნა

სკრიპტები მულაობს, თითოეული სადგურისთვის მომსახურების დრო ლემცირდა, მიზანი მი჊წეულია. ჩემთვის, როგორც Linux-ის მომხმარებლისთვის, ვინდოუსის დაყენება არ იყო უმარტივესი თავგადასავალი, მაგრამ ეს იყო საგანმანათლებლო. მე განვავითარებ დაყენების სკრიპტს. იგეგმება დაინსტალირებული პროგრამული უზრუნველყოჀის ლემოწმების დამატება და ანტივირუსის ინსტალაცია და გაჹვება.

საბოლოო სკრიპტები მიმდინარეობს

Ადმინისტრატორის სახელით გაჹვება

Function New-User {
<#
.SYNOPSIS
СПзЎаМОе МПвПгП пПльзПвателя
.DESCRIPTION
ДаММая фуМкцОя сПзЎает МПвПгП пПльзПвателя О ЎПбавляет егП в группу ППльзПвателО
.EXAMPLE
#New-User "Student" "Student"
.PARAMETER Name
ИЌя МПвПгП пПльзПвателя (ПбязательМый параЌетр)
.PARAMETER Password
ПарПль (ПбязательМый параЌетр)
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$Pwd = convertto-securestring $Password -asplaintext -force
$GroupSID = "S-1-5-32-545"
New-LocalUser -User $Name -AccountNeverExpires:$true -FullName $Name -Password $Pwd -PasswordNeverExpires:$true
Add-LocalGroupMember -SID $GroupSID -Member $Name
Write-Host "-- СПзЎаМ пПльзПватель $Name с парПлеЌ $Password" -foregroundcolor Green
}
Function Remove-Users {
<#
.SYNOPSIS
УЎалеМОе пПльзПвателей
.DESCRIPTION
ДаММая фуМкцОя уЎаляет пПльзПвателей, кПтПрые сейчас Ме актОвМы О Ме являются спецОальМыЌО
УЎаляются в тПЌ чОсле рабПчОй каталПг О реестр пПльзПвателей
.EXAMPLE
#Remove-Users
#>
[CmdletBinding()]
$UsersProfiles = Get-WMIObject -class Win32_UserProfile -ComputerName $env:COMPUTERNAME | Where {!($_.Loaded) -and !($_.Special)}
foreach($Usr in $UsersProfiles) {
$UsrName = $Usr.LocalPath.Split("")[2]
Write-Host "-- УЎалеМОе пПльзПвателя $UsrName ..." -foregroundcolor Green
Remove-LocalUser -Name $UsrName
Remove-WmiObject -Path $Usr.__PATH
Write-Host "-- ППльзПватель $UsrName уЎалеМ" -foregroundcolor Green
}
}
Function Set-AutoLogon {
<#
.SYNOPSIS
ВключеМОе автПвхПЎа Ўля пПльзПвателя
.DESCRIPTION
ДаММая фуМкцОя включает автПвхПЎ Ўля указаММПгП пПльзПвателя
.EXAMPLE
#Set-AutoLogon  "Student" "Student"
.PARAMETER Name
ИЌя пПльзПвателя (ПбязательМый параЌетр)
.PARAMETER Password
ПарПль (ПбязательМый параЌетр)
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$PathToWinlogon = "HKLM:SoftwareMicrosoftWindows NTCurrentVersionWinlogon"
New-ItemProperty -Path $PathToWinlogon -Name AutoAdminLogon  -Value 1 -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultUserName -Value $Name -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultPassword -Value $Password -PropertyType "String"
}
$Source = @'
using System;
using System.Collections.Generic;
using System.Text;
namespace MyLsaWrapper
{
using System.Runtime.InteropServices;
using System.Security;
using System.Management;
using System.Runtime.CompilerServices;
using System.ComponentModel;
using LSA_HANDLE = IntPtr;
[StructLayout(LayoutKind.Sequential)]
struct LSA_OBJECT_ATTRIBUTES
{
internal int Length;
internal IntPtr RootDirectory;
internal IntPtr ObjectName;
internal int Attributes;
internal IntPtr SecurityDescriptor;
internal IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct LSA_UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
internal string Buffer;
}
sealed class Win32Sec
{
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaOpenPolicy(
LSA_UNICODE_STRING[] SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
int AccessMask,
out IntPtr PolicyHandle
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaAddAccountRights(
LSA_HANDLE PolicyHandle,
IntPtr pSID,
LSA_UNICODE_STRING[] UserRights,
int CountOfRights
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern int LsaLookupNames2(
LSA_HANDLE PolicyHandle,
uint Flags,
uint Count,
LSA_UNICODE_STRING[] Names,
ref IntPtr ReferencedDomains,
ref IntPtr Sids
);
[DllImport("advapi32")]
internal static extern int LsaNtStatusToWinError(int NTSTATUS);
[DllImport("advapi32")]
internal static extern int LsaClose(IntPtr PolicyHandle);
[DllImport("advapi32")]
internal static extern int LsaFreeMemory(IntPtr Buffer);
}
/// <summary>
/// This class is used to grant "Log on as a service", "Log on as a batchjob", "Log on localy" etc.
/// to a user.
/// </summary>
public sealed class LsaWrapper : IDisposable
{
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRUST_INFORMATION
{
internal LSA_UNICODE_STRING Name;
internal IntPtr Sid;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRANSLATED_SID2
{
internal SidNameUse Use;
internal IntPtr Sid;
internal int DomainIndex;
uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_REFERENCED_DOMAIN_LIST
{
internal uint Entries;
internal LSA_TRUST_INFORMATION Domains;
}
enum SidNameUse : int
{
User = 1,
Group = 2,
Domain = 3,
Alias = 4,
KnownGroup = 5,
DeletedAccount = 6,
Invalid = 7,
Unknown = 8,
Computer = 9
}
enum Access : int
{
POLICY_READ = 0x20006,
POLICY_ALL_ACCESS = 0x00F0FFF,
POLICY_EXECUTE = 0X20801,
POLICY_WRITE = 0X207F8
}
const uint STATUS_ACCESS_DENIED = 0xc0000022;
const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
const uint STATUS_NO_MEMORY = 0xc0000017;
IntPtr lsaHandle;
public LsaWrapper()
: this(null)
{ }
// // local system if systemName is null
public LsaWrapper(string systemName)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
lsaHandle = IntPtr.Zero;
LSA_UNICODE_STRING[] system = null;
if (systemName != null)
{
system = new LSA_UNICODE_STRING[1];
system[0] = InitLsaString(systemName);
}
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr,
(int)Access.POLICY_ALL_ACCESS, out lsaHandle);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void AddPrivileges(string account, string privilege)
{
IntPtr pSid = GetSIDInformation(account);
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void Dispose()
{
if (lsaHandle != IntPtr.Zero)
{
Win32Sec.LsaClose(lsaHandle);
lsaHandle = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~LsaWrapper()
{
Dispose();
}
// helper functions
IntPtr GetSIDInformation(string account)
{
LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
LSA_TRANSLATED_SID2 lts;
IntPtr tsids = IntPtr.Zero;
IntPtr tdom = IntPtr.Zero;
names[0] = InitLsaString(account);
lts.Sid = IntPtr.Zero;
//Console.WriteLine("String account: {0}", names[0].Length);
int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
if (ret != 0)
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret));
lts = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(tsids,
typeof(LSA_TRANSLATED_SID2));
Win32Sec.LsaFreeMemory(tsids);
Win32Sec.LsaFreeMemory(tdom);
return lts.Sid;
}
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort)(s.Length * sizeof(char));
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
return lus;
}
}
public class LsaWrapperCaller
{
public static void AddPrivileges(string account, string privilege)
{
using (LsaWrapper lsaWrapper = new LsaWrapper())
{
lsaWrapper.AddPrivileges(account, privilege);
}
}
}
}
'@
Add-Type -TypeDefinition $Source | Out-Null
# -------------------------
# ПересПзЎаМОе пПльзПвателя
# -------------------------
$UserName    = "Student"
$Password    = "Student"
Remove-Users | Out-Null
New-User $UserName $Password | Out-Null
Set-AutoLogon $UserName $Password | Out-Null
[MyLsaWrapper.LsaWrapperCaller]::AddPrivileges($UserName, "SeBatchLogonRight") | Out-Null
write-host "-- разрешеМ вхПЎ в качестве пакетМПгП заЎаМОя Ўля пПльзПвателя $UserName" -foregroundcolor Green
schtasks /create /tn LogonUserSettings /tr "pwsh C:ScriptsSetupUser.ps1" /sc onlogon /ru $env:USERDOMAIN$UserName /rp $Password /f

გალვებულია სტუდენტური მომხმარებლის ქველ

Function Set-Proxy {
<#
.SYNOPSIS
УстаМПвка параЌетрПв прПксО
.DESCRIPTION
ДаММая фуМкцОя заЎает параЌетры прПксО Ўля пПльзПвателя
.EXAMPLE
#Set-Proxy a.cproxy.ru 8080
.PARAMETER Server
АЎрес ОлО ЎПЌеММПе ОЌя сервера (ПбязательМый параЌетр)
.PARAMETER Port
ППрт (ПбязательМый параЌетр)
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Server,
[PARAMETER(Mandatory=$True)][Int]$Port
)
If ((Test-NetConnection -ComputerName $Server -Port $Port).TcpTestSucceeded) {
Set-ItemProperty -Path 'HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settings' -name ProxyServer -Value "$($Server):$($Port)"
Set-ItemProperty -Path 'HKCU:SoftwareMicrosoftWindowsCurrentVersionInternet Settings' -name ProxyEnable -Value 1
} Else {
Write-Error -Message "-- Invalid proxy server address or port:  $($Server):$($Port)"
}
}
Function Set-AccessRule {
<#
.SYNOPSIS
УстаМПвка правк Ма папку
.DESCRIPTION
ДаММая фуМкцОя устаМавлОвает заЎаММые права Ма ЎОрректПрОю
.EXAMPLE
#Set-AccessRule -Folder $env:USERPROFILEDesktop  -UserName $env:USERNAME -Rules CreateFiles,AppendData -AccessControlType Deny
.PARAMETER Folder
ДОрректПрОя, МаЎ кПтПрПй прПОзвПЎОтся ЎействОе (ПбязательМый параЌетр)
.PARAMETER UserName
ИЌя учетМПй запОсО пПльзПвателя, Ўля кПгП заЎаются права ЎПступа (ПбязательМый параЌетр)
.PARAMETER Rules
Права ЎПступа через запятую(ПбязательМый параЌетр)
.PARAMETER AccessControlType
ОбязательМый параЌетр, кПтПрый ЌПжет прОМЌать ПЎМП Оз Ўвух зМачеМОй: Allow ОлО Deny
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Folder,
[PARAMETER(Mandatory=$True)][String]$UserName,
[PARAMETER(Mandatory=$True)][String]$Rules,
[PARAMETER(Mandatory=$True)][String]$AccessControlType
)
#счОтываеЌ текущОй спОсПк ACL рабПчегП стПла
$acl = Get-Acl $Folder
#СПзЎаеЌ переЌеММю с МужМыЌО праваЌО
$fileSystemRights = [System.Security.AccessControl.FileSystemRights]"$Rules"
#CПзЎаеЌ переЌеММую с указаМОеЌ пПльзПвателя, прав ЎПступа О тОпа разрешеМОя
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($UserName, $fileSystemRights, $AccessControlType)
#ПереЎаеЌ переЌеММую в класс FileSystemAccessRule Ўля сПзЎаМОя Пбъекта
$acl.SetAccessRule($AccessRule)
#ПрОЌеМяеЌ разрешеМОя к папке
$acl | Set-Acl $Folder
}
function Set-PinnedApplication
{
<#
.SYNOPSIS
УправлеМОе ярлыкаЌО Ма паМелО управлеМОя
.DESCRIPTION
ДаММая фуМкцОя ЎПбавляет ОлО уЎаляет ярлыкО Ма паМелО управлеМОя пПльзПвателя
.EXAMPLE
#Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFilesInternet Exploreriexplore.exe"
.EXAMPLE
#Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}Mozilla Firefoxfirefox.exe"
.PARAMETER Action
ОбязательМый параЌетр, кПтПрый ЌПжет прОМОЌать ПЎМП Оз Ўвух зМачеМОй: UnpinfromTaskbar ОлО PintoTaskbar
.PARAMETER FilePath
ИЌя учетМПй запОсО пПльзПвателя, Ўля кПгП заЎаются права ЎПступа (ПбязательМый параЌетр)
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)][String]$Action, 
[Parameter(Mandatory=$True)][String]$FilePath
)
if(-not (test-path $FilePath)) { 
throw "FilePath does not exist."  
}
function InvokeVerb {
param([string]$FilePath,$verb)
$verb = $verb.Replace("&","")
$path = split-path $FilePath
$shell = new-object -com "Shell.Application" 
$folder = $shell.Namespace($path)   
$item = $folder.Parsename((split-path $FilePath -leaf))
$itemVerb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb}
if($itemVerb -eq $null){
throw "Verb $verb not found."           
} else {
$itemVerb.DoIt()
}
}
function GetVerb {
param([int]$verbId)
try {
$t = [type]"CosmosKey.Util.MuiHelper"
} catch {
$def = [Text.StringBuilder]""
[void]$def.AppendLine('[DllImport("user32.dll")]')
[void]$def.AppendLine('public static extern int LoadString(IntPtr h,uint id, System.Text.StringBuilder sb,int maxBuffer);')
[void]$def.AppendLine('[DllImport("kernel32.dll")]')
[void]$def.AppendLine('public static extern IntPtr LoadLibrary(string s);')
Add-Type -MemberDefinition $def.ToString() -name MuiHelper -namespace CosmosKey.Util            
}
if($global:CosmosKey_Utils_MuiHelper_Shell32 -eq $null){        
$global:CosmosKey_Utils_MuiHelper_Shell32 = [CosmosKey.Util.MuiHelper]::LoadLibrary("shell32.dll")
}
$maxVerbLength=255
$verbBuilder = New-Object Text.StringBuilder "",$maxVerbLength
[void][CosmosKey.Util.MuiHelper]::LoadString($CosmosKey_Utils_MuiHelper_Shell32,$verbId,$verbBuilder,$maxVerbLength)
return $verbBuilder.ToString()
}
$verbs = @{ 
"PintoTaskbar"=5386
"UnpinfromTaskbar"=5387
}
if($verbs.$Action -eq $null){
Throw "Action $action not supported`nSupported actions are:`n`tPintoTaskbar`n`tUnpinfromTaskbar"
}
InvokeVerb -FilePath $FilePath -Verb $(GetVerb -VerbId $verbs.$action)
}
Set-Proxy cproxy.udsu.ru 8080
Set-AccessRule -Folder $env:USERPROFILEDesktop  -UserName $env:USERNAME -Rules "CreateFiles,AppendData,Delete" -AccessControlType Deny
Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFilesInternet Exploreriexplore.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}Mozilla Firefoxfirefox.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramDataMicrosoftWindowsStart MenuProgramsMicrosoft Office 2013Excel 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramDataMicrosoftWindowsStart MenuProgramsMicrosoft Office 2013Word 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramDataMicrosoftWindowsStart MenuProgramsMicrosoft Office 2013PowerPoint 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramDataMicrosoftWindowsStart MenuProgramsАСКОНКОМПАС-3D V16КОМПАС-3D V16.lnk"
# УЎалеМОе заЎачО, пПсле ее выпПлМеМОя
Unregister-ScheduledTask -TaskName UdSUSettingStudent -Confirm:$false

წყარო: www.habr.com

ახალი კომენტარის დამატება