Чтение системного реестра из MQL - страница 2

 
stringo:

Стандартные грабли ...

СЛЕШ ДОЛЖЕН БЫТЬ ДВОЙНЫМ!!! читайте доки, ибо они - рулез


Опять таки большое спасибо за содержательный совет. Почему-то все считают что то, что они знают, работает так как они думают.
А ведь есть две большие разницы между "я читал, что оно так должно работать" и "оно так работает".

Ну ведь специально приложен откоментаренный код. Ну поставьте недостающие "черточки" и убедитесь, что что ваш рецепт подействовал :)

Я, например, прежде чем написать ЭТОТ ответ, сделал имено так - проверил как оно работает. И что? Теже самые 87. Пошел дальше - написал перед вызовом две строчки:

Print("SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders");
Print("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");

обе напечатали одну и туже строку "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders". По секрету скажу - я даже в начале и в конце строки слеши (и одинарные и двойные) дописывал... с тем же результатом. Видать проблемма не в этом.

Дорогие форумчане, у меня есть проблема которую я решить не могу. Если для вас это семечки со "стандартными граблями" - "JUST DO IT": получите нужный MessageBox с текстом и запостите ответ с работающим кодом и, чтобы не было никаких подозрений по поводу вашей "начитанности" - приложите скрин полученного результата.

Я очень надеюсь что здесь найдется специалист, которому эта задачка окажется по зубам ;)

 
stringo писал (а):
... читайте доки, ибо они - рулез

Но чтение доков и правда приносит пользу :)

Строковая константа представляет собой ...
Внутреннее представление - структура размером 8 байт. Первый элемент структуры - длинное целое, содержит размер распределенного для строки буфера. Второй элемент структуры - 32-разрядный адрес буфера, содержащего строку.

если в DLL передается не сама строка а эта структура или ссылка на нее, то ожидать правильного результата нельзя - ведь системная DLL-ка наверняка принимает честную строку с нулевым символом в конце а не эту структуру.

Интересно, а чего молчат разработчики MQL? Ведь это либо их недоработка, либо явный глюк, либо нечетко написанная документация :(

 
Я один из разработчиков. Нечётко написанная документация. Будем дополнять.
 
stringo:
Я один из разработчиков. Нечётко написанная документация. Будем дополнять.
Отлично. Готов быть бета-тестером, даже бета-редактором (О.Р. редактором - 3 года) ;)
 

Вот правильно работающий скрипт

//+------------------------------------------------------------------+
//|                                                 ReadRegistry.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Кравчук Сергей"
#property link      "http://forextools.forexland.ru"
 
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// БИБЛИОТЕКА РАБОТЫ С РЕЕСТРОМ
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#import "advapi32.dll"
    int RegOpenKeyA(int hkey, string lpSubKey, int phkResult[]);
    int RegCloseKey(int hkey);
    int RegQueryValueExA(int hkey, string lpValueName, int lpReserved, int lpType[], string lpData, int lpcbData[]);
    int RegSetValueExA(int hkey, string lpValueName, int Reserved, int dwType, string lpData, int cbData);
 
