[Системное администрирование, PowerShell] Автоматизация обслуживания компьютерного класса на Powershell
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Вот уже несколько лет занимаюсь в университете поддержкой 10 рабочих станций под управлением ОС Microsoft Windows 8.1. В основном поддержка заключается в установке нужного для учебного процесса ПО и обспечении общей работоспособности.
На каждой станции есть 2 пользователя: Администратор и Студент. Администратору доступно полное управление, у Студента нет возможности установки ПО. Чтобы не утруждать себя чисткой пользователя Студент, эта учетка просто удаляется целиком и создается заново. Это влечет за собой некоторые телодвижения, которые нужно выполнять на каждой станции.
В этом году решил автоматизировать большую часть телодвижений c помощью PowerShell без ActiveDirectory и собрал в этот пост некоторые рецепты, которые отыскал в сети.
Подготовка
Сразу же столкнулся с тем, что на станциях установлен PS 4 и некоторые примеры из всезнающего Интернета не работали. Поэтому, прежде, чем запускать получившиеся скрипты, нужно выполнить пару действий:
- установить Windows Management Framework 5.1
- установить последнюю верисию PowerShell
Автоматизируемые действия
- Удаление/создание учетной записи пользователя
- Автовход заданного пользователя
- Запуск скрипта при первом входе пользователя
Удаление/создание учетной записи пользователя
Начал с создания. В этом случае требуется выполнить 2 действия: создать пользователя (New-LocalUser) и добавить его в группу (Add-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.
Удаление организовал по следующему принципу: удалить все учетные записи, которые были созданы Администратором. Для этого с помощью WMI объекта класса Win32_UserProfile определяю всех пользователей, которые в данный момент не активны и не являются специальными.
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"
}
Запуск скрипта при первом входе пользователя
Оказалось, что не все можно настроить до первого входа нового пользователя (что было для меня несколько удивительно). Поэтому возникла потребность запустить скрипт, который выполняет некоторые действия после первого входа:
- Настройка прокси
- Запрет создания файлов на рабочем столе
- Настройка панели управления пользователя
Я попробовал несколько способов, но по рабочим для меня оказался следующий: установить таск. Но таск средствами PS мне не удалось завести. Поэтому пошел длинной тропинкой:
schtasks /create /tn LogonUserSettings /tr "pwsh C:\Scripts\Settings.ps1" /sc onlogon /ru $env:USERDOMAIN\$UserName /rp $Password /f
Но этого оказалось не достаточно — Windows запросила разрешить вход в качестве пакетного задания (SeBatchLogonRight). Поиски ответа на вопрос как это сделать привели к такому результату:
LsaWrapper
SPL
$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
SPL
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 оказалось не самым простым преключением, но познавательным. Скрипт настройки буду развивать. В планах добавить проверку на наличие установленного ПО и установка, запуск антивируса.
Итоговые скрипты, которые в работе
SPL
Запуск от имени Администратора
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
===========
Источник:
habr.com
===========
Похожие новости:
- [Системное администрирование] Windows 10@2004 update и потеря куков
- [Системное администрирование, Nginx, *nix, DevOps] Отправка Nginx json логов с помощью Vector в Clickhouse и Elasticsearch
- [Системное администрирование, IT-инфраструктура, Microsoft SQL Server, Хранение данных] Миграция IBM Lotus Notes/Domino в Microsoft Exchange без шума и пыли
- [Системное администрирование, Серверное администрирование, DevOps, Kubernetes] New Relic меняет бизнесь модель — открывает код агентов и инструментария (перевод)
- [Системное администрирование, DevOps] Системный подход к переменным в Ansible
- [Open source, Системное администрирование, JavaScript, IT-инфраструктура] Решаем практические задачи в Zabbix с помощью JavaScript
- [Системное администрирование, Серверное администрирование, Администрирование баз данных] Зачем нужно держать клетки в зоопарке закрытыми (перевод)
- [Системное администрирование, Серверное администрирование, DevOps, Kubernetes] Требования к разработке приложения в Kubernetes
- [Системное администрирование, IT-инфраструктура, Серверное администрирование, DevOps] С чего начать DevOps?
- [Разработка веб-сайтов, Разработка игр, Разработка мобильных приложений, Разработка под Linux, Разработка под Windows] Свободная веб-энциклопедия для любых IT-проектов на собственном движке
Теги для поиска: #_sistemnoe_administrirovanie (Системное администрирование), #_powershell, #_powershell, #_windows, #_administrirovanie_windows (администрирование windows), #_sistemnoe_administrirovanie (
Системное администрирование
), #_powershell
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 01:03
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Вот уже несколько лет занимаюсь в университете поддержкой 10 рабочих станций под управлением ОС Microsoft Windows 8.1. В основном поддержка заключается в установке нужного для учебного процесса ПО и обспечении общей работоспособности. На каждой станции есть 2 пользователя: Администратор и Студент. Администратору доступно полное управление, у Студента нет возможности установки ПО. Чтобы не утруждать себя чисткой пользователя Студент, эта учетка просто удаляется целиком и создается заново. Это влечет за собой некоторые телодвижения, которые нужно выполнять на каждой станции. В этом году решил автоматизировать большую часть телодвижений c помощью PowerShell без ActiveDirectory и собрал в этот пост некоторые рецепты, которые отыскал в сети. Подготовка Сразу же столкнулся с тем, что на станциях установлен PS 4 и некоторые примеры из всезнающего Интернета не работали. Поэтому, прежде, чем запускать получившиеся скрипты, нужно выполнить пару действий:
Автоматизируемые действия
Удаление/создание учетной записи пользователя Начал с создания. В этом случае требуется выполнить 2 действия: создать пользователя (New-LocalUser) и добавить его в группу (Add-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. Удаление организовал по следующему принципу: удалить все учетные записи, которые были созданы Администратором. Для этого с помощью WMI объекта класса Win32_UserProfile определяю всех пользователей, которые в данный момент не активны и не являются специальными. 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" } Запуск скрипта при первом входе пользователя Оказалось, что не все можно настроить до первого входа нового пользователя (что было для меня несколько удивительно). Поэтому возникла потребность запустить скрипт, который выполняет некоторые действия после первого входа:
Я попробовал несколько способов, но по рабочим для меня оказался следующий: установить таск. Но таск средствами PS мне не удалось завести. Поэтому пошел длинной тропинкой: schtasks /create /tn LogonUserSettings /tr "pwsh C:\Scripts\Settings.ps1" /sc onlogon /ru $env:USERDOMAIN\$UserName /rp $Password /f
Но этого оказалось не достаточно — Windows запросила разрешить вход в качестве пакетного задания (SeBatchLogonRight). Поиски ответа на вопрос как это сделать привели к такому результату: LsaWrapperSPL$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 на официальном сайте. Настройка панели управления пользователя Это делать было не обязательно, но я подумал, что было бы круто предоставить студентам настроенную панель, с часто используемыми программами. Ответ нашелся тут. PinnedApplicationSPLfunction 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 оказалось не самым простым преключением, но познавательным. Скрипт настройки буду развивать. В планах добавить проверку на наличие установленного ПО и установка, запуск антивируса. Итоговые скрипты, которые в работеSPLЗапуск от имени Администратора
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 =========== Источник: habr.com =========== Похожие новости:
Системное администрирование ), #_powershell |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 23-Ноя 01:03
Часовой пояс: UTC + 5