更改.NET中的默認時區(qū)的操作方法
如何更改.NET中的默認時區(qū)?
除了"在操作系統(tǒng)中修改時區(qū)信息,然后重啟.NET應用程序,使其生效"之外。如何在不修改操作系統(tǒng)時區(qū)的前提下,修改.NET中的默認時區(qū)呢?
這是一位 同學兼同事 于5月21日在技術(shù)群里問的問題,我當時簡單地研究了一下,就寫出來了。
現(xiàn)在寫文章分享給大家,雖然我覺得這種需求非常小眾,幾乎不會有人用到。
正文
正常手段下,.NET是不允許開發(fā)者修改默認時區(qū)的,它沒有公開這樣的API。
在 .NET 中,管理時區(qū)的類型叫 TimeZoneInfo,它位于 System 命名空間下,由 System.Private.CoreLib.dll 提供。
使用 ILSpy 反編譯 System.Private.CoreLib.dll,找到 TimeZoneInfo 類型,我們可以看到 TimeZoneInfo.Local 指向一個私有字段 s_cachedData 的成員屬性 Local,該字段類型是一個屬于 TimeZoneInfo 的私有嵌套類型 CachedData。
當首次訪問 CachedData.Local 時,它會先檢查 _localTimeZone 私有字段是否有值。如果沒有值,則調(diào)用 CreateLocal 方法從操作系統(tǒng)獲取時區(qū)信息并且賦值。
看到了這里,我腦海里就浮現(xiàn)了兩種方案:
- 使用
hook技術(shù)挾持并修改win32 api返回的時區(qū)信息。 - 使用
reflection技術(shù)反射并且修改時區(qū)信息。
方案1的優(yōu)點是穩(wěn)定,但可能會被殺毒軟件報毒。
方案2的優(yōu)點是不會報毒,但可能不穩(wěn)定。
為什么說方案2不穩(wěn)定呢?因為 s_cachedData 私有字段值有可能在某個時候被重置。
現(xiàn)在我們來看看方案2的實現(xiàn):
public static bool TrySetLocalTimeZoneInfo(TimeZoneInfo timeZoneInfo)
{
Type timeZoneInfoType = typeof(TimeZoneInfo);
// 獲取TimeZoneInfo類型的私有靜態(tài)字段成員信息s_cachedData
FieldInfo cachedDataFieldInfo = timeZoneInfoType.GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static);
if (cachedDataFieldInfo == null)
{
return false;
}
// 獲取TimeZoneInfo類型的私有嵌套類型CachedData
Type cachedDataType = timeZoneInfoType.GetNestedType("CachedData", BindingFlags.NonPublic);
if (cachedDataType == null)
{
return false;
}
// 獲取CachedData類型的私有字段成員信息_localTimeZone
FieldInfo localTimeZoneFieldInfo = cachedDataType.GetField("_localTimeZone", BindingFlags.NonPublic | BindingFlags.Instance);
if (localTimeZoneFieldInfo == null)
{
return false;
}
// 獲取TimeZoneInfo類型的私有靜態(tài)字段s_cachedData值
object cachedData = cachedDataFieldInfo.GetValue(null);
if (cachedData == null)
{
return false;
}
// 設置私有字段的值
localTimeZoneFieldInfo.SetValue(cachedData, timeZoneInfo);
return true;
}PS: 該方法代碼實際測試在 .NET Core 3.1, .NET 5.0, .NET 6.0, .NET 7.0, .NET 8.0 都可以正常工作。
用法:
void Main()
{
// 設置前
Console.WriteLine(TimeZoneInfo.Local);
// 修改為 GMT 時區(qū)
TimeZoneInfo hkTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
bool setResult = TrySetLocalTimeZoneInfo(hkTimeZoneInfo);
// 設置后
Console.WriteLine(TimeZoneInfo.Local);
}注意:這種方案需要嚴謹測試,反復驗證。
因為是篡改.NET內(nèi)部私有變量,不知道是否會引起其它后果。
比如.NET內(nèi)部其它API沒有使用 TimeZoneInfo.Local,而是自己在其它地方又緩存了一套 TimeZoneInfo,那就GG了。
又比如,需要檢查整個 .NET Runtime 和其它第三方組件,是否有調(diào)用 TimeZoneInfo.ClearCachedData 靜態(tài)方法 或者 調(diào)用 CultureInfo.ClearCachedData 對象方法。
到此這篇關于如何更改.NET中的默認時區(qū)?的文章就介紹到這了,更多相關.NET默認時區(qū)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Asp.net后臺把腳本樣式輸出到head標簽中節(jié)省代碼冗余
最近在學習開發(fā)服務器控件,其它就少不了為控件注冊js和css之類的資源文件,或者直接注冊純腳本樣式。其中就遇到如下問題 1、 注冊的資源文件或純腳本樣式在生成的頁面中都不在head標簽中(當然這個不影響頁面功能) 2、 一個頁面使用多個一樣的控件時,會出現(xiàn)重復輸入(出現(xiàn)多余代碼)2013-02-02
使CheckBoxList的Attributes屬性生效(修改微軟的一個bug)
使CheckBoxList的Attributes屬性生效(修改微軟的一個bug)...2007-08-08
ADO.Net對oracle數(shù)據(jù)庫操作的實例代碼
ADO.Net對oracle數(shù)據(jù)庫操作的實例代碼,需要的朋友可以參考一下2013-06-06
ASP.NET MVC中使用Bundle打包壓縮js和css的方法
這篇文章主要為大家詳細介紹了ASP.NET MVC中使用Bundle打包壓縮js和css的方法,感興趣的小伙伴們可以參考一下2016-05-05
Visual Studio(VS2017)配置C/C++ PostgreSQL9.6.3開發(fā)環(huán)境
這篇文章主要為大家詳細介紹了Visual Studio(VS2017)配置C/C++,PostgreSQL9.6.3開發(fā)環(huán)境,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
asp.net 1.1/ 2.0 中快速實現(xiàn)單點登陸
asp.net 1.1/ 2.0 中快速實現(xiàn)單點登陸...2007-04-04

