пятница, 21 июня 2019 г.

Команда Power Shell для сохранения списка электронных адресов из Active Directory

1. Убедитесь что у вас к Power Shell подключен модуль для работы с Active Directory. 

2. Выполните команду Power Shell
 

PS C:\Users\User> Get-ADUser -Filter * -Properties EmailAddress |
 select EmailAddress | Export-CSV "D:\Email_Addresses.csv"  


3. После выполнения команду список электронных адресов у вас будет сохранен в файле Email_Addresses.csv на разделе D.

Получение списка адресов электронной почты из Active Directory в Delphi 7

Под этим способом подразумевается получение списка адресов электронной почты из Active Directory с использованием скрипта VBScript и передача этого списка в Delphi программу для дальнейшей обработки.

Теперь приступим к реализации этого способа.

Нам необходимо разработать VBScript для получения списка адресов электронной почты из Active Directory. Назовём этот скрипт main.vbs.

Ниже показан код скрипта main.vbs:
function GetADMailString()

On Error Resume Next

Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strMail
Dim strResult

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")

If Err.Number <> 0 Then
 GetADMailString = ""
Else
 
 strDNSDomain = objRootDSE.Get("defaultNamingContext")
 strBase = "<LDAP://" & strDNSDomain & ">"

 ' Filter on user objects.
 strFilter = "(&(objectCategory=person)(objectClass=user) (mail=*))"

 ' Comma delimited list of attribute values to retrieve.
 strAttributes = "mail"

 ' Construct the LDAP syntax query.
 strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
 adoCommand.CommandText = strQuery
 adoCommand.Properties("Page Size") = 100
 adoCommand.Properties("Timeout") = 30
 adoCommand.Properties("Cache Results") = False

 ' Run the query.
 Set adoRecordset = adoCommand.Execute 
 
 ' Enumerate the resulting recordset.
 Do Until adoRecordset.EOF
  ' Retrieve values and display.
  strMail = adoRecordset.Fields("mail").Value
  
  If strMail <> "" Then
   strResult = strResult & strMail & vbCrLf
  End if
  ' Move to the next record in the recordset.
  adoRecordset.MoveNext
 Loop
 ' Clean up.
 adoRecordset.Close
 adoConnection.Close
 
 GetADMailString = strResult
end if

end function

Теперь пройдемся вкратце по коду скрипта main.vbs и функции GetADMailString

1. Объявляем необходимые переменные для работы скрипта, смотрите часть кода ниже:

On Error Resume Next

Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strMail
Dim strResult


2. Осуществляем подключение к Active Directory

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection


3. Получаем домен по умолчанию

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")

If Err.Number <> 0 Then
    GetADMailString = ""
Else
   
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    strBase = "<LDAP://" & strDNSDomain & ">"


4. Формируем запрос и выполняем его для получения строки со всеми почтовыми адресами из Active Directory

' Filter on user objects.
    strFilter = "(&(objectCategory=person)(objectClass=user) (mail=*))"

    ' Comma delimited list of attribute values to retrieve.
    strAttributes = "mail"

    ' Construct the LDAP syntax query.
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    adoCommand.CommandText = strQuery
    adoCommand.Properties("Page Size") = 100
    adoCommand.Properties("Timeout") = 30
    adoCommand.Properties("Cache Results") = False

    ' Run the query.
    Set adoRecordset = adoCommand.Execute   


5. Формируем строку из всех почтовых адресов

' Enumerate the resulting recordset.
    Do Until adoRecordset.EOF
        ' Retrieve values and display.
        strMail = adoRecordset.Fields("mail").Value
       
        If strMail <> "" Then
            strResult = strResult & strMail & vbCrLf
        End if
        ' Move to the next record in the recordset.
        adoRecordset.MoveNext
    Loop


6. Закрываем соединение с Active Directory и возвращаем результат выполнения скрипта main.vbs

    ' Clean up.
    adoRecordset.Close
    adoConnection.Close
   
    GetADMailString = strResult
end if

end function


Так со скриптом main.vbs мы разобрались. Теперь нам необходимо передать результат выполнения скрипта в нашу программу и сохранить все почтовые адреса в текстовый файл.

Создайте проект на в среде Delphi 7 и сохраните его под именем p22.dpr. Основной модуль программы сохраните под именем p22_unit1.pas. Файл скрипта main.vbs должен лежать в той же директории, что и файл проекта, и исполняемый файл программы.

