<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>IT science: заметки с тегом lazarus</title>
<link>https://itscience.pro/tags/lazarus/</link>
<description>IT science — статьи и инструкции из мира IT</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.4 (v4171)</generator>

<itunes:subtitle>IT science — статьи и инструкции из мира IT</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>рекурсивное удаление директории</title>
<guid isPermaLink="false">10</guid>
<link>https://itscience.pro/all/rekursivnoe-udalenie-direktorii/</link>
<pubDate>Fri, 12 Apr 2019 09:06:18 +0300</pubDate>
<author></author>
<comments>https://itscience.pro/all/rekursivnoe-udalenie-direktorii/</comments>
<description>
&lt;p&gt;аналог&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;rmdir /s /q &lt;directory&gt; или rm -rf &lt;directory&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function DeleteDirectoryEx(DirectoryName: string): boolean;
// адаптирована функция DeleteDirectory из модуля fileutil, спасибо Павлу Дмитруку
var
  FileInfo: TSearchRec;
  CurSrcDir: String;
  CurFilename: String;
begin
  Result:=false;
  CurSrcDir:=CleanAndExpandDirectory(DirectoryName);
  try
         if FindFirstUTF8(CurSrcDir+GetAllFilesMask,faAnyFile,FileInfo)=0 then
         begin
           repeat
             if (FileInfo.Name&amp;lt;&amp;gt;&amp;#039;.&amp;#039;) and (FileInfo.Name&amp;lt;&amp;gt;&amp;#039;..&amp;#039;) and (FileInfo.Name&amp;lt;&amp;gt;&amp;#039;&amp;#039;) then
             begin
               CurFilename:=CurSrcDir+FileInfo.Name;
               if (FileInfo.Attr and faReadOnly)&amp;gt;0 then
                 FileSetAttrUTF8(CurFilename, FileInfo.Attr-faReadOnly);
               if (FileInfo.Attr and faDirectory)&amp;gt;0 then
               begin
                 if not DeleteDirectoryEx(CurFilename) then exit;
               end
               else
               begin
                 if not DeleteFileUTF8(CurFilename) then exit;
               end;
             end;
           until FindNextUTF8(FileInfo)&amp;lt;&amp;gt;0;
         end;
         FindCloseUTF8(FileInfo);
         if (not RemoveDirUTF8(DirectoryName)) then
           begin
             exit;
             Result:=true;
           end;
  except
    Result:=false;
  end;
end;&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>запускаем внешнее приложение, ждем завершения и получаем вывод</title>
<guid isPermaLink="false">9</guid>
<link>https://itscience.pro/all/zapuskaem-vneshnee-prilozhenie-zhdem-zaversheniya-i-poluchaem-vy/</link>
<pubDate>Thu, 11 Apr 2019 19:00:38 +0300</pubDate>
<author></author>
<comments>https://itscience.pro/all/zapuskaem-vneshnee-prilozhenie-zhdem-zaversheniya-i-poluchaem-vy/</comments>
<description>
&lt;p&gt;запускаем внешнее консольное приложение и ждем окончания его выполнения, после завершения получаем вывод в список&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function RunScript(sCommand: String): TStringList;
var
  OurCommand: String;
  OutputLines: TStringList;
  MemStream: TMemoryStream;
  OurProcess: TProcess;
  NumBytes: LongInt;
  BytesRead: LongInt;
const
  READ_BYTES = 204800;
begin
  MemStream := TMemoryStream.Create;
  BytesRead := 0;
  OurProcess := TProcess.Create(nil);
  OurCommand := sCommand;
  OurProcess.CommandLine := OurCommand;
  OurProcess.ShowWindow:=swoHIDE;
  OurProcess.Options := [poUsePipes, poNoConsole];
  OurProcess.Execute;
  while OurProcess.Running do
  begin
    MemStream.SetSize(BytesRead + READ_BYTES);
    NumBytes := OurProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
    if NumBytes &amp;gt; 0
    then begin
      Inc(BytesRead, NumBytes);
      Sleep(100);
    end
    else begin
      Sleep(100);
    end;
  end;
  Sleep(1000);
  repeat
    MemStream.SetSize(BytesRead + READ_BYTES);
    NumBytes := OurProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
    if NumBytes &amp;gt; 0
    then begin
      Inc(BytesRead, NumBytes);
    end;
    Sleep(100);
  until NumBytes &amp;lt;= 0;
  MemStream.SetSize(BytesRead);
  OutputLines := TStringList.Create;
  OutputLines.LoadFromStream(MemStream);
  result := OutputLines;
  OurProcess.Free;
  MemStream.Free;
end;&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>получаем содержимое url (поддерживается http, https)</title>
<guid isPermaLink="false">8</guid>
<link>https://itscience.pro/all/poluchaem-soderzhimoe-url-podderzhivaetsya-http-https/</link>
<pubDate>Thu, 11 Apr 2019 18:57:32 +0300</pubDate>
<author></author>
<comments>https://itscience.pro/all/poluchaem-soderzhimoe-url-podderzhivaetsya-http-https/</comments>
<description>
&lt;p&gt;Бывает в приложении для windows нужно по ссылке получить какую нибудь информацию, ниже представлена функция, которая это сделает быстро и без дополнительных библиотек&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function get_from_server(const Url: string): string;
const
  UserAgent = &amp;#039;Mozilla/5.0 (compatible)&amp;#039;;
var
  hInet: HINTERNET;
  hURL: HINTERNET;
  Buffer: array[0..1023] of AnsiChar;
  BufferLen: cardinal;
begin
  result := &amp;#039;&amp;#039;;
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if hInet = nil then RaiseLastOSError;
  try
    hURL := InternetOpenUrl(hInet, PChar(URL), nil, 0, 0, 0);
    if hURL = nil then RaiseLastOSError;
    try
      repeat
        if not InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) then
          RaiseLastOSError;
        result := result + UTF8Decode(Copy(Buffer, 1, BufferLen))
      until BufferLen = 0;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>получаем namingContexts контроллера домена</title>