int start()
{
  string Res = GetRegString(0x80000002, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal");
    
  Print(Res); MessageBox(Res);
}
 
string GetRegString(int HomeKey, string KeyName, string ValueName) 
{
  int hkey[1];       //Handle раздела реестра
  string sData;      //переменная для хранения значения
  int lres;          //Результат работы API функций
  int lDataType[1];  //Тип возвращаемого значения
  int lDlen[1];      //переменная для хранения длины строки
  int p;             //переменная для подрезки последних пустых строк 
  lres = RegOpenKeyA(HomeKey, KeyName, hkey); // Открываем Раздел
  
  Print("RegOpenKeyA ret code="+lres); 
/*
Return values
Public Const ERROR_SUCCESS = 0&
Public Const ERROR_FILE_NOT_FOUND = 2&
Public Const ERROR_ACCESS_DENIED = 5&
Public Const ERROR_INVALID_HANDLE = 6&
Public Const ERROR_INVALID_PARAMETER = 87
Public Const ERROR_CALL_NOT_IMPLEMENTED = 120&
Public Const ERROR_INSUFFICIENT_BUFFER = 122
Public Const ERROR_MORE_DATA = 234
Public Const ERROR_NO_MORE_ITEMS = 259&
Public Const ERROR_CANTOPEN = 1011&
Public Const ERROR_CANTREAD = 1012&
Public Const ERROR_CANTWRITE = 1013&
Public Const ERROR_REGISTRY_RECOVERED = 1014&
Public Const ERROR_REGISTRY_CORRUPT = 1015&
Public Const ERROR_REGISTRY_IO_FAILED = 1016&
Public Const ERROR_NOT_REGISTRY_FILE = 1017&
Public Const ERROR_KEY_DELETED = 1018&
*/  
  if (lres!=0) return(""); //Если вернулся не ноль - ошибка, выходим
  sData = "                                                                                                                       ";
  lDlen[0] = StringLen(sData);
  lres = RegQueryValueExA(hkey[0], ValueName, 0, lDataType, sData, lDlen); //Читаем значение
  
  Print("RegQueryValueExA ret code="+lres+"  Value="+sData); 
  
  if (lres!=0) return(""); //Если вернулся не ноль - ошибка, выходим
 
  if (lDataType[0]==1 || lDataType[0]==2) return(StringSubstr(sData,0,lDlen[0]-1)); //  REG_SZ, REG_EXPAND_SZ - Unicode nul terminated string
  else if (lDataType[0]==7) // REG_MULTI_SZ - Multiple Unicode Strings
  {    
    for(p=lDlen[0];0<p;p--) if(StringGetChar(sData,p)!=0) break; 
    sData = StringSubstr(sData,0,p);
    for(p=StringLen(sData);0<p;p--) if(StringGetChar(sData,p)==0) StringSetChar(sData,p,10); //заменим нули на символы переноса строки            
    return(sData);
  }
  else return(""); //остальные типы данных не преобразуются в строку :(
  lres = RegCloseKey(hkey[0]);
}

Все нюансы, которые Вы найдёте, описаны в документации (читайте про передачу параметров в импортируемые функции). И обсуждались здесь на форуме.

 

Снова ОТЛИЧНО. Все работает! Огромадное спасибо!!!

Особая благодарность stringo за оперативность и решение проблемы по существу.

 
Slava:

Вот правильно работающий скрипт

Все нюансы, которые Вы найдёте, описаны в документации (читайте про передачу параметров в импортируемые функции). И обсуждались здесь на форуме.

Доброго времени суток!
Прошло уже не мало лет :)
У мня такая же задача, но возвращает ошибку ERROR_FILE_NOT_FOUND = 2
Код поправлен для MQL5

//+------------------------------------------------------------------+
//|                                                 ReadRegistry.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Кравчук Сергей"
#property link      "http://forextools.forexland.ru"

#define HKEY_CLASSES_ROOT     0x80000000
#define HKEY_CURRENT_USER     0x80000001
#define HKEY_LOCAL_MACHINE    0x80000002
#define HKEY_USERS            0x80000003
#define HKEY_PERFORMANCE_DATA 0x80000004
#define HKEY_CURRENT_CONFIG   0x80000005
#define HKEY_DYN_DATA         0x80000006
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// БИБЛИОТЕКА РАБОТЫ С РЕЕСТРОМ
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#import "advapi32.dll"
int RegOpenKeyA(uint hkey,string lpSubKey,uint &phkResult[]);
int RegCloseKey(uint hkey);
int RegQueryValueExA(uint hkey,string lpValueName,uint lpReserved,uint &lpType[],string lpData,uint &lpcbData[]);
int RegSetValueExA(uint hkey,string lpValueName,uint Reserved,uint dwType,string lpData,uint cbData);
#import
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
// string Res = GetRegString(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal");
   string Res = GetRegString(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography","MachineGuid");
// string Res = GetRegString(HKEY_LOCAL_MACHINE, "SOFTWARE\\AGEIA Technologies", "PhysX Version"); 
   MessageBox("["+Res+"]");
   Print("Result: ["+Res+"]");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string GetRegString(uint HomeKey,string KeyName,string ValueName)
  {
   uint hkey[1];       //Handle раздела реестра
   string sData;      //переменная для хранения значения
   uint lres;          //Результат работы API функций
   uint lDataType[1];  //Тип возвращаемого значения
   uint lDlen[1];      //переменная для хранения длины строки
   uint p;             //переменная для подрезки последних пустых строк 
   lres=RegOpenKeyA(HomeKey,KeyName,hkey); // Открываем Раздел

   Print("RegOpenKeyA ret code="+Errors(lres));
   if (lres!=0) return(""); //Если вернулся не ноль - ошибка, выходим
   
   sData="                                                                                                                       ";
   lDlen[0]=StringLen(sData);
   lres=RegQueryValueExA(hkey[0],ValueName,0,lDataType,sData,lDlen); //Читаем значение

   Print("RegQueryValueExA ret code="+Errors(lres)+"  Value=["+sData+"]");

   if(lres!=0) return(""); //Если вернулся не ноль - ошибка, выходим

   if(lDataType[0]==1 || lDataType[0]==2) return(StringSubstr(sData,0,lDlen[0]-1)); //  REG_SZ, REG_EXPAND_SZ - Unicode nul terminated string
   else if(lDataType[0]==7) // REG_MULTI_SZ - Multiple Unicode Strings
     {
      for(p=lDlen[0];0<p;p--) if(StringGetCharacter(sData,p)!=0) break;
      sData= StringSubstr(sData,0,p);
      for(p=StringLen(sData);0<p;p--) if(StringGetCharacter(sData,p)==0) StringSetCharacter(sData,p,10); //заменим нули на символы переноса строки            
      return(sData);
     }
   else return(""); //остальные типы данных не преобразуются в строку :(
   lres=RegCloseKey(hkey[0]);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#define ERROR_SUCCESS 0
#define ERROR_FILE_NOT_FOUND 2
#define ERROR_ACCESS_DENIED 5
#define ERROR_INVALID_HANDLE 6
#define ERROR_INVALID_PARAMETER 87
#define ERROR_CALL_NOT_IMPLEMENTED 120
#define ERROR_INSUFFICIENT_BUFFER 122
#define ERROR_MORE_DATA 234
#define ERROR_NO_MORE_ITEMS 259
#define ERROR_CANTOPEN 1011
#define ERROR_CANTREAD 1012
#define ERROR_CANTWRITE 1013
#define ERROR_REGISTRY_RECOVERED 1014
#define ERROR_REGISTRY_CORRUPT 1015
#define ERROR_REGISTRY_IO_FAILED 1016
#define ERROR_NOT_REGISTRY_FILE 1017
#define ERROR_KEY_DELETED 1018

string Errors(uint err)
  {
  string res;
   switch(err)
     {
      case              ERROR_SUCCESS: res = "ERROR_SUCCESS"; break;
      case       ERROR_FILE_NOT_FOUND: res = "ERROR_FILE_NOT_FOUND"; break;
      case        ERROR_ACCESS_DENIED: res = "ERROR_ACCESS_DENIED"; break;
      case       ERROR_INVALID_HANDLE: res = "ERROR_INVALID_HANDLE"; break;
      case    ERROR_INVALID_PARAMETER: res = "ERROR_INVALID_PARAMETER"; break;
      case ERROR_CALL_NOT_IMPLEMENTED: res = "ERROR_CALL_NOT_IMPLEMENTED"; break;
      case  ERROR_INSUFFICIENT_BUFFER: res = "ERROR_INSUFFICIENT_BUFFER"; break;
      case            ERROR_MORE_DATA: res = "ERROR_MORE_DATA"; break;
      case        ERROR_NO_MORE_ITEMS: res = "ERROR_NO_MORE_ITEMS"; break;
      case             ERROR_CANTOPEN: res = "ERROR_CANTOPEN"; break;
      case             ERROR_CANTREAD: res = "ERROR_CANTREAD"; break;
      case            ERROR_CANTWRITE: res = "ERROR_CANTWRITE"; break;
      case   ERROR_REGISTRY_RECOVERED: res = "ERROR_REGISTRY_RECOVERED"; break;
      case     ERROR_REGISTRY_CORRUPT: res = "ERROR_REGISTRY_CORRUPT"; break;
      case   ERROR_REGISTRY_IO_FAILED: res = "ERROR_REGISTRY_IO_FAILED"; break;
      case    ERROR_NOT_REGISTRY_FILE: res = "ERROR_NOT_REGISTRY_FILE"; break;
      case          ERROR_KEY_DELETED: res = "ERROR_KEY_DELETED"; break;
      default: res = "Unknow error"; break;
     }
   return res;
  }
//+------------------------------------------------------------------+
 
#define _WIN64  // Только для 64-разрядного терминала!

#include <WinDef.mqh>

#define HKEY PVOID

#define HKEY_CLASSES_ROOT                   (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )
#define HKEY_CURRENT_USER                   (( HKEY ) (ULONG_PTR)((LONG)0x80000001) )
#define HKEY_LOCAL_MACHINE                  (( HKEY ) (ULONG_PTR)((LONG)0x80000002) )
#define HKEY_USERS                          (( HKEY ) (ULONG_PTR)((LONG)0x80000003) )
#define HKEY_PERFORMANCE_DATA               (( HKEY ) (ULONG_PTR)((LONG)0x80000004) )
#define HKEY_PERFORMANCE_TEXT               (( HKEY ) (ULONG_PTR)((LONG)0x80000050) )
#define HKEY_PERFORMANCE_NLSTEXT            (( HKEY ) (ULONG_PTR)((LONG)0x80000060) )

#define REG_NONE                    ( 0 )   // No value type
#define REG_SZ                      ( 1 )   // Unicode nul terminated string
#define REG_EXPAND_SZ               ( 2 )   // Unicode nul terminated string
                                            // (with environment variable references)
#define REG_BINARY                  ( 3 )   // Free form binary
#define REG_DWORD                   ( 4 )   // 32-bit number
#define REG_DWORD_LITTLE_ENDIAN     ( 4 )   // 32-bit number (same as REG_DWORD)
#define REG_DWORD_BIG_ENDIAN        ( 5 )   // 32-bit number
#define REG_LINK                    ( 6 )   // Symbolic Link (unicode)
#define REG_MULTI_SZ                ( 7 )   // Multiple Unicode strings
#define REG_RESOURCE_LIST           ( 8 )   // Resource list in the resource map
#define REG_FULL_RESOURCE_DESCRIPTOR ( 9 )  // Resource list in the hardware description
#define REG_RESOURCE_REQUIREMENTS_LIST ( 10 )
#define REG_QWORD                   ( 11 )  // 64-bit number
#define REG_QWORD_LITTLE_ENDIAN     ( 11 )  // 64-bit number (same as REG_QWORD)

#define FORMAT_MESSAGE_IGNORE_INSERTS  0x00000200
#define FORMAT_MESSAGE_FROM_HMODULE    0x00000800
#define FORMAT_MESSAGE_FROM_SYSTEM     0x00001000

#define MAKELANGID(p, s)       ((((WORD  )(s)) << 10) | (WORD  )(p))

#define LANG_NEUTRAL                     0x00
#define SUBLANG_DEFAULT                  0x01    // user default
#define SUBLANG_SYS_DEFAULT              0x02    // system default

#define LANG_SYSTEM_DEFAULT    (MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT))
#define LANG_USER_DEFAULT      (MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT))


#import "advapi32.dll"
   uint RegOpenKeyW( HKEY hKey, const string lpSubKey, HKEY& phkResult );
   uint RegCloseKey( HKEY hKey );
   uint RegQueryValueExW( HKEY hKey, const string lpValueName, PVOID lpReserved, uint& lpType, ushort& lpData[], uint& lpcbData );
   uint RegQueryValueExW( HKEY hKey, const string lpValueName, PVOID lpReserved, uint& lpType, PVOID lpData, uint& lpcbData );
#import "Kernel32.dll"
   uint FormatMessageW( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, ushort& lpBuffer[], DWORD nSize, PVOID Arguments );
#import

ushort buffer[256];
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   string Res = GetRegString( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", "MachineGuid" );
   Print( Res );
   MessageBox( Res );
}
//+------------------------------------------------------------------+
string GetRegString( HKEY HomeKey, string KeyName, string ValueName )
{
   string sValue;          // Результат
   HKEY hkey;              // Handle раздела реестра
   
   uint lres = RegOpenKeyW( HomeKey, KeyName, hkey ); // Открываем Раздел
   
   Print( "RegOpenKey ret code = " + ErrorString( lres ) );
   if( lres != 0 ){
      return sValue;       // Если вернулся не ноль - ошибка, выходим
   }
   
   uint lDlen = 0;          // переменная для хранения длины строки
   uint lDataType = 0;      // Тип возвращаемого значения
   
   lres = RegQueryValueExW( hkey, ValueName, 0, lDataType, 0, lDlen ); // Получаем длину строки
   
   Print( "RegQueryValueEx ret code = " + ErrorString( lres ) );
   
   if( lres == 0 && lDlen > 0 && ((lDataType == REG_SZ) || (lDataType == REG_EXPAND_SZ)) )
   {
      ushort sData[];
      ArrayResize( sData, lDlen / 2 );
      
      lres = RegQueryValueExW( hkey, ValueName, 0, lDataType, sData, lDlen ); // Читаем значение
      
      sValue = ShortArrayToString( sData );
   }
   RegCloseKey( hkey );
   
   return sValue;
}
//+------------------------------------------------------------------+
string ErrorString( uint code )
{
   uint len = FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, code, LANG_SYSTEM_DEFAULT, buffer, 256, 0 );
   if( len ){
      return ShortArrayToString( buffer );
   }
   return "Неизвестная ошибка";
}
//+------------------------------------------------------------------+

Работает и в MT4 и в MT5.

Файлы:
WinDef.mqh  2 kb
 
Koldun Zloy:

Работает и в MT4 и в MT5.

Где взять 64битный МТ4?

 
Edgar:

Где взять 64битный МТ4?

Попросить разработчиков чтобы выпустили=)

Причина обращения: