Пользователь Redmon как пользователь не загружает переменные среды пользователя
Я пытаюсь использовать Redmon http://www.winimage.com/misc/redmon/ для отправки заданий на печать в пользовательское приложение C#. Redmon "запускается" (фактически "Диспетчер очереди печати") как SYSTEM, но имеет опцию "Запуск от имени пользователя", позволяющую запускать ваше приложение под пользователем, напечатавшим задание. Проблема в том, что он не загружает среду пользователя. Поэтому вызов функций, таких как Path.GetTempPath(), указывает на \windows\temp вместо пользователя. Также при попытке запустить Outlook 2007+ через вызовы MAPI (для добавления вложений) он сообщает об ошибках формы из-за, я думаю, расположения временной папки.
Есть ли способ "перезагрузить" профиль или, по крайней мере, получить переменные среды в приложении "Олицетворение"? Единственные идеи, которые у меня были до сих пор, - это перестраивать vars непосредственно из реестра, но я хочу избежать этого, так как это является хакерской атакой (избегая деталей реализации и всего такого). Или создание программы-заглушки, которую Redmon вызывает, которая затем правильно запускается как пользователь с полным профилем пользовательского приложения.
Любые другие предметы или хитрости?
2 ответа
Я закончил тем, что нашел способ загрузить EnvironmentBlock пользователя, извлечь каждую переменную и загрузить их в мою существующую среду. На основе кода и идей с нескольких страниц:
- http://nibuthomas.wordpress.com/2007/07/05/some-user-profile-related-functions-which-could-be-useful/
- http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0c0ca087-5e7b-4046-93cb-c7b3e48d0dfb
- Выделение неуправляемого массива строк из PInvoked OpenFileDialog (GetOpenFileName)
Извините мой код C#, любые изменения приветствуются:
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, ref IntPtr TokenHandle);
private const uint TOKEN_QUERY = 0x0008;
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
private static void ReloadEnviroVars()
{
IntPtr hToken = IntPtr.Zero;
IntPtr envBlock = IntPtr.Zero;
//Load this user's environment variables
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, ref hToken);
bool retVal = CreateEnvironmentBlock(ref envBlock, hToken, false);
//Extract each environment variable from the envroblock and add it to
// our running program's environment vars
int offset = 0;
while (true) {
//EnviroBlock is an array of null-terminated unicode strings
IntPtr ptr = new IntPtr(envBlock.ToInt64() + offset);
string Enviro = Marshal.PtrToStringUni(ptr);
offset += Encoding.Unicode.GetByteCount(Enviro) + 2;
if (string.IsNullOrEmpty(Enviro))
break;
string EnviroKey = Enviro.Substring(0, Enviro.IndexOf("="));
string EnviroValue = Enviro.Substring(Enviro.IndexOf("=") + 1, Enviro.Length - 1 - Enviro.IndexOf("="));
Environment.SetEnvironmentVariable(EnviroKey, EnviroValue);
}
CloseHandle(hToken);
}
У меня была такая же проблема на Windows 10.
Я заметил, что если в файле.exe приложения установлен флаг "Запуск от имени администратора", он будет работать как пользовательская система. Снятие этого флажка заставило мое приложение работать с привилегиями пользователя и переменными среды, и это было то, что мне было нужно.