Что нового

странный возврат макроса @TempDir

saavaage

Знающий
Сообщения
171
Репутация
17
суть проблемы:
1. вношу твиками новые значение для путей к папкам временных файлов (Temp) и переменных сред (Tmp):
а)Temp (например, путь D:\1)
Код:
$Input_MyTemp = 'D:\1'
RunWait(@COMSPEC & ' /c Echo Y | Cacls ' & $Input_MyTemp&' /E /P "Все":F', '', @SW_HIDE)
	   RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'TEMP', 'REG_SZ', $Input_MyTemp)
;~ 	   RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment', 'TEMP', 'REG_SZ', $Input_MyTemp)
	   RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment', 'TEMP', 'REG_SZ', $Input_MyTemp)
	   RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Session Manager\Environment', 'TEMP', 'REG_SZ', $Input_MyTemp)
	   RegWrite('HKEY_CURRENT_USER\Environment', 'TEMP', 'REG_SZ', $Input_MyTemp)


б) Tmp (например, D:\Tweaks):
Код:
$Input_MyTmp ='D:\Tweaks'
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'TMP', 'REG_SZ', $Input_MyTmp)
;~ 	  RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment', 'TMP', 'REG_SZ', $Input_MyTmp)
	  RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment', 'TMP', 'REG_SZ', $Input_MyTmp)
	  RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Session Manager\Environment', 'TMP', 'REG_SZ', $Input_MyTmp)
	  RegWrite('HKEY_CURRENT_USER\Environment', 'TMP', 'REG_SZ', $Input_MyTmp)


2. Логично ожидать получение следующего результата -пути для:
а) Temp - D:\1
б) Tmp - D:\Tweaks

3. В итоге получаем:
Реестр - все согласно твиков
Панель управления -> Система -> Дополнительно -> Переменные среды - все согласно твиков
Вызов Msgbox (0, '', @TempDir) упорно возвращает D:\Tweaks...

Не понимаю, что я сделал не так???
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
$Input_MyTmp ='D:\Tweaks'

...

RegWrite('HKEY_CURRENT_USER\Environment', 'TMP', 'REG_SZ', GUICtrlRead($Input_MyTmp))

Здесь все нормально?
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
Yashied, прошу прощения за невнимательность. Выдрал из скрипта и наспех слепил пример. В скрипте идет считка из Input. Суть проблемы не изменилась. Шапку откорректировал.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
итак, на настоящий момент выяснил следующее:
1. макрос @TempDir должен отображать путь к папке временных файлов, считанный системой при ее загрузке. Т.е. при изменении в входе сессии пользователем, все равно, отображаются старые значения.
2. при разных путях к Temp и Tmp макрос @TempDir отображает путь к Tmp, игнорируя Temp. Даже после перезагрузки он стандартно отображает путь к Tmp, а не к моей папке временных файлов Temp.

3. Складывается ощущение, что макрос изначально выдает информацию именно по Tmp, а не Temp. Проверить быстро не могу, т.к. у меня изначально винда ставится с одинаковым путем и для Temp и Tmp...

PS Во избежания эффекта "кривых ручек" для задания новых значений Temp и Tmp применял вполне официальную утилиту setenv.exe. Эффект - аналогично эффекту вноса через твики (в шапке).

Если возможно, уважаемые гуру, отпишитесь баг ли это и если нет, то в чем я не прав... :(
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
http://www.infocity.kiev.ua/os/content/osworkrul_15.phtml сказал(а):
TEMP и TMP - переменные, определяющие каталог, в котором программы фирмы Microsoft создают свои временные файлы. Переменная TMP используется старыми приложениями, TEMP - новыми.

Т.ч не думаю что AutoIt проверяет по старому методу, хотя кто его знает.

Код:
ConsoleWrite("@TempDir:	" & @TempDir & @LF)
ConsoleWrite("%Tmp%:		" & EnvGet("Tmp") & @LF)
ConsoleWrite("%Temp%:		" & EnvGet("Temp") & @LF)
ConsoleWrite("Registry Tmp:	" & RegRead("HKEY_CURRENT_USER\Environment", "Tmp") & @LF)
ConsoleWrite("Registry Temp:	" & RegRead("HKEY_CURRENT_USER\Environment", "Temp") & @LF)

Проверяйте.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
AutoIt не использует переменные окружения. Для этого есть специальная функция, и нужно использовать именно ее, а не реестр.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
saavaage
В ScriptOMatic нашел функции:
для переменных:
Код:
; Generated by AutoIt ScriptOMatic

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$OutputTitle = ""
$Output = ""
$OutputTitle &= "Computer: " & $strComputer  & @CRLF
$OutputTitle &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Environment", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
   Local $Object_Flag = 0
   For $objItem In $colItems
      $Object_Flag = 1
      $Output &= "Caption: " & $objItem.Caption & @CRLF
      $Output &= "Description: " & $objItem.Description & @CRLF
      $Output &= "InstallDate: " & WMIDateStringToDate($objItem.InstallDate) & @CRLF
      $Output &= "Name: " & $objItem.Name & @CRLF
      $Output &= "Status: " & $objItem.Status & @CRLF
      $Output &= "SystemVariable: " & $objItem.SystemVariable & @CRLF
      $Output &= "UserName: " & $objItem.UserName & @CRLF
      $Output &= "VariableValue: " & $objItem.VariableValue & @CRLF
      if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
      $Output=""
   Next
  If $Object_Flag = 0 Then Msgbox(1,"WMI Output",$OutputTitle)
Else
   Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_Environment" )
Endif


Func WMIDateStringToDate($dtmDate)
	Return (StringMid($dtmDate, 5, 2) & "/" & _
	StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
	& " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc
и для процессора:
Код:
; Generated by AutoIt ScriptOMatic

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$OutputTitle = ""
$Output = ""
$OutputTitle &= "Computer: " & $strComputer  & @CRLF
$OutputTitle &= "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Processor", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
   Local $Object_Flag = 0
   For $objItem In $colItems
      $Object_Flag = 1
      $Output &= "AddressWidth: " & $objItem.AddressWidth & @CRLF
      $Output &= "Architecture: " & $objItem.Architecture & @CRLF
      $Output &= "Availability: " & $objItem.Availability & @CRLF
      $Output &= "Caption: " & $objItem.Caption & @CRLF
      $Output &= "ConfigManagerErrorCode: " & $objItem.ConfigManagerErrorCode & @CRLF
      $Output &= "ConfigManagerUserConfig: " & $objItem.ConfigManagerUserConfig & @CRLF
      $Output &= "CpuStatus: " & $objItem.CpuStatus & @CRLF
      $Output &= "CreationClassName: " & $objItem.CreationClassName & @CRLF
      $Output &= "CurrentClockSpeed: " & $objItem.CurrentClockSpeed & @CRLF
      $Output &= "CurrentVoltage: " & $objItem.CurrentVoltage & @CRLF
      $Output &= "DataWidth: " & $objItem.DataWidth & @CRLF
      $Output &= "Description: " & $objItem.Description & @CRLF
      $Output &= "DeviceID: " & $objItem.DeviceID & @CRLF
      $Output &= "ErrorCleared: " & $objItem.ErrorCleared & @CRLF
      $Output &= "ErrorDescription: " & $objItem.ErrorDescription & @CRLF
      $Output &= "ExtClock: " & $objItem.ExtClock & @CRLF
      $Output &= "Family: " & $objItem.Family & @CRLF
      $Output &= "InstallDate: " & WMIDateStringToDate($objItem.InstallDate) & @CRLF
      $Output &= "L2CacheSize: " & $objItem.L2CacheSize & @CRLF
      $Output &= "L2CacheSpeed: " & $objItem.L2CacheSpeed & @CRLF
      $Output &= "LastErrorCode: " & $objItem.LastErrorCode & @CRLF
      $Output &= "Level: " & $objItem.Level & @CRLF
      $Output &= "LoadPercentage: " & $objItem.LoadPercentage & @CRLF
      $Output &= "Manufacturer: " & $objItem.Manufacturer & @CRLF
      $Output &= "MaxClockSpeed: " & $objItem.MaxClockSpeed & @CRLF
      $Output &= "Name: " & $objItem.Name & @CRLF
      $Output &= "NumberOfCores: " & $objItem.NumberOfCores & @CRLF
      $Output &= "NumberOfLogicalProcessors: " & $objItem.NumberOfLogicalProcessors & @CRLF
      $Output &= "OtherFamilyDescription: " & $objItem.OtherFamilyDescription & @CRLF
      $Output &= "PNPDeviceID: " & $objItem.PNPDeviceID & @CRLF
      $strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(0)
      $Output &= "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF
      $Output &= "PowerManagementSupported: " & $objItem.PowerManagementSupported & @CRLF
      $Output &= "ProcessorId: " & $objItem.ProcessorId & @CRLF
      $Output &= "ProcessorType: " & $objItem.ProcessorType & @CRLF
      $Output &= "Revision: " & $objItem.Revision & @CRLF
      $Output &= "Role: " & $objItem.Role & @CRLF
      $Output &= "SocketDesignation: " & $objItem.SocketDesignation & @CRLF
      $Output &= "Status: " & $objItem.Status & @CRLF
      $Output &= "StatusInfo: " & $objItem.StatusInfo & @CRLF
      $Output &= "Stepping: " & $objItem.Stepping & @CRLF
      $Output &= "SystemCreationClassName: " & $objItem.SystemCreationClassName & @CRLF
      $Output &= "SystemName: " & $objItem.SystemName & @CRLF
      $Output &= "UniqueId: " & $objItem.UniqueId & @CRLF
      $Output &= "UpgradeMethod: " & $objItem.UpgradeMethod & @CRLF
      $Output &= "Version: " & $objItem.Version & @CRLF
      $Output &= "VoltageCaps: " & $objItem.VoltageCaps & @CRLF
      if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
      $Output=""
   Next
  If $Object_Flag = 0 Then Msgbox(1,"WMI Output",$OutputTitle)
Else
   Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_Processor" )
Endif


Func WMIDateStringToDate($dtmDate)
	Return (StringMid($dtmDate, 5, 2) & "/" & _
	StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
	& " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc
Посмотрите, у меня они работают.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, вот возврат:

@TempDir: C:\Dr
%Tmp%: C:\Dr
%Temp%: C:\Dura
Registry Tmp: C:\Dr
Registry Temp: C:\Dura

Я немного изменил папки, Dr - Tmp, Dura - Temp. Как видите, вывод @TempDir: C:\Dr говорит сам за себя...


Добавлено:
Сообщение автоматически объединено:

madmasles, у меня сработали немного в другом варианте. Спасибо за наводку (Autoit ScriptOmatic Tool рулит!!!)
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
итак, небольшое предварительное резюме:
1. У меня на машине %TempDir возвращает именно Tmp, а не Temp.
2. Самый быстрый и ненапряжный, имхо, вариант получить точные значения Temp и Tmp - взять информацию из реестра. Следует учитывать, что, только что измененные через реестр пути к Tmp и Temp, вступят в силу только после перезагрузки системы.
Пояснение:
EnvGet показывает корректную информацию только после перезагрузки, Реестр - сразу же после изменений, %TempDir - вопрос вообще открыт..
3. использование утилиты setenv.exe позволяет не только оперативно менять пути к Tmp и Temp, но и получать возможность работы с ними в текущей сессии (без перезагрузки системы)

Вывод:
1. оптимально использовать связку Реестр - setenv.exe для изменения и активации путей к Temp и Tmp в режиме online.
2. вопрос по использованию в скриптах %TempDir остается открытым (непонятно куда будет обращаться скрипт, если у юзера Temp и Tmp разведены по разным местам)

Все это имхо. Жду комментарии более старших и мудрых товарищей...
 

SyDr

Сидра
Сообщения
651
Репутация
158
Yashied же уже дал ссылку на описание WinAPI-функции.

Там чётко указано, что функция проверяет следующие переменные окружения и возвращает первую найденную:
1) Путь, указанный в переменной среды TMP
2) Путь, указанный в переменной среды TEMP
3) Путь, указанный в переменной среды USERPROFILE
4) Каталог Windows
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
SyDr , это разве меняет ситуацию с фактической некорректностью возврата @TempDir , если у юзера Temp и Tmp разведены по разным местам?
Теперь, просто есть конкретное подтверждение этому факту. Непонятно только, почему этот факт не отмечен в справке по макрасам...
 

