Powershellコンピュータークラスサービスの自動化





ここ数年、私は大学でMicrosoft Windows8.1を実行している10台のワークステーションをサポートするために働いています。基本的に、サポートは、教育プロセスに必要なソフトウェアのインストールと全体的なパフォーマンスの確保で構成されます。



各ステーションには、管理者と学生の2人のユーザーがいます。管理者は完全に制御でき、学生はソフトウェアをインストールすることができません。Studentユーザーのクリーニングに煩わ​​されないように、このアカウントは完全に削除され、新しく作成されます。これには、各ステーションで実行する必要のある体の動きが伴います。



今年、私はActive DirectoryなしでPowerShellを使用して体の動きのほとんどを自動化することに決め、この投稿でネット上で見つけたいくつかのレシピを収集しました。



トレーニング



すぐに、PS 4がステーションにインストールされていて、すべてを知っているインターネットからのいくつかの例が機能しなかったという事実に出会いました。したがって、結果のスクリプトを実行する前に、いくつかのアクションを実行する必要があります。



  1. Windows Management Framework5.1をインストールします
  2. PowerShellの最新バージョンをインストールします


自動化されたアクション



  1. ユーザーアカウントの削除/作成
  2. 特定のユーザーの自動ログイン
  3. ユーザーが最初にログインしたときにスクリプトを実行する


ユーザーアカウントの削除/作成



彼は作成することから始めました。この場合、2つのアクションを実行する必要があります。ユーザーを作成し(New-LocalUser)、それをグループに追加しますAdd-LocalGroupMember)便宜上、これらのコマンドを1つの関数に組み合わせました。



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でグループに追加します。これは、ある記事で、Usersグループの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:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
    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:\Scripts\Settings.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:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "$($Server):$($Port)"
        Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet 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:USERPROFILE\Desktop\  -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:USERPROFILE\Desktop\  -UserName $env:USERNAME -Rules CreateFiles,AppendData,Delete -AccessControlType Deny


公式ウェブサイトのFileSystemRightsの説明



ユーザーコントロールパネルのカスタマイズ



これはオプションでしたが、一般的に使用されるプログラムを備えたカスタムダッシュボードを学生に提供するのはクールだと思いました。答えはここで見つかりまし



PinnedApplication
function Set-PinnedApplication
{
    <#
    .SYNOPSIS
            
    .DESCRIPTION
                 
    .EXAMPLE
        #Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFiles\Internet Explorer\iexplore.exe"
    .EXAMPLE
        #Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.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ユーザーとして、Windowsのセットアップは最も簡単な冒険ではなく、教育的なものであることがわかりました。セットアップスクリプトを開発します。インストールされているソフトウェアとインストールのチェックを追加して、アンチウイルスを起動する計画があります。



作業中の最終スクリプト



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:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
    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:\Scripts\SetupUser.ps1" /sc onlogon /ru $env:USERDOMAIN\$UserName /rp $Password /f


- Student



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:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "$($Server):$($Port)"
		Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet 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:USERPROFILE\Desktop\  -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:ProgramFiles\Internet Explorer\iexplore.exe"
    .EXAMPLE
        #Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.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:USERPROFILE\Desktop\  -UserName $env:USERNAME -Rules "CreateFiles,AppendData,Delete" -AccessControlType Deny

Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFiles\Internet Explorer\iexplore.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Excel 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Word 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\PowerPoint 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\\-3D V16\-3D V16.lnk"

#  ,   
Unregister-ScheduledTask -TaskName UdSUSettingStudent -Confirm:$false





All Articles