2016-01-25 1 views
2
.

У меня возникла проблема с загрузкой текущей папки пользователя Windows при запуске приложения для Windows в разделе «Локальная система». , когда я пытаюсь использовать:C# - Служба Windows Получить текущий зарегистрированный пользователь. Путь к каталогу рабочего стола.

Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 

я получаю пустую строку (я думаю, потому что я бегу службу под «Local System»).

это моя OnStart функция:

protected override void OnStart(string[] args) 
{ 
    System.Diagnostics.Debugger.Launch(); 

    //Get the current user desktop path; 
    string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 
    string filter = "*.*"; 

    // create the watcher. 
    FileSystemWatcher watcher = new FileSystemWatcher(path, filter) 
    { 
     EnableRaisingEvents = true, 
     IncludeSubdirectories = true 

    }; 
    //listen to the change event; 
    watcher.Changed += watcher_Changed; 
    //Thread.Sleep(Timeout.Infinite); 
} 

Есть ли способ, чтобы получить текущий авторизованы окна пути пользователя?

Спасибо.

+1

Что делать, если пользователь не подключен к сети или несколько пользователей? – stuartd

+0

OK Я понимаю вашу точку зрения. так что я должен использовать жесткое кодирование на этом? – Tal

ответ

3

Windows допускает, хотя и не всегда по умолчанию, от нуля до нескольких пользователей, для входа в систему.

Вы должны вызвать три функции:

1) Получить (все) активный сеанс (ы) с WTSEnumerateSessions. Хороший пример звонка в this question. Вы можете использовать «localhost» в качестве параметра servername.

2) Получить токены (для каждой) сессии с помощью WTSQueryUserToken Должно быть прямолинейным, не забывайте об управлении памятью.

3) Запрос SHGetKnownFolderPath с (каждым) токеном. (некоторые соответствующие вырезы из pinvoke.net):

public static readonly Guid Desktop = new Guid("B4BFCC3A-DB2C-424C-B029-7FE99A87C641"); 

public static readonly Guid PublicDesktop = new Guid("C4AA340D-F20F-4863-AFEF-F87EF2E6BA25"); 

IntPtr token = AllWTSQueryUserTokens().First(); // <-- Your implementation 
IntPtr pPath; 
if (SHGetKnownFolderPath(PublicDesktop, 0, token, out pPath) == 0) 
{ 
    string s = System.Runtime.InteropServices.Marshal.PtrToStringUni(pPath); 
    System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath); 
    // s now contains the path for the all-users "Public Desktop" folder 
} 
// Release memory (token)! 

Склеивание эти три вместе довольно мало работы и много управления тестирования и памяти, в качестве упражнения для ОП.

Остерегайтесь caveats with 32bit/64bit registry issues при тестировании вашего решения.

Также вы должны прочитать вопрос this для получения дополнительной информации.

0

Вы можете использовать следующий код из службы, чтобы получить специальную папку, используя любые CSIDL. Вы должны заменить CSIDL_LOCAL_APPDATA на CSIDL_DESKTOPDIRECTORY для каталога на рабочем столе.

Pinvoke.net можно найти, чтобы импортировать методы winapi в C#.

public static String GetUserPath() 
{ 
    var hUserToken = IntPtr.Zero; 
    IntPtr pidlist = IntPtr.Zero; 
    StringBuilder sb = new StringBuilder(MAX_PATH); 

    GetSessionUserToken(ref hUserToken); 
    SHGetFolderLocation(IntPtr.Zero, CSIDL_LOCAL_APPDATA, hUserToken, 0, out pidlist); 
    SHGetPathFromIDListW(pidlist, sb); 

    return sb.ToString(); 
} 

private static bool GetSessionUserToken(ref IntPtr phUserToken) 
{ 
    var bResult = false; 
    var hImpersonationToken = IntPtr.Zero; 
    var activeSessionId = INVALID_SESSION_ID; 
    var pSessionInfo = IntPtr.Zero; 
    var sessionCount = 0; 

    // Get a handle to the user access token for the current active session. 
    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref sessionCount) != 0) 
    { 
     var arrayElementSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); 
     var current = pSessionInfo; 

     for (var i = 0; i < sessionCount; i++) 
     { 
      var si = (WTS_SESSION_INFO)Marshal.PtrToStructure((IntPtr)current, typeof(WTS_SESSION_INFO)); 
      //current = new IntPtr(current.ToInt64() + arrayElementSize); 
      current = (IntPtr)((long)current + arrayElementSize); // should be same as above line 

      if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive) 
      { 
       activeSessionId = si.SessionID; 
      } 
     } 
    } 

    // If enumerating did not work, fall back to the old method 
    if (activeSessionId == INVALID_SESSION_ID) 
    { 
     activeSessionId = WTSGetActiveConsoleSessionId(); 
    } 

    SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 
    sa.nLength = Marshal.SizeOf(sa); 
    if (WTSQueryUserToken(activeSessionId, ref hImpersonationToken) != 0) 
    { 
     // Convert the impersonation token to a primary token 
     bResult = DuplicateTokenEx(
      hImpersonationToken, 
      0, 
      ref sa,//IntPtr.Zero, 
      (int)SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, 
      (int)TOKEN_TYPE.TokenPrimary, 
      ref phUserToken); 

     CloseHandle(hImpersonationToken); 
    } 

    return bResult; 
} 

private const int CSIDL_LOCAL_APPDATA = 0x001c; 
private const int MAX_PATH = 260; 
Смежные вопросы