2010-05-21 166 views
3

我试图使用Redmon http://www.winimage.com/misc/redmon/将打印作业发送到自定义C#应用程序。 Redmon“运行”(实际上是打印后台处理程序)作为SYSTEM,但具有“运行身份用户”选项以允许应用程序在打印作业的用户下运行。问题是它似乎不加载用户的环境。所以调用Path.GetTempPath()等函数指向\ windows \ temp而不是用户的。此外,当试图通过MAPI调用运行Outlook 2007+(添加附件)时,它会报告表单错误,因为我认为它是临时文件夹位置。Redmon的用户运行环境变量不加载用户的环境变量

有没有办法在模拟应用程序中“重新加载”一个配置文件或至少让你的环境变量?我迄今为止唯一的想法是直接从注册表重建变量,但是我想避免这种情况,因为它是一种破解(避免实现细节和所有这些)。或者制作一个存根程序,让Redmon调用这个存根程序,然后以完整的配置文件正确运行用户身份。

任何其他物品或窍门?

回答

7

我最终找到了一种方法来加载用户的EnvironmentBlock,提取每个变量并将它们加载到我现有的环境中。基于代码和理念几页:

请原谅我的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); 
} 
+0

更新的代码使用ToInt64而不是64位系统的ToInt32(超过4gig ram?)。 http://stackoverflow.com/a/1866268报告说,它只会在32位系统上使用更多的开销,但会起作用。 – Halfdone 2013-02-01 16:50:01