На форму с именем Form1 необходимо перетащить компонент ScriptControl. Я уже писал, как установить данный компонент и задействовать его в проекте (Смотрите статью http://notidealrunner.blogspot.com/2019/05/vbscripts-delphi.html).  Вкратце опишу основные моменты работы программы.

1. В обработчике показа формы мы проверяем существует ли скрипт main.vbs, открываем его на чтение, считываем его построчно.

procedure TForm1.FormShow(Sender: TObject);
var
    ScriptFile: TextFile;
    Script, LineScript: String;
    SA : TSafeArrayBound;
    pPar:PSafeArray;
    res:Variant;
begin
    AssignFile(ScriptFile,'main.vbs');
    Reset(ScriptFile);
    if IOResult <> 0 then
    begin
      MessageBox(0,'File access error.','Error',0);
      exit;
    end;

    while not EOF(ScriptFile) do
    begin
      readln(ScriptFile, LineScript);
      Script := Script + LineScript+#13+#10;
    end;
    CloseFile(ScriptFile);


2. Далее выполняем скрипт mian.vbs и функцию GetADMailString. Получаем результат выполнения скрипта и сохраняем в строковую переменную strTemp.   

    try
      ScriptControl1.Language := 'VBScript';
      ScriptControl1.AddCode(Script);
      SA.cElements := 0;
      pPar := SafeArrayCreate(varVariant, 1, SA);
      res:=ScriptControl1.Run('GetADMailString',pPar);
      strTemp := VarToStr(res);
    except
      on E: Exception do
        MessageDlg(PWideChar(E.Message), mtError, [mbOK], 0);
    end;


3. Далее передаем строковую переменную strTemp в процедуру сохранения в текстовый файл.

StrToFile('Mail.txt', strTemp); 

Ниже код процедуры сохранения строки в файл (Код процедуры взят с сайта https://stackoverflow.com/questions/7752273/how-to-save-a-string-to-a-txt-file-in-delphi).

procedure StrToFile(const FileName, SourceString : string);
var
  Stream : TFileStream;
begin
  Stream:= TFileStream.Create(FileName, fmCreate);
  try
    Stream.WriteBuffer(Pointer(SourceString)^, Length(SourceString));
  finally
    Stream.Free;
  end;
end;


Вот и все. Список всех электронных почтовых адресов будет сохранен в файл Mail.txt в директории проекта. Ниже показан код проекта полностью.

unit p22_unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, MSScriptControl_TLB, ActiveX;

type
  TForm1 = class(TForm)
    ScriptControl1: TScriptControl;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure StrToFile(const FileName, SourceString : string);
var
  Stream : TFileStream;
begin
  Stream:= TFileStream.Create(FileName, fmCreate);
  try
    Stream.WriteBuffer(Pointer(SourceString)^, Length(SourceString));
  finally
    Stream.Free;
  end;
end;

var
  strTemp: String;

procedure TForm1.FormShow(Sender: TObject);
var
    ScriptFile: TextFile;
    Script, LineScript: String;
    SA : TSafeArrayBound;
    pPar:PSafeArray;
    res:Variant;
begin
    AssignFile(ScriptFile,'main.vbs');
    Reset(ScriptFile);
    if IOResult <> 0 then
    begin
      MessageBox(0,'File access error.','Error',0);
      exit;
    end;

    while not EOF(ScriptFile) do
    begin
      readln(ScriptFile, LineScript);
      Script := Script + LineScript+#13+#10;
    end;
    CloseFile(ScriptFile);

    try
      ScriptControl1.Language := 'VBScript';
      ScriptControl1.AddCode(Script);
      SA.cElements := 0;
      pPar := SafeArrayCreate(varVariant, 1, SA);
      res:=ScriptControl1.Run('GetADMailString',pPar);
      strTemp := VarToStr(res);
    except
      on E: Exception do
        MessageDlg(PWideChar(E.Message), mtError, [mbOK], 0);
    end;

    StrToFile('Mail.txt', strTemp);
end;

end.

Получаем версию операционной системы Windows в Delphi 7

Есть такая известная функция получения версии операционной системы Windows – GetVersionEx, но начиная с версии Windows 8 и выше данная функция работает должным образом только совместно с файлом манифеста.

Создайте новый проект. Сохраните проект с именем p21.dpr. Основной модуль назовите p21_unit1.pas. В каталоге проекта создайте файл манифеста Windows.manifest. Содержимое файла должно быть следующее:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" name="App" version="3.1.0.0" processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> 
      <!--The ID below indicates application support for Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> 
      <!--The ID below indicates application support for Windows 10 --> 
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility></assembly>

Далее нам необходимо в каталоге проекта создать файл ресурсов компиляции с именем Windows.rc. Содержимое файла компиляции будет следующее:

1 24 "Windows.manifest"

То есть мы в качестве ресурсов нашего приложения указываем наш файл манифеста.

Файл ресурсов компиляции Windows.rc необходимо скомпилировать при помощи компилятора ресурсов brcc32.exe, этот компилятор ресурсов расположен в каталоге, где расположены бинарные файлы Delphi, у меня это каталог D:\Programs\Delphi7\Files\Delphi7\Bin. Убедитесь, что данный каталог добавлен в переменную окружения Path. Запустите командную строку Windows, перейдите в каталог проекта и выполните команду компиляции ресурсов (Смотрите рисунок 1).

brcc32.exe Windows.rc

В качестве результата в каталоге проекта вы получите файл ресурсов Windows.RES, который необходимо в файле проекта p21.dpr подключить. Смотрите код ниже:

Рисунок 1. Создание файла ресурсов

program p21;

uses
  Forms,
  p21_unit1 in 'p21_unit1.pas' {Form1};

{$R *.res}
{$R Windows.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Разместите на форме Form1 текстовую метку Lable1. В метке Label1 мы будем отображать версию операционной системы Windows (Смотрите рисунок 2).

Рисунок 2. Создание формы приложения

Переходим к написанию кода. Рассмотрим обработчик показа формы Form1, это следующий код:

procedure TForm1.FormShow(Sender: TObject);
begin
  Label1.Caption := WinName;
end;

В обработчике показа формы Form1 мы метке Label1 присваиваем результат возврата функции WinName.

Рассмотрим две функции, которые получают версию операционной системы Windows.

function WinVerNum: integer;
var
  ver: TOSVersionInfo;
begin
  ver.dwOSVersionInfoSize := SizeOf(ver);
  if GetVersionEx(ver) then
    with ver do
      result := StrToInt(IntToStr(dwMajorVersion) + '' + IntToStr(dwMinorVersion));
end;

При помощи функции GetVersionEx мы получаем номер основной и второстепенный для нашей операционной системы Windows. Преобразуем основной и второстепенный номер в строку, выполняем соединение этих строк в одну и возвращаем результат выполнения функции WinVerNum.

function WinName: String;
begin
  if WinVerNum = 51 then result := 'Windows XP';
  if WinVerNum = 60 then result := 'Windows Vista';
  if WinVerNum = 61 then result := 'Windows 7';
  if WinVerNum = 62 then result := 'Windows 8';
  if WinVerNum = 63 then result := 'Windows 8.1';
  if WinVerNum = 100 then result := 'Windows 10';
end;

При помощи функции WinName мы получаем версию операционной системы Windows и возвращаем ее в виде строки.

Результат работы программы (Смотрите рисунок 3).

Рисунок 3. Результат работы программы

Код полностью:

unit p21_unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function WinVerNum: integer;
var
  ver: TOSVersionInfo;
begin
  ver.dwOSVersionInfoSize := SizeOf(ver);
  if GetVersionEx(ver) then
    with ver do
      result := StrToInt(IntToStr(dwMajorVersion) + '' + IntToStr(dwMinorVersion));
end;

function WinName: String;
begin
  if WinVerNum = 51 then result := 'Windows XP';
  if WinVerNum = 60 then result := 'Windows Vista';
  if WinVerNum = 61 then result := 'Windows 7';
  if WinVerNum = 62 then result := 'Windows 8';
  if WinVerNum = 63 then result := 'Windows 8.1';
  if WinVerNum = 100 then result := 'Windows 10';
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Label1.Caption := WinName;
end;

end.

Задействуем UAC в приложениях написанных на Delphi 7

UAC – это Контроль Учетных Записей (Wikipedia), используется для повышения привилегий в том случае если вашему приложению это необходимо. Появился в Windows Vista и присутствует Windows 7, 8, 10. Необходимо убедится в том, что UAC включен. В Windows 7 это можно проверить, открыв «Панель управления» - «Учетные записи пользователей» - «Изменение параметров контроля учетных записей» - убедится, что установлен уровень «По умолчанию» (Смотрите рисунок 1).

 Рисунок 1. Включение UAC в Windows 7

Создадим тестовое приложение, которое будет писать в реестр Windows выбираемые из списка значения, правда путь куда мы будем записывать значения требуют повышения привилегий. Откроем Delphi 7 и создадим новый проект. Присвоим ему имя p12.dpr. Сохраним основной модуль под именем p12_unit.pas. Чтобы научить наше приложение работать с UAC, необходимо создать в папке проекта файл манифеста, назовём его Win7UAC.manifest. Содержимое файла следующее:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" name="App" version="3.1.0.0" processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> 
      <!--The ID below indicates application support for Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> 
      <!--The ID below indicates application support for Windows 10 --> 
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility></assembly>

Основным, важным моментом в файле манифеста является строчка кода:

 <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
 </requestedPrivileges>

Параметр level со значением requireAdministrator указывает на то, что нашему приложению для работы требуются права администратора.  Следующими строчками кода мы указываем с какими операционными системами наше приложение будет совместимо:

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> 
      <!--The ID below indicates application support for Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> 
      <!--The ID below indicates application support for Windows 10 --> 
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
 </compatibility>

Далее нам необходимо в каталоге проекта создать файл ресурсов компиляции с именем Win7UAC.rc. Содержимое файла компиляции будет следующее:

1 24 "Win7UAC.manifest"

То есть мы в качестве ресурсов нашего приложения указываем наш файл манифеста.

Файл ресурсов компиляции Win7UAC.rc необходимо скомпилировать при помощи компилятора ресурсов brcc32.exe, этот компилятор ресурсов расположен в каталоге, где расположены бинарные файлы Delphi, у меня это каталог D:\Programs\Delphi7\Files\Delphi7\Bin. Убедитесь, что данный каталог добавлен в переменную окружения Path. Запустите командную строку Windows, перейдите в каталог проекта и выполните команду компиляции ресурсов (Смотрите рисунок 2).

Рисунок 2. Запуск компилятора ресурсов

brcc32.exe Win7UAC.rc

В качестве результата в каталоге проекта вы получите файл ресурсов Win7UAC.RES, который необходимо в файле проекта p12.dpr подключить. Смотрите код ниже:

program p12;

uses
  Forms,
  p12_unit1 in 'p12_unit1.pas' {Form1};

{$R 'Win7UAC.RES'}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Вынесите на форму с именем Form1 одну кнопку Button1 и один список ComboBox1 (Смотрите рисунок 3).

 Рисунок 3. Создания формы приложения

Добавьте в свойства Items списка ComboBox1 две строки DOMAIN\User1 и DOMAIN\User2 (Смотрите рисунок 4). Эти строки у нас будут выбираться в ComboBox1. Также поменяйте свойства Style для списка ComboBox1 на csOwnerDraw.

Рисунок 4. Формирование списка ComboBox

Переходим к написанию кода. Рассмотрим обработчик показа формы Form1, это следующий код:

procedure TForm1.FormShow(Sender: TObject);
begin
  Combobox1.ItemIndex := Combobox1.Items.IndexOf('DOMAIN\User1');
end;

В данном обработчике мы присваиваем списку ComboBox1 значение по умолчанию значение DOMAIN\User1. 

Рассмотрим обработчик нажатия кнопки Button1, это следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
  R: TRegistry;
  openResult: Boolean;
const
  SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';

begin
  strSetRegValue := ComboBox1.Text;
  if (strSetRegValue <> '') then
  begin
    R := TRegistry.Create(KEY_READ);
    R.RootKey := HKEY_LOCAL_MACHINE;
    if (R.KeyExists(SubKey)) then
    begin
      With R do
      begin
        Access := KEY_WRITE OR $0100;
        openResult := OpenKey(SubKey, False);
        if (not openResult = True) Then
        begin
          MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
        end;
        WriteString('LastLoggedOnSAMUser', strSetRegValue);
        WriteString('LastLoggedOnUser', strSetRegValue);

        CloseKey();
        Free;
      end;
    end;
    ShowMessage('Done! Recorded in the registry.');
    strSetRegValue := '';
  end;
end;

В данном обработчике мы указываем путь в реестре Windows куда будем писать значения, это переменная типа String c именем SubKey. Смотрите код:

SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';

Далее берем выбранное значение ComboBox1 и присваиваем его переменной strSetRegValue. Смотрите код:

strSetRegValue := ComboBox1.Text;

Если переменная strSetRegValue не пуста, то начинаем писать в реестр Windows. Работать будем в корневом разделе HKEY_LOCAL_MACHINE. Смотрите код:

  if (strSetRegValue <> '') then
  begin
    R := TRegistry.Create(KEY_READ);
    R.RootKey := HKEY_LOCAL_MACHINE;


Далее проверяем существует ли путь в реестре SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI. Также открываем подраздел реестра на запись для Windows 7 32 bit и 64 bit, следующая строчка: 

Access := KEY_WRITE OR $0100;


Смотрите следующий код:

if (R.KeyExists(SubKey)) then
    begin
      With R do
      begin
        Access := KEY_WRITE OR $0100;
        openResult := OpenKey(SubKey, False);
        if (not openResult = True) Then
        begin
          MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
        end;


Далее пишем в реестр параметры LastLoggedOnSAMUser, LastLoggedOnUser и закрываем ветку реестра и освобождаем память. Следующие строчки:

        WriteString('LastLoggedOnSAMUser', strSetRegValue);
        WriteString('LastLoggedOnUser', strSetRegValue);

        CloseKey();
        Free;


Ниже показан снимок рабочей программы (Смотрите рисунок 5) и код полностью. При запуске приложения, оно спросит повышения привилегий, если вы имеете права админа (Смотрите рисунок 6) или повышения привилегий путем ввода логина и пароля администратора (Смотрите рисунок 7).

Рисунок 5. Запущенная программа

Рисунок 6. Окно разрешения запуска вашей программы, если вы имеете права администратора

Рисунок 7. Запрос прав администратора, если они у вас отсутствуют

unit p12_unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Registry;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  strSetRegValue: String;

procedure TForm1.Button1Click(Sender: TObject);
var
  R: TRegistry;
  openResult: Boolean;
const
  SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';

begin
  strSetRegValue := ComboBox1.Text;
  if (strSetRegValue <> '') then
  begin
    R := TRegistry.Create(KEY_READ);
    R.RootKey := HKEY_LOCAL_MACHINE;
    if (R.KeyExists(SubKey)) then
    begin
      With R do
      begin
        Access := KEY_WRITE OR $0100;
        openResult := OpenKey(SubKey, False);
        if (not openResult = True) Then
        begin
          MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
        end;
        WriteString('LastLoggedOnSAMUser', strSetRegValue);
        WriteString('LastLoggedOnUser', strSetRegValue);

        CloseKey();
        Free;
      end;
    end;
    ShowMessage('Done! Recorded in the registry.');
    strSetRegValue := '';
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Combobox1.ItemIndex := Combobox1.Items.IndexOf('DOMAIN\User1');
end;

end.

среда, 19 июня 2019 г.

Outlook при запуске выдает сообщение "..Ошибка операции клиента"

При запуске Outlook выдается сообщение «Файл C:\Users\ [Имя пользователя] \AppData\Local\Microsoft\Outlook\Outlook.ost» используется и в данное время недоступен. Закройте использующее файл приложение и повторить попытку. Возможно, потребуется перезагрузить компьютер». (Смотрите рисунок 1)

Рисунок 1. Первое сообщение об ошибке при запуске Outlook

После нажатия на кнопку Ok выдается второе сообщение «Не удается запустить приложение Microsoft Outlook. Невозможно открыть окно Outlook. Невозможно открыть набор папок. Ошибка операции клиента.» (Смотрите рисунок 2). После нажатия на кнопку Ok запуск Outlook не происходит.


Рисунок 2. Второе сообщение об ошибке "..Ошибка операции клиента" 

После нажатия на кнопку Ok запуск Outlook не происходит.

Данная проблема замечена в Outlook 2013 Pro 32 bit, Windows 7 64 bit. Для решения данной проблемы необходимо пересоздать профиль Outlook. Для этого откройте «Панель управления» > далее кнопку «Mail (Microsoft Outlook 2013)» и добавьте новый профиль, выставьте новый профиль по умолчанию. Откройте Outlook заново.

понедельник, 17 июня 2019 г.

Подключаем общий принтер через создание локального порта

Бывает такая ситуация, что общий принтер, подключенный к компьютеру по USB под любым предлогом, отказывается подключиться к другому компьютеру по сети, выдавая сообщение об ошибке «Windows не удается подключиться к принтеру. В ходе операции произошла ошибка 0x00000043.» (Смотрите рисунок 1).


Рисунок 1. Сообщение об ошибке при подключение принтера

В этом случае может сработать следующий способ подключения общего принтера:

Например, принтер подключен по USB к компьютеру comp1 и общее имя принтера printer1. Компьютер к которому необходимо подключить принтер по сети имеет имя comp2. На компьютере comp2 открываем «Панель управления» - «Администрирование» - «Управление печатью» - выбираем раздел «Порты», щелкаем на нем правой кнопкой мыши, в выпадающем меню выбираем пункт меню «Добавить порт…», тип порта выбираем «Local Port», в качестве имени порта укажите общий путь до принтера, например \\comp1\printer1 (Смотрите рисунок 2). Осталось установить новый принтера и в качестве порта указать наш локальный порт  \\comp1\printer1.

Рисунок 2. Настройка локально порта для общего принтера