2012-11-19 86 views
5

我已經實現了使用參考Reading All Users SessionGet a list of all active sessions in ASP.NET來讀取活動會話的代碼。閱讀用戶會話時出現NULL參考異常(反射)

Private List<String> getOnlineUsers() 
{ 
    List<String> activeSessions = new List<String>(); 
    object obj = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null); 
    object[] obj2 = (object[])obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj); 
    for (int i = 0; i < obj2.Length; i++) 
    { 
     Hashtable c2 = (Hashtable)obj2[i].GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj2[i]); 
     foreach (DictionaryEntry entry in c2) 
     { 
      object o1 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null); 
      if (o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState") 
      { 
       SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(o1); 
       if (sess != null) 
       { 
        if (sess["loggedInUserId"] != null) 
        { 
         activeSessions.Add(sess["loggedInUserId"].ToString()); 
        } 
       } 
      } 
     } 
    } 
    return activeSessions; 
} 

它在本地系統(在Windows XP和Windows 7中)工作正常。雖然我託管在Windows Server 2003(IIS 6版)的應用程序,它提供了在該行

object[] obj2 = (object[])obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj); 

一個空的對象引用錯誤是這樣任何有關與IIS的權限問題或信任級別設置?請讓任何人知道有人遇到過這樣的問題。任何幫助是非常可觀的。

+1

什麼版本的.NET安裝在3個地方?和你的目標是什麼版本? –

+0

Framework 3.5存在於服務器中。 – TechDo

+0

3.5?或3.5 SP1? –

回答

0

這聽起來像.NET的不同版本(或更新)2003年比你有XP/Win7的運行,雖然它也可能僅僅是一個特定於平臺的區別。如果它是權限/信任,你會看到一個異常。相反,它似乎更可能只是:在2003計算機上的任何版本上都不存在_caches。如果您使用反射來訪問私有狀態:你應該完全指望它/版本/更新/平臺之間爆炸/ AT突發奇想等

探討:

  • 檢查是否objnull
  • 檢查obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance)是否null

(無論這些事情可能會導致你舉的這行除外)

+0

好的...我猜可能是這種情況。因爲相同的代碼在其中一個客戶端服務器(MS服務器2003)中工作。 – TechDo

+0

作爲虛擬目錄/網站託管 - 這有什麼關係嗎? – TechDo

+0

@techdo只有這樣回答最後纔會比較......你可能是最適合嘗試的了 –

0

準確地說,您的業務案例是在asp.net中有應用程序狀態變量。它與會話狀態類似,但對所有用戶請求都可見。

1

我知道這是一個古老的線程,但這可能會節省一些時間。另一件要檢查的是obj是System.Web.Caching.CacheMultiple類型。我也遇到了同樣的問題,這是一個與Marc Gravell建議的平臺相關的問題。事實證明,在Windows 2003服務器上,obj的類型是System.Web.Caching.CacheSingle,並且在嘗試獲取「_caches」的值時出現空引用異常。

如果是這樣的話,你仍然可以得到活動會話列表使用(Hashtable)obj.GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj);

1

試試這個,如果_cachesRefs是_caches NULL。下面的函數將返回所有多個版本的Windows和Windows Server的所有用戶會話集合。

它的工作原理。

public List<SessionStateItemCollection> GetAllUserSessions() { 

List<Hashtable> hTables = new List<Hashtable>(); 

PropertyInfo propInfo = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static); 

object CacheInternal = propInfo.GetValue(null, null); 

dynamic fieldInfo = CacheInternal.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance); 

if (fieldInfo != null) { 
    object[] _caches = (object[])fieldInfo.GetValue(CacheInternal); 
    for (int i = 0; i <= _caches.Length - 1; i++) { 
     Hashtable hTable = (Hashtable)_caches(i).GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_caches(i)); 
     hTables.Add(hTable); 
    } 
} else { 
    fieldInfo = CacheInternal.GetType().GetField("_cachesRefs", BindingFlags.NonPublic | BindingFlags.Instance); 
    dynamic cacheRefs = fieldInfo.GetValue(CacheInternal); 
    foreach (void cacheRef_loopVariable in cacheRefs) { 
     cacheRef = cacheRef_loopVariable; 
     dynamic target = cacheRef.Target; 
     fieldInfo = target.GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance); 
     Hashtable hTable = fieldInfo.GetValue(target); 
     hTables.Add(hTable); 
    } 
} 

List<SessionStateItemCollection> sessionlist = new List<SessionStateItemCollection>(); 

foreach (void hTable_loopVariable in hTables) { 
    hTable = hTable_loopVariable; 
    foreach (DictionaryEntry entry in hTable) { 
     object value = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null); 
     if (value.GetType().ToString() == "System.Web.SessionState.InProcSessionState") { 
      SessionStateItemCollection sCollection = (SessionStateItemCollection)value.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value); 
      if (sCollection != null) 
       sessionlist.Add(sCollection); 
     } 
    } 
} 

return sessionlist; 

}

+1

這個例子中的空格在foreach中會變成var(void - > var – dewelloper

3

我已經試過Paully的解決方案,它並沒有在某些方面編譯並導致運行時在別人的錯誤。無論如何,啓發他的建議(非常感謝!我的投票結果是這樣),我來到了我自己的位置,編譯並獲得了預期的數據。

另外,我返回IEnumerable和我使用的「產量回報」,這使得它成爲大名單(種類的數據延遲加載)更performatic。這裏是:

public static System.Collections.Generic.IEnumerable<SessionStateItemCollection> GetAllUserSessions() 
{ 
    List<Hashtable> hTables = new List<Hashtable>(); 
    object obj = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null); 
    dynamic fieldInfo = obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance); 

    //If server uses "_caches" to store session info 
    if (fieldInfo != null) 
    { 
     object[] _caches = (object[])fieldInfo.GetValue(obj); 
     for (int i = 0; i <= _caches.Length - 1; i++) 
     { 
      Hashtable hTable = (Hashtable)_caches[i].GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_caches[i]); 
      hTables.Add(hTable); 
     } 
    } 
    //If server uses "_cachesRefs" to store session info 
    else 
    { 
     fieldInfo = obj.GetType().GetField("_cachesRefs", BindingFlags.NonPublic | BindingFlags.Instance); 
     object[] cacheRefs = fieldInfo.GetValue(obj); 
     for (int i = 0; i <= cacheRefs.Length - 1; i++) 
     { 
      var target = cacheRefs[i].GetType().GetProperty("Target").GetValue(cacheRefs[i], null); 
      Hashtable hTable = (Hashtable)target.GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(target); 
      hTables.Add(hTable); 
     } 
    } 

    foreach (Hashtable hTable in hTables) 
    { 
     foreach (DictionaryEntry entry in hTable) 
     { 
      object o1 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null); 
      if (o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState") 
      { 
       SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(o1); 
       if (sess != null) 
        yield return sess; 
      } 
     } 
    } 
} 
+0

太棒了!是的,我用手輸入並可能有錯別字,祝你好運! – Paully

相關問題