SyDr

Сидра
Сообщения
651
Репутация
158
http://ru.wikipedia.org/wiki/Переменные_среды_Windows
TEMP or TMP системная и локальная Возвращает временные папки, по умолчанию используемые приложениями, которые доступны пользователям, выполнившим вход в систему. Некоторые приложения требуют переменную TEMP, другие — переменную TMP. Потенциально TEMP и TMP могут указывать на разные каталоги, но обычно - совпадают.

При использовании Макроса @TempDir первым проверяется именно значение переменной TMP

А в чём неккоректность возвращаемого значения? TMP ведь также указывает на каталог с временными файлами.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
saavaage сказал(а):
SyDr , это разве меняет ситуацию с фактической некорректностью возврата @TempDir , если у юзера Temp и Tmp разведены по разным местам?
Теперь, просто есть конкретное подтверждение этому факту. Непонятно только, почему этот факт не отмечен в справке по макрасам...

saavaage

Во-первых, то, что у юзера находится в %TEMP% или %TMP%, AutoIt'у, да и всем другим приложениям, по барабану: главное, это то, что возвращает функция GetTempPath(). Windows-приложения, как правило, вызывают эту функцию и используют возвращенный ею путь. AutoIt действует также, т.е. он ни считывает значение из %TEMP% или %TMP%, а использует GetTempPath(). А что именно она возвращает (%TEMP% или %TMP%), это уже на совести Windows, и нас не должно волновать.

Во-вторых, для работы с переменными окружения, тебе не нужно лезть в реестр. В AutoIt есть для этого функции Env... Для того, чтобы обновить переменные без "перелогинивания", нужно послать широковещательное сообщение WM_SETTINGCHANGE, как сказано здесь.

Код:
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>

$tData = DllStructCreate('wchar[12]')
DllStructSetData($tData, 1, 'Environment')
_WinAPI_SendMessageTimeout(-1, 0x001A, 0, DllStructGetPtr($tData), 5000, $SMTO_ABORTIFHUNG)


Или просто вызвать EnvUpdate(), которая делает тоже самое.

Но в Windows Vista/7, это не будет работать (и твоя setenv.exe тоже), так что "перелогиниваться" все равно придется.
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
"А в чём неккоректность возвращаемого значения? TMP ведь также указывает на каталог с временными файлами." - Означает ли это, что если я сначала выгружаю файл в C:\Temp юзеру (выгружает другая программа), а затем хочу "подобрать" его и обработать в autoit через @TempDir, то можно не беспокоиться за результат (даже если на машине Tmp и Temp не совпадают)?. Если да, то тогда часть проблемы снимается..

"Во-вторых, для работы с переменными окружения, тебе не нужно лезть в реестр. В AutoIt есть для этого функции Env" - немного непонятно для каких ветвей она это делает (есть подозрение, что только для пользовательской среды). В setenv.exe можно гибко настраивать варианты отработки

[box title=TitleBox]User environment: setenv -u name value
Machine environment: setenv -m name value
Default user environment: setenv -d name value
Volatile environment: setenv -v name value[/box]


Добавлено:
Сообщение автоматически объединено:


Плюс в EnvSet насторожил такой момент:
"Значения переменных среды, которые устанавливаются внутри скрипта, будут доступны только тем приложениям, которые непосредственно запускаются из AutoIt скрипта командами Run или RunWait. При завершении работы AutoIt эти значения будут утрачены."
Мне необходимо прописать не на время работы данного скрипта, а на постоянной основе в системе. Будет ли эта функция работать в таком случае для всех пользователей машины после перезагрузки системы или добавлении нового пользователя в систему?

Yashied, за EnvUpdate() спасибо, что ткнули. Каюсь, не посмотрел. Сразу начал ковырять setenv.exe и зациклился на ней немного... :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
IMHO, программы должны использовать переменные окружения только в крайнем случае. Путь к любой системной папке можно получить через WinAPI функции (_WinAPI_ShellGetSpecialFolderPath() и _WinAPI_ShellGetKnownFolderPath()), и их нужно использовать. Для поиска файлов также есть функция - _WinAPI_PathSearchAndQualify(). Какие могут быть причины для использования переменных окружения? Кроме того, ведь %TEMP% и %TMP% вообще могут отсутствовать. И что тогда?
 
Автор
S

saavaage

Знающий
Сообщения
171
Репутация
17
Yashied, я теперь так и буду делать. Но если прога сторонняя, а не моя, то ей ведь не прикажешь куда кидать свои файлики... Поэтому я и думал первоначально, что если программа выгружает свои файлы в Temp, то их элементарно можно подхватывать через @TempDir. Теперь я понял, что с этим делом необходимо осторожно обращаться. + Еще стоял вопрос по созданию Temp и Tmp в одной утилите по настройке и там всплыл этот вопрос у одного юзера (он попытался задать разные папки и при обновлении информации в Inputaх получил бред.)

Спасибо, в принципе, основную задачу я этим топиком решил. Тема, имхо, решена и закрыта
 
Верх