<guid isPermaLink="false">7</guid>
<link>https://itscience.pro/all/poluchaem-namingcontexts-kontrollera-domena/</link>
<pubDate>Thu, 11 Apr 2019 18:53:24 +0300</pubDate>
<author></author>
<comments>https://itscience.pro/all/poluchaem-namingcontexts-kontrollera-domena/</comments>
<description>
&lt;p&gt;Некоторую информацию можно получить от контроллера домена без авторизации, например, namingContexts.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function get_ldap_namingContexts(server: string): string;
var
  ldap: TLDAPsend;
  attr: TStringList;
begin
  ldap:= TLDAPsend.Create;
  attr := TStringList.Create;
  attr.Add(&amp;#039;namingContexts&amp;#039;);
  try
       ldap.TargetHost := server;
       ldap.TargetPort := &amp;#039;389&amp;#039;;
         if ldap.Login then
          begin
           if ldap.Bind then
            begin
              ldap.SearchScope:=SS_BaseObject;
              if ldap.Search(&amp;#039;&amp;#039;, False, &amp;#039;(objectClass=*)&amp;#039;, attr) then
               begin
                  result:= ldap.SearchResult.Items[0].Attributes.Get(&amp;#039;namingContexts&amp;#039;)
               end;
            end;
           ldap.Logout;
          end;
  finally
     ldap.Free;
     attr.Free;
  end;
end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;результатом работы этой функции будет: DC=domain,DC=loc&lt;/p&gt;
&lt;p&gt;про другие параметры можно почитать здесь: &lt;a href="https://msdn.microsoft.com/en-us/library/ms684291(v=vs.85).aspx"&gt;https://msdn.microsoft.com/en-us/library/ms684291(v=vs.85).aspx&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>ldapsend, получаем sid в hex формате</title>
<guid isPermaLink="false">5</guid>
<link>https://itscience.pro/all/ldapsend-poluchaem-sid-v-hex-formate/</link>
<pubDate>Mon, 08 Apr 2019 11:58:04 +0300</pubDate>
<author></author>
<comments>https://itscience.pro/all/ldapsend-poluchaem-sid-v-hex-formate/</comments>
<description>
&lt;p&gt;функция для тех, кто работает с LDAP (ActiveDirectory)&lt;/p&gt;
&lt;p&gt;Все знают, что sid LDAP возвращает в формате bin, сконвертируем в hex строку. Функция делает запрос к серверу и получает objectSid пользователя по sAMAccountName, затем конвертирует его в строку hex с разделителями запятыми. Результатом работы функции будет строка: 01,05,00,00,00,00,00,05,15,00,00,00,8a,1c,a9,8e,20,29,32,58,4f,d1,a7,56,50,04,00,00&lt;/p&gt;
&lt;p&gt;фильтр запроса (&amp;(objectClass=user)(sAMAccountName=’+user_name+’)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) исключает заблокированные учетные записи.&lt;/p&gt;
&lt;p&gt;не забудьте подключить модуль ldapsend из библиотеки Synapse &lt;a href="http://synapse.ararat.cz/doku.php/"&gt;http://synapse.ararat.cz/doku.php/&lt;/a&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function get_bin_sid_by_name(user_name,server,user,password,namingContexts: string): string;
var
  ldap: TLDAPsend;
  attr: TStringList;
  s,str:string;
  l:PAnsiChar;
  l_l:integer;
begin
  ldap:= TLDAPsend.Create;
  attr := TStringList.Create;
  attr.Add(&amp;#039;cn&amp;#039;);
  attr.Add(&amp;#039;sAMAccountName&amp;#039;);
  attr.Add(&amp;#039;objectSid&amp;#039;);
  result:=&amp;#039;&amp;#039;;

  try
    ldap.TargetHost := server;
    ldap.TargetPort := &amp;#039;389&amp;#039;;
    ldap.UserName := user+&amp;#039;@&amp;#039;+copy(namingContexts,4,pos(&amp;#039;,&amp;#039;, namingContexts)-4);
    ldap.Password := password;
    ldap.SearchScope:=SS_WholeSubtree;
    ldap.SearchSizeLimit:=0;
    ldap.SearchTimeLimit:=0;


    if ldap.Login then
     begin
       if ldap.Bind then
        begin
          if ldap.Search(&amp;#039;CN=users,&amp;#039;+namingContexts, False, &amp;#039;(&amp;amp;(objectClass=user)(sAMAccountName=&amp;#039;+user_name+&amp;#039;)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))&amp;#039;, attr) then
             begin
               s:=ldap.SearchResult.Items[0].Attributes.Get(&amp;#039;objectSid&amp;#039;);
               GetMem(l,length(s));
               BinToHex((@s[1]),l,length(s));
               result:=copy(l,1,length(s)*2);
               str:=&amp;#039;&amp;#039;;
               for l_l:=0 to length(s)*2 do
                 begin
                   if ((l_l mod 2 = 0) and (l_l&amp;lt;&amp;gt;0) and (l_l&amp;lt;&amp;gt;length(s)*2)) then
                     begin
                      str:=str+result[l_l]+&amp;#039;,&amp;#039;;
                     end
                   else
                     begin
                       str:=str+result[l_l];
                     end;
                 end;
               result:=trim(str);
             end;
        end;
     end;
  finally
     ldap.Free;
     attr.Free;
  end;
end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;user_name — sAMAccountName пользователя, чей sid хотим получить&lt;br /&gt;
server — адрес сервера LDAP&lt;br /&gt;
user — логин для авторизации&lt;br /&gt;
password — пароль пользователя (достаточно прав обычного пользователя домена для чтения атрибутов)&lt;br /&gt;
namingContexts — корень нашего домена, например dc=server,dc=loc&lt;/p&gt;
</description>
</item>


</channel>
</